Skip to content

JET API

JET is a cross-border payment rail for regulated businesses. You send a stablecoin amount; your recipient is paid in their local currency, through a licensed local payout channel in the destination country.

The pattern is sometimes called a stablecoin sandwich: value moves in as fiat or stablecoin, travels across borders as a stablecoin, and lands as local fiat. The recipient never holds, receives, or needs to know about a stablecoin.

Info

JET is a business-to-business rail. You keep the relationship with your end users and you own their KYC. JET verifies you (KYB) and provides the corridor.

What you can do with it

Price a payment Get a firm, rate-locked quote before committing to anything.
Send a payment One authenticated call starts a durable payment that runs to completion on its own.
Send a batch Up to 1,000 payments in one instruction, funded in a single transfer.
Fund your balance Wire EUR or USD, pay BRL by PIX, or send USDC on chain.
Take money out Withdraw USDC to your own wallet, or off-ramp to a bank account.
Track it Poll a status endpoint, or receive signed webhooks on every state change.
Manage recipients Save payees once, reuse them across payments.
Manage your team Invite colleagues, assign roles, rotate your API key.
Reconcile Pull a per-period statement of what you sent and what it cost.

The shortest possible example

curl -X POST "$JET_API/transactions" \
  -H "Authorization: Bearer $JET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "idempotencyKey": "pay-2026-08-21-0001",
    "corridor": { "to": "VND", "destinationCountry": "VN" },
    "sendAmount": { "amount": "1000.00", "currency": "USDC" },
    "recipientReference": "customer-4471",
    "beneficiary": { "name": "NGUYEN VAN A", "account": "0123456789", "bic": "BFTVVNVX", "country": "VN" }
  }'
{ "transactionId": "pay-2026-08-21-0001", "status": "accepted" }

That 202 Accepted means the payment is now running as a durable process on our side. It will keep going (retrying providers, posting to our ledger, and, if something goes wrong, unwinding itself) whether or not your process is still alive. You find out how it ended by polling or by webhook.

Design principles you will notice

These are worth knowing up front, because they explain choices that might otherwise look strange.

Amounts are never JSON numbers. You send decimal strings; we return integer minor units. A JSON number cannot carry a 6-decimal stablecoin amount without losing precision, and losing precision on money is not an acceptable failure mode. See Amounts and currencies.

Every money-moving call is idempotent, and the key is the ID. Your idempotencyKey becomes the transaction ID. Retry the same call as often as you like; you get one payment. See Idempotency.

We fail closed and we never fake success. If a feature is not wired up on your environment, the endpoint returns 501 with a machine-readable reason: not an empty list, not a plausible-looking stub. If we cannot tell whether funds moved, the payment goes to IN_DOUBT and is reconciled rather than optimistically marked complete.

The API tells you what it can do. GET /capabilities returns the live corridors and the status of every feature, so you can build against what is actually available instead of hard-coding assumptions.

Where to go next