Appearance
Textile FX API v2 · Ramp
The Ramp API moves fiat in and out of the stablecoins Textile FX trades. A buy takes a bank transfer in local currency and delivers the stablecoin to a wallet. A sell takes the stablecoin from a wallet and pays local currency to a bank account. Today that is NGN ↔ cNGN.
Textile does not hold the money. A licensed provider does the banking and the compliance; Textile runs the flow, keeps the state, and gives you one API that does not change when the provider does. The public Buy and Sell pages in the app run on exactly these endpoints.
GET /v2/ramp/providers → who can run this corridor, and what they need from the user
POST /v2/ramp/customers → register the person at the provider (once per wallet)
POST /v2/ramp/customers/kyc → hand over identity documents (buy only)
POST /v2/ramp/customers/kyc/status → where the review stands
GET /v2/ramp/banks → payout banks (sell)
POST /v2/ramp/banks/resolve → account number → account holder (sell)
POST /v2/ramp/transfers → quote and execute in one call
the user pays the bank account we return (buy), or sends the token to
the deposit address we return (sell)
GET /v2/ramp/transfers/{id} → status, timeline, and the delivered amount once it landsWhat to expect
- No key, no login. A wallet is the identity. Every write that names a wallet carries a short EIP-712 signature proving the caller controls it, the same proof of control the RFQ API uses. Creating a transfer returns a claim token, exactly once, and that token is what reads it back.
- One call books the whole thing.
POST /v2/ramp/transferslocks the price, registers the payout recipient on a sell, creates the transfer and returns the payment instructions. There is no separate quote step to keep alive. - The provider's fees are in the number.
targetAmountis what the user receives.rateLabelandfeeLabelare display strings for the receipt. Textile adds no fee of its own on a ramp. - Safe to retry. You send an
intentKeywith every create. A retry after a lost response returns the transfer that already exists instead of booking a second one with its own live bank details. - Status is pushed and pulled. The provider webhooks us, and a status read re-checks the provider when the stored state is more than a few seconds old. A lost webhook cannot strand a transfer. Statuses only move forward.
- Identity verification is part of the API. A buy needs a verified person at the provider. You collect documents in your own UI and post them to us; we never store them. The review state is readable, so a reload lands on the right screen.
Base URL
https://api.textilecredit.com/v2/rampThe flow
Buy (NGN → cNGN). Read /providers for the corridor. If the wallet has never used the provider, collect name, contact, date of birth and address and POST /customers. Post identity documents to /customers/kyc and poll /customers/kyc/status until verified. Then POST /transfers with the fiat amount and the destination wallet. The response carries a one-off bank account in payIn. The user pays it from their bank app. Poll GET /transfers/{id} until COMPLETED; payOut then carries the on-chain transaction hash.
Sell (cNGN → NGN). Read /providers, register the person if needed, then pick a bank from /banks and confirm the account number with /banks/resolve. POST /transfers with the token amount and the payout account. The response carries a deposit address in payIn. The user sends the token there from the wallet they named. The payout lands in the bank account. Sell is not gated on identity verification.
The first-time buy is the long path. A returning user with a verified profile is one call: POST /transfers.
Conventions
The Ramp API is a fiat surface, so two conventions differ from the RFQ API.
- Amounts are human decimal strings.
"50000"is fifty thousand naira or fifty thousand cNGN, not atomic units.amounton a buy is fiat, on a sell it is the token.sourceAmountandtargetAmountfollow the same rule. - Currencies are codes, uppercase:
fiat: "NGN",token: "CNGN". Chains are numericchainIds. - Addresses are standard EVM addresses. Lowercase is fine, we normalize.
- Timestamps are ISO-8601 UTC.
- Every response carries an
X-Request-Idheader. Quote it when you report a problem. - Errors use the v2 envelope. See Ramp errors.
Trying it
The app's Buy and Sell pages are the reference client. Watch the network tab on app.textilecredit.com/s/buy and you see these calls in order.
There is no testnet ramp: the rails are real banks. Staging runs the provider's sandbox account behind a sandbox: true flag; production refuses the flag. Ask us if you need sandbox access.
Next
- Customers and verification: registering a person, submitting documents, reading the review state.
- Transfers: providers, banks, creating a transfer, reading it back, the status lifecycle.
- Errors: the ramp-specific codes and what to do about each.