Skip to content

Transfers & FX Conversion

These endpoints are authenticated with your API Key (X-API-Key header).
Base URL: https://rach-caas-api-dx75yvdhaq-nw.a.run.app


Get FX Conversion Quote

Returns a locked exchange rate for converting any local fiat currency to USDC. The returned quote_id must be passed to POST /v1/transfers/send for fiat-denominated transfers.

Quotes expire in 60 seconds — check expires_at before use.

For direct crypto-to-crypto transfers without FX conversion, use the DIRECT_CRYPTO:{TOKEN}:{AMOUNT} format as the quote_id instead (e.g. DIRECT_CRYPTO:USDC:10.50).

POST /v1/fx/quote

Request

http
POST /v1/fx/quote
X-API-Key: rach_sk_live_xxxxxxxxxxxxxxxx
Content-Type: application/json

{
  "local_currency": "XOF",
  "fiat_amount": 20000,
  "target_token": "USDC"
}
FieldTypeRequiredDescription
local_currencystringISO 4217 currency code (e.g. "XOF", "NGN", "KES", "GHS", "EUR", "USD")
fiat_amountnumberAmount in local currency (e.g. 20000)
target_tokenstringDefaults to "USDC"

Response 200 OK

json
{
  "quote_id": "fx_b3d8a1c2-4f5e-6789-abcd-ef0123456789",
  "currency_pair": "XOF_USDC",
  "fiat_amount": "20000.00",
  "rate": "560.77",
  "expected_out": "35.67",
  "target_token": "USDC",
  "expires_at": "2026-06-25T12:01:05Z"
}
FieldDescription
quote_idLocked rate token — pass this to /v1/transfers/send
currency_pairTrading pair (e.g. XOF_USDC, NGN_USDC, KES_USDC)
rateLocal currency units per USDC at lock time
expected_outUSDC amount the recipient will receive
expires_atISO 8601 timestamp — quote invalid after this

Error Codes

StatusMeaning
400Invalid currency or missing fields
401Invalid or missing API key
500FX engine error or unsupported trading pair

Send Instant On-Chain Transfer

Moves USDC between two customer SCWs on Polygon PoS via an ERC-4337 UserOperation. Settlement is on-chain and final within seconds — no banks, no correspondents, no cut-off times.

Both sender and recipient must be provisioned users under your tenant.

AML daily/monthly limits apply per sender. Exceeding them returns 429.

POST /v1/transfers/send

Request — With FX Quote

http
POST /v1/transfers/send
X-API-Key: rach_sk_live_xxxxxxxxxxxxxxxx
Content-Type: application/json

{
  "sender_phone": "+2250700000001",
  "recipient_phone": "+2250700000002",
  "quote_id": "fx_b3d8a1c2-4f5e-6789-abcd-ef0123456789",
  "local_fiat_amount": "5500.00",
  "target_token": "USDC",
  "idempotency_key": "txn_ref_abc123"
}

Request — Direct Crypto (No FX)

http
POST /v1/transfers/send
X-API-Key: rach_sk_live_xxxxxxxxxxxxxxxx
Content-Type: application/json

{
  "sender_phone": "+2250700000001",
  "recipient_phone": "+2250700000002",
  "quote_id": "DIRECT_CRYPTO:USDC:10.50",
  "local_fiat_amount": "10.50",
  "target_token": "USDC",
  "idempotency_key": "txn_ref_direct_001"
}
FieldTypeRequiredDescription
sender_phonestringSender's E.164 phone number
recipient_phonestringRecipient's E.164 phone number
quote_idstringFrom POST /v1/fx/quote, or DIRECT_CRYPTO:USDC:{amount}
local_fiat_amountstringOriginal fiat amount (for audit/ledger)
target_tokenstring"USDC" or "USDT"
idempotency_keystringYour unique reference — prevents duplicate UserOps

Response 202 Accepted

json
{
  "transfer_id": "txn_abc123xyz",
  "status": "QUEUED",
  "message": "Transfer queued for on-chain submission",
  "created_at": "2026-06-25T12:05:00Z"
}

Transfer lifecycle: QUEUEDSUBMITTEDSETTLED

Monitor progress via GET /v1/dashboard/transfers/{id}

Error Codes

StatusMeaning
400Invalid payload or expired FX quote
401Invalid or missing API key
404Sender or recipient wallet not provisioned
409Duplicate idempotency_key
410FX quote expired (>60 seconds since quote was issued)
429AML block: daily or monthly sending limit exceeded

Transfer Flow

┌─────────────────────────────────────────────────┐
│  1. POST /v1/fx/quote                           │
│     → Receive locked quote_id (60s TTL)         │
└────────────────────────┬────────────────────────┘


┌─────────────────────────────────────────────────┐
│  2. POST /v1/transfers/send (with quote_id)     │
│     → Transfer queued (QUEUED)                  │
│     → ERC-4337 UserOp submitted (SUBMITTED)     │
│     → On-chain settlement (SETTLED)             │
└─────────────────────────────────────────────────┘

For very time-sensitive flows, you can pre-fetch a quote speculatively and pass it immediately when the user confirms. Quotes are valid for 60 seconds from issuance.


AML Limits

Rach CaaS enforces per-sender AML velocity controls. If a sender exceeds their daily or monthly USDC transfer limit, the transfer returns HTTP 429. Contact support@rach.finance to adjust limits for your use case.

Rach Payments API