XFIAT API v1 - plain text reference Base: https://xfiat.app/api/v1 Docs: https://xfiat.app/api/docs/ WHAT IT DOES Crypto to bank. The payer sends crypto; Xfiat converts it and pays a bank account. Coins: USDT USDC BTC ETH BNB received directly, plus many other coins converted on the way in (LTC, SOL, DOGE ...). One list: GET /assets. Payout: NGN. KEYS sk_test_... / sk_live_... secret, server only. Header: Authorization: Bearer sk_... pk_test_... / pk_live_... public, payment links only. Test and live data never mix. REPLY SHAPE {"ok":true,"data":{...},"request_id":"req_..."} {"ok":false,"error":{"code":"...","message":"...","field":"..."},"request_id":"req_..."} JSON only, max 32 KB. Amounts are strings. Times are UTC ISO 8601. ENDPOINTS GET /ping no key GET /account status, live, verification, payout bank, fee_percent, limits, 24h usage GET /assets?payout_currency=NGN[&coin=LTC][&search=doge] all coins in one list: networks, min_amount, memo_required (converted coins priced with ?coin=) GET /banks?currency=NGN [{code,name}] POST /banks/resolve {bank_code, account_number, currency?} -> account_name POST /quotes {coin, network?, payout_currency?, crypto_amount | payout_amount} -> both amounts, rate, min/max_crypto_amount POST /payments Idempotency-Key {coin, network?, payout_currency?, payout_amount | crypto_amount, bank?{bank_code, account_number} | "default", reference?, metadata?} GET /payments?limit&status&reference&starting_after GET /payments/{id} POST /payments/{id}/cancel only while awaiting_payment POST /checkouts Idempotency-Key {payout_amount, payout_currency?, coins?[], reference?, description?, success_url?, cancel_url?} -> url GET /checkouts/{id} GET /events?limit POST /webhooks/test POST /test/payments/{id}/simulate test keys only. {status: confirming|processing|completed|needs_review|expired|failed} PAYMENT LINK (no code) GET /api/v1/pay/?key=pk_live_...&amount=50000[&reference=INV-1][&description=..][&coins=USDT,BTC][&success_url=..][&cancel_url=..] Opens the hosted page. Pays the account's registered bank. Same reference = same page. No coins = every coin (search box). PAYMENT FIELDS id, mode, status, coin, network, network_name, deposit_address, memo, crypto_amount, crypto_received, payout{currency, amount_estimate, amount, bank{bank_code, bank_name, account_name, account_number_last4}}, reference, metadata, checkout_id, expires_at, completed_at, created_at, updated_at STATUSES awaiting_payment -> confirming -> processing -> completed awaiting_payment -> expired | cancelled (a late payment still completes) processing -> needs_review -> completed any -> failed (rare) RULES reference: unique per account and mode; letters digits . _ : / # - ; max 80. Idempotency-Key: required on POST /payments and /checkouts; 8-80 chars; same key + same body = same reply; other body = 409. Payer sends exactly crypto_amount of coin on network before expires_at (1 hour), plus memo when set. network is required for a converted coin with more than one network. WEBHOOKS POST to your https address. Header Xfiat-Signature: t=TS,v1=HEX HEX = hex(HMAC_SHA256(webhook_secret, TS + "." + raw_body)). Reject if |now - TS| > 300. Reply 2xx within 8 s. Retries: 1m 5m 15m 1h 3h 6h 12h 24h. Deduplicate by event id. Events: payment.created .confirming .processing .completed .needs_review .expired .cancelled .failed, webhook.test SIGNED REQUESTS (if required on your account) X-Xfiat-Timestamp: TS X-Xfiat-Signature: hex(HMAC_SHA256(signing_secret, TS + "." + METHOD + "." + path_after_v1 + "." + body)) within 300 s LIMITS (usual; yours in GET /account) 60 calls/min, 10000/day, 10 new payments/min, $2-$2000 per payment, $10000 and 200 payments per 24h, 100 open payments. Headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. 429 -> wait Retry-After. ERRORS 400 invalid_request | 401 unauthorized | 403 forbidden, live_not_enabled, kyc_required, account_suspended | 404 not_found 409 conflict | 413 payload_too_large | 415 unsupported_media_type | 422 limit_exceeded | 429 rate_limited 500 server_error | 503 service_unavailable, rate_unavailable, endpoint_disabled