For the complete documentation index, see llms.txt. This page is also available as Markdown.

Creating an off-ramp

Move crypto into a bank account with KiiChain Pay. Quote a rail, open the off-ramp, execute the on-chain transaction, and track the activity until the fiat lands.

An off-ramp converts crypto into fiat, paid out to a bank account. Unlike an on-ramp, the user (or your backend, via a delegated wallet) must execute an on-chain transaction to move the crypto into settlement. After that, the activity passes an AML check and provider processing before the fiat is sent to the destination bank account.

At a glance

Property
Value

Direction

Crypto → Fiat

Create endpoint

POST /tickets/v1/offramp

User acts

On-chain — executes the returned transaction

On-chain signing

Delegated Kii Wallet (server-side) or external wallet (self-sign)

You need

A KYC-verified account, an off-ramp products_provider_id, a bank withdraw_destination_id, and a delegated Kii Wallet (for the primary path)

Tracks via

display_status on the activity

Prerequisites

  • A KiiChain Pay account that has completed KYC, with its Kii Wallet delegated if you want KiiChain Pay to sign the on-chain step for you.

  • An API key with tickets.tickets.write and (for the delegated path) blockchain.transactions.execute; write calls must be signed.

  • Your account_id, your on-chain wallet address, and a bank withdrawal destination.

Set up a bank withdrawal destination

The fiat payout goes to a confirmed bank destination. If you don't have one yet, create it (see Discovering rails & IDs for the full flow):

  1. GET /accounts/v1/rails/schemas?country={country} — read the bank rail's required payload fields.

  2. POST /accounts/v1/users/{userId}/accounts/{accountId}/withdrawal_destinations — register it with { rail_code, rail_version, payload, name }.

  3. POST …/withdrawal_destinations/{destinationId}:confirm — confirm with the verify_code you receive.

Then list your destinations and pick the id of the "bank" one — that's your withdraw_destination_id. The examples assume KII_API_KEY, KII_ACCOUNT_ID, KII_ADDRESS (your 0x… wallet address), and KII_WITHDRAW_DEST_ID are set.

Step 1 — Get a quote

Find an off-ramp rail (a products-provider whose type is "offramp") and quote it for the crypto amount you want to sell. For an off-ramp the amount is crypto in atoms (smallest unit).

The response is a signed quote envelope with target_type: "offramp"; pass it back unchanged in the next step. Quotes expire — check expiration_date / exp.

Step 2 — Create the off-ramp

Create the activity with the quote, your account_id, user_chain_address, and the bank withdraw_destination_id. This is a signed write request.

The response holds the new ticket and the transactions you must execute on-chain to fund the off-ramp:

If the token needs an ERC-20 allowance, an approval transaction is prepended to the list. Execute the transactions in order.

Step 3 — Execute the transaction

KiiChain Pay does not sign for you at create time — the transactions come back unsigned. You execute them one of two ways.

Hand the returned transactions straight to the blockchain execute endpoint. KiiChain Pay signs and broadcasts them from your delegated Kii Wallet, with gas sponsored. This is a signed write request.

A hash of "0x00" in the array means that transaction failed to broadcast.

With an external wallet

If the user holds their own keys, don't call KiiChain Pay to sign. Take each evm transaction's chain_id, to, value, and data, then sign and broadcast it with your own signer (for example, viem's sendTransaction). KiiChain Pay observes the on-chain event and advances the activity.

You can re-fetch the outstanding transaction at any time while the activity is open with GET /tickets/v1/{ticketId}/pending_user_actions (it returns a transaction_payload).

Step 4 — Track to completion

Poll the activity and watch display_status.

After your transaction confirms, the activity runs an AML check, then provider processing, then pays out — display_status moves through processing to fulfilled when the fiat is sent to the bank account. If the AML check or provider rejects the transfer, the crypto is returned and the activity ends as refunded (or canceled / failed). While the activity is awaiting on-chain confirmation you can cancel it — GET /tickets/v1/{ticketId}/user_txs returns a cancel transaction when that action is available.

Full example

End-to-end off-ramp via a delegated Kii Wallet, using the kiiFetch signing helper from Generating API keys.

Last updated