What Wyra Rails is
Wyra Rails is a way to show Wyra's catalog — prepaid top-ups, travel eSIM and digital gift cards, with real prices already attached — directly on your own site, app or tool, with checkout included. You paste a widget (or call our API directly, if you have your own backend), your customer buys without leaving your page, and Wyra handles everything else: the payment (Wyra is the registered merchant on every sale, always — never you), compliance (including sanctioned-country restrictions), product delivery, and your commission.
Today Wyra Rails is an embeddable widget + API tier: the checkout and the emails your customer receives carry Wyra's brand. It is, deliberately, the first step toward a fully white-label API — where those same emails, and potentially checkout itself, carry your own brand. That version isn't built yet. This isn't an empty promise: it's a real, production foundation that the next version gets built on — and section 10 tells you exactly what's missing and how you get there.
How it works, step by step
From your first visit to your first payout, here's the full path:
- You create your account, for free.On the partner portal, with Google, Apple, or your email plus a one-time code — no password. A Wyra Rails account is, under the hood, the same identity as a Wyra affiliate: if you already have an account (affiliate, top-ups, eSIM), you log in and activate Rails in one step.
- You get your keys instantly.A public key (safe to paste in the browser) and a secret key (for your own backend only, never in JavaScript). You can have several of each type — test or live — and rotate them whenever you want from your dashboard.
- Wyra sets your margin.10% over our normal price by default — configurable by Wyra up to a 30% ceiling, so the final price stays competitive for your customer. Today Wyra sets the number on your account (it's not a field you edit yourself from the dashboard); if you want to request an adjustment, write to us.
- You paste the widget — or call the API.For most sites (WordPress, Wix, Squarespace, or your own code) one
<div>plus one<script>is enough. If you have your own backend, you can skip the widget and call the same REST endpoints directly with your secret key — see the technical specification. - Wyra reviews your account before real money moves.A brand-new key can read the catalog (real, live prices) immediately — that's read-only, zero risk. But creating a real payment session requires Wyra to activate your account for live mode, a manual review, usually 1-2 business days.
- Your customer buys without leaving your site.They see the final price, no surprises, fill in their details, and get redirected — inside the same tab — to a secure payment page run by Stripe, under Wyra's name. When they're done, they're sent automatically back to your site.
- Wyra delivers the product.Using the exact same system that already delivers every top-up, eSIM and gift card Wyra sells today — nothing new, nothing different, for a sale that came through your widget.
- Your commission accrues, visible in real time.100% of the margin you added gets credited to you the moment the payment is confirmed, with a waiting period (the refund window) before it's available for withdrawal — see the earnings section.
- You get paid.Via Stripe Connect — the same payout system Wyra's affiliates already use. Wyra never sees your banking details.
What it looks like in your business
The widget, embedded in your site: a compact box that adopts your brand's accent color (you set it with a single attribute). It shows tabs per product (Recargas / eSIM / Gift cards, or only the one you enable), a country search, and a price list where the big number — what your customer actually pays, your margin already included — is the headline. Tapping an item opens the purchase form, with that same final price. Below it, a small "Powered by Wyra" credit — not removable at this tier, the same pattern Stripe Checkout and other payment platforms use on their free/low-cost plan.
The purchase, from your customer's side: they fill in their email (and the product detail — the number to top up, for example), tap "Buy," and an invisible anti-bot check resolves in the background without asking them anything. Right after, they're redirected — in the same tab, no new window — to a real payment page, run by Stripe, with Wyra Technologies' name on the card statement. There they enter their card (or Apple Pay / Google Pay, if the browser offers it) on Stripe's standard interface — that screen never carries your brand, deliberately: it's the proof that Wyra, not you, is the one charging. On confirmation, Stripe redirects them back to your own site, to whatever success page you set.
What kinds of businesses it's built for
Wyra Rails isn't "for everyone" — it's built for businesses that already have their own audience and want to sell them something more, without building payments infrastructure or negotiating with wholesale suppliers:
And, being just as honest about who it's not the best fit for today: if you need checkout and your customer's emails to carry your brand end to end, that version (full white-label) isn't built yet — see section 10. And if your business doesn't have any audience of its own yet, the affiliate program (share a link, no site required) is usually a better starting point than Wyra Rails.
Regulatory specifications
None. You don't need a money-transmitter license, an MSB (Money Services Business) registration, or any kind of payments account or regulated entity of your own to sell through Wyra Rails.
This is possible because Wyra — not you — is always the registered merchant on every sale. Wyra operates under the FinCEN closed-loop prepaid exemption (31 CFR 1010.100): the balance that gets delivered (minutes, data, a gift card code) isn't money that's transferable or redeemable for cash, so the activity doesn't qualify as money transmission under that framework. Your customer pays Wyra directly through Stripe; you never process the payment, never have access to the funds, and are never part of the money's chain of custody.
Earnings and payouts
The math, with a real example
Your margin is added on top of the Wyra price — the same price it already charges on its own site. It's purely additional, and 100% of it is yours.
Your commission doesn't subtract anything from Wyra's own economics on that sale — it exists only because your traffic exists.
What never changes, no matter what
- $0 upfront. There's no cost to create your account, no monthly fee, no sales minimum. It's pure pay-for-performance: you earn when your customer buys, and nothing before that.
- Your commission is automatically reversed if the sale is reversed. If a sale is refunded or disputed (chargeback), your commission is reversed automatically — the same mechanism Wyra's affiliate program already uses, triggered by the same webhook that processes every Wyra refund, regardless of whether the sale came from your widget or from wyraapp.com directly. You never get paid on a sale that doesn't stick.
- Margin set by Wyra, not self-service. The percentage you add (10% by default, up to 30%) is set by Wyra on your account — it's not a slider you edit yourself today from the dashboard.
When and how you get paid
Every sale attributed to your account is recorded as a "pending" commission the moment the payment is confirmed. Before it's available for withdrawal, it passes through two real filters, not cosmetic ones:
- Refund window (~30 days).Your commission moves from "pending" to "available" only once that sale's refund window closes — the same waiting period that already protects Wyra's affiliate program. It's not an arbitrary delay: it's the standard time frame in which a refund or a chargeback could still land.
- Minimum payout: $25.You can withdraw your available balance once it reaches $25 — the same threshold Wyra's affiliates already use today, via Stripe Connect. Wyra never sees your banking details; Stripe handles that directly with you.
- Manual approval before money moves.Every payout batch goes through a human review at Wyra before the transfer executes — today that's the same for any amount. Wyra's intent is for noticeably large withdrawals to get a closer look before they're released (it gives Stripe's own settlement period time to finish settling, reducing the risk of paying you a commission right before a late refund lands) — but today that's manual judgment inside that same review, not an automatic "bigger amount = longer wait" formula coded into the system yet.
Installation and technical specification
This section is the complete reference — authentication, endpoints, exact request/response shapes, and error codes. If you're integrating (or if you're a coding assistant reading this on a human's behalf), this is everything you need.
The bare minimum to get started
<!-- Everything you need to paste into your site --> <div id="wyra-rails" data-wyra-pubkey="wr_pub_live_YOUR_KEY"></div> <script src="https://wyraapp.com/rails/widget.js" async></script>
Widget attributes (data-wyra-*)
| Attribute | Required | Values | Default |
|---|---|---|---|
data-wyra-pubkey | Yes | wr_pub_live_… / wr_pub_test_… | — |
data-wyra-product | No | esim · recargas · giftcard · all | all (with a tab selector) |
data-wyra-country | No | ISO-2, e.g. MX | none — your customer searches |
data-wyra-lang | No | es · en · pt | your page's <html lang>, or es |
data-wyra-theme | No | light · dark · auto | light |
data-wyra-accent | No | any CSS color (#hex, rgb(), name) | Wyra cyan |
data-wyra-success-url | No | absolute URL on your own domain | the current page |
data-wyra-cancel-url | No | absolute URL on your own domain | the current page |
A success_url / cancel_url that doesn't point to a domain you registered on your account is silently ignored and falls back to a generic Wyra page — that's a real protection: a leaked public key can't be used to redirect a customer who just paid to an arbitrary site.
Authentication
Two key types, with very different exposure rules:
wr_pub_…Safe to paste in the browser. It's what the widget carries. Can only read the catalog and create a payment session (never read another customer's data).wr_sec_…For your own backend only. Never put it in browser-side JavaScript.Send your key as the x-rails-key header (recommended — works in any environment, including low-code builders where the Authorization header is awkward to set), or as Authorization: Bearer <your-key>.
If you're calling from your own backend (without the widget), you don't need anything else:
Authorization: Bearer wr_sec_live_YOUR_SECRET_KEYIf you're calling from the browser with the widget, two auth layers travel together — the widget already handles them for you, you don't have to build them by hand: Supabase's public pair (Wyra's, not yours) plus your own key:
apikey: <Wyra's public anon key — widget.js supplies it> Authorization: Bearer <the same anon key> x-rails-key: wr_pub_live_YOUR_PUBLIC_KEY
test key authenticates and can read the catalog with no problem (useful for testing your visual integration with real prices). But creating a payment session with a test key is rejected today with test_mode_not_supported — there isn't yet a separate Stripe sandbox environment to simulate a charge without actually moving it. To test checkout end to end you need a live key already approved by Wyra.Catalog — GET /rails?action=catalog
Base: https://owvktacuqmlymszkrwxv.supabase.co/functions/v1/rails. Pure read, no side effects — any active key (public or secret, live or test) can call it. The prices it returns already include your margin (partner_price_usd); it never exposes Wyra's wholesale cost.
GET /rails?action=catalog&product=recargas&country=MX{
"product": "recargas", "country": "MX",
"operators": [{
"wyra_operator_id": 100234,
"operator_name": "Telcel Mexico",
"is_bundle": false,
"logo_url": "https://.../telcel.png",
"brackets": [{
"bracket_id": 3,
"wyra_retail_usd": 20.65,
"partner_price_usd": 22.72,
"markup_usd": 2.07,
"local_amount": 350, "currency_delivered": "MXN",
"denomination_type": "fixed",
"product_label": "$350 MXN top-up",
"validity": null, "benefits": null
}]
}]
}Illustrative example with the real field shape — a country carries several operators, each with several denominations (brackets).
GET /rails?action=catalog&product=esim&country_code=ES{
"product": "esim", "country_code": "ES",
"packages": [{
"package_id": "6b6f6e5b-…", "name": "Spain 20GB 30 days",
"country_code": "ES", "data_quantity": 20, "data_unit": "GB",
"validity": 30, "validity_unit": "days", "unlimited": false,
"wyra_retail_usd": 23.99, "partner_price_usd": 26.39, "markup_usd": 2.40
}],
"truncated": false
}GET /rails?action=catalog&product=giftcard&country_iso=US&brand=amazon{
"product": "giftcard", "country_iso": "US",
"cards": [{
"catalog_id": "b21e4b0e-…", "brand": "Amazon", "category": "retail",
"country_iso": "US", "face_value": 25, "face_currency": "USD",
"logo_url": "https://.../amazon.png",
"wyra_retail_usd": 25.00, "partner_price_usd": 27.50, "markup_usd": 2.50
}],
"truncated": false
}The gift-card catalog only includes brands whose source channel is already validated on Wyra's side — the same safety filter Wyra's own store uses, not a different one for Rails.
Checkout — POST /rails?action=checkout-session
Creates the real payment session (a Stripe Checkout Session, on Wyra's account) and its associated pending order. Requires a live key and an account already approved for live mode.
POST /rails?action=checkout-session { "product": "recargas", "customer_email": "customer@email.com", "wyra_operator_id": 100234, "bracket_id": 3, "country_iso": "MX", "recipient_phone": "5215512345678", "operator_name": "Telcel Mexico", "turnstile_token": "…", // only required with a public key (browser) "success_url": "https://yourbusiness.com/thanks", "cancel_url": "https://yourbusiness.com/recargas" }
| Product | Product-specific body fields |
|---|---|
recargas | wyra_operator_id, bracket_id, country_iso, recipient_phone, operator_name (optional) |
esim | package_id |
giftcard | catalog_id |
Common to all three: product, customer_email, and optionally turnstile_token (required only when calling with a public key from the browser — the widget resolves it on its own), success_url, cancel_url.
{
"checkout_url": "https://checkout.stripe.com/c/pay/cs_live_…",
"transaction_id": "b0e21c4a-…", // esim returns "order_id" instead
"wyra_retail_usd": 20.65, "markup_usd": 2.07, "partner_price_usd": 22.72
}A 200 is the success signal — redirect to checkout_url (same tab). Only error responses carry success:false.
{
"ok": false, "success": false,
"error_code": "destination_not_supported",
"error": "Destination country not supported",
"message": "Destination country not supported"
}Most common error codes
| error_code | Status | What it means |
|---|---|---|
invalid_api_key | 401 | Key missing, mistyped, or revoked. |
rate_limited | 429 | You went over the request limit — see below. |
product_not_enabled | 403 | Your account doesn't have that product enabled. |
rails_not_live | 403 | Your account (or the system in general) isn't approved for real checkout yet. |
test_mode_not_supported | 403 | You tried to create a checkout with a test key — not possible today, see above. |
captcha_failed | 403 | The anti-bot check (Turnstile) didn't resolve — only applies to public keys. |
destination_not_supported | 403 | Sanctioned / non-sellable destination country — the same block that applies on wyraapp.com. |
missing_fields | 400 | Required fields are missing — listed in error_params.fields. |
invalid_phone | 400 | The destination number doesn't have the expected length for that country. |
bracket_unavailable | 404 | That specific denomination is no longer available — request the catalog again. |
esim_package_wrong_type | 409 | That eSIM package is outside v1 scope (not "data-only, single country"). |
limit_exceeded_… | 403 | The amount exceeds the end customer's compliance limits. |
disposable_email_not_allowed | 400 | The customer's email is from a blocked disposable-email domain. |
upstream_error | 502 | Stripe couldn't create the session — retry. |
service_temporarily_unavailable | 503 | A Wyra infrastructure hiccup — retry, never permanent. |
Usage limits
| Scope | Per minute | Per day |
|---|---|---|
| Catalog, per key | 120 | 20,000 |
| Checkout, per key | 30 | 2,000 |
| Checkout, per IP (extra layer, any key) | 4 | 15 per hour |
The per-IP layer uses the same mechanism that protects recargas, eSIM and gift cards on wyraapp.com, but with its own dedicated Rails quota — a checkout on your site doesn't eat into another Wyra product's quota from that same IP, or the other way around.
A hiccup on Wyra's infrastructure never blocks your integration by mistake: these limits fail "open" — if something internal doesn't respond, your request goes through instead of being rejected.
catalog to show prices and checkout-session when your customer confirms, with your secret key from your own server. You don't need to use widget.js at all.Who Wyra is
Wyra Technologies LLC already operates three real product lines, live, sold directly to the Latino diaspora in the United States at wyraapp.com: prepaid top-ups to 140+ countries, travel eSIM, and digital gift cards. Wyra Rails isn't a separate experiment — it's the same infrastructure that already charges, already delivers, and already complies, extended so you can use it too. When your widget shows a price, it's the same pricing engine that runs on Wyra's own store; when your customer buys, it's the same Stripe webhook and the same delivery systems that already process every Wyra sale today.
That same legal structure — the FinCEN closed-loop prepaid exemption — is what makes it possible for Wyra Rails to require no license from you (see section 5).
Speed
There's no separate, slower path for a sale that comes through Rails. The catalog is read from the exact same curated pricing tables wyraapp.com itself queries — there's no separate, potentially stale "partner price feed." Checkout is a real Stripe Checkout session, the same single-redirect flow Wyra already uses today for every top-up, eSIM and gift card it sells directly. And delivery — the confirmation SMS, the eSIM QR code, the gift-card code — runs through the exact same webhooks that already serve Wyra's live customers, unmodified, without putting a Rails sale in a separate queue or treating it as second-class.
We deliberately don't publish a millisecond figure here: we'd rather describe the real architecture (the same one already in production, serving real traffic) than invent a number we couldn't stand behind under every network condition.
The road to full white-label
Being honest about where this stands: today, the emails a partner's customer receives (the purchase receipt, the eSIM QR code, the gift-card code) go out under Wyra's brand — not yours. That's the current phase, not the final version. The fully white-label version (emails under your own brand, and potentially a checkout with your own visual identity) is on the roadmap, but isn't built yet.
There are two real paths to unlock it — and both are current Wyra policy, not a fixed guarantee forever:
Sustaining real sales volume — today Wyra's benchmark is around $1,000/month in Wyra price, for two consecutive months — shows it's worth building the per-partner branding work, and Wyra prioritizes it for your account.
If you want to unlock it before proving that volume on your own, you can fund the build with an upfront setup fee — today Wyra's benchmark is between $250 and $1,000, depending on the scope of what you need.
Neither is a contractual promise set in stone — they're Wyra's current intent, and the exact amounts can be adjusted. If either path interests you, write to us at support@wyraapp.com and we'll talk through your specific case.
A hosted page, for a physical location with no website
This is different from the embeddable widget described in the sections above, and different from the white-label roadmap in section 10 — it's a third, narrower option, built for one specific case: a business that has no website of its own to paste a widget onto — a kiosk, a remittance counter, a tablet standing on a counter waiting for a customer to tap the screen.
For that case, instead of asking you to build a site first, Wyra can host a page for you — same catalog, same checkout, without writing a single line of code — and you point your tablet's or counter's browser at that URL. Request it from your dashboard once your Rails account is active, and today it's free.