Integration guide — local fiat ↔ stablecoin
One corridor pattern for both directions. Only a few quote fields change per market and asset. Based on existing repo docs / OpenAPI — seeKNOWN_GAPS.md for unknowns.
Product: corridor quote → accept (POST /partner/orders/quote → POST /partner/orders/{quote_id}/accept → order.settled).Not this guide: ledger
…/conversions (fiat↔fiat banking) — see customers/conversions.mdx.
Directions (same endpoints)
Always discover
network_id with the same country + order_type as the quote (GET /partner/catalog or GET /partner/payment-methods). Provider lists differ by direction.
What changes between corridors
Field hints:
GET /partner/order-requirements?country=…¤cy=…&order_type=…. Playbooks: corridors/kenya.mdx, corridors/nigeria.mdx, corridors/uganda.mdx, corridors/overview.mdx.
Stablecoin assets (documented)
Same addresses on sandbox and production. Prefer Base USDC unless QA confirms USDT for your corridor (
corridors/overview.mdx). KE OffRamp sandbox samples often use Polygon USDT.
How the rate is quoted and locked
Quote fields to show / store
TTL in seconds: not a fixed published constant — honor
expires_at. TODO: KNOWN_GAPS.md.
Indicative rates are not binding and not ledger-pair FX.
Worked examples (same shape)
OnRamp — local amount → USDC (KE momo sandbox)
country / currency / phone / network_id for other OnRamp markets (e.g. NG bank + BVN — see corridors/nigeria.mdx). Success/failure sandbox identities: sandbox/success-failure.mdx.
OffRamp — USDT/USDC → local fiat (same accept path)
Checklist fromorders/quote-and-accept.mdx:
Sandbox: do not settle by sending testnet crypto — include
Successful in retail customer.name (or institution business_name) so the crypto leg auto-credits (sandbox/success-failure.mdx, corridors/kenya.mdx).Production: after accept, customer sends the exact crypto amount to
payment_instructions.crypto_deposit before that address’s expires_at. Deposit address is per order — do not reuse.
Accept is identical for both directions:
What ID to store for reconciliation
Prefer
order_id as the ledger journal external reference.
When funds are final
Backup poll:
GET /partner/orders/{order_id}.
Fees and currency codes
- Fiat: ISO 4217 from catalog (
KES,NGN, …). - Crypto:
USDC/USDTas in the asset table. - Fee fields on quote:
amounts.fees.service_fee_local,amounts.fees.service_fee_usd. - Static fee schedule / BPS: not in this repo — use per-quote
fees. TODO:KNOWN_GAPS.md.
Stablecoin minor-unit ledgers
API examples return decimal crypto amounts (e.g.5.95), not integer minor units.
Integrator convention (your system):
amount_fiat / user_pays (or non-binding indicative rates for marketing only). Never replace the locked quote rate for checkout confirmation. Credit/debit from the settled webhook amounts, not a re-fetched indicative rate.
Minimal settled handler sketch
asset.currency / network with order_id at accept time — settled webhook examples emphasize fiat currency and amount_crypto, not always a full asset object (KNOWN_GAPS.md if you need a richer schema).
Related OpenAPI operations
GET /partner/catalog·GET /partner/payment-methods·GET /partner/order-requirementsPOST /partner/orders/quote·POST /partner/orders/{quote_id}/accept·GET /partner/orders/{order_id}GET /partner/rates/indicativewebhooks.partnerEvent(outbound)
agents.md.