Ramps
Ramps convert fiat to crypto (on-ramp) or crypto to fiat (off-ramp), such as USD → USDC or USDC → USD.
A ramp follows the quote → execution → settlement flow.
If you are exchanging one fiat currency for another, see FX .
Example: turn customer receipts into payroll funds
A software company converts 10,000 USDC from customer receipts into USD for payroll.
The example quote returns 9,975.00 USD for 10,000 USDC, with a listed fee of 25.00 USDC.
All figures and IDs are illustrative. Use approved accounts and enabled assets, networks, and payment rails.
Workflow
- Request available quotes.
- Select and persist a quoteId.
- Execute the selected quote.
- If funding is required, follow depositInstructions and complete the applicable deposit workflow.
- Retrieve the transaction to track its final status.
Get quotes and execute a selected route
Use input.amount to fix the 10,000 USDC source amount; omit output.amount to quote the USD proceeds. Quote requests supply exactly one amount.
Here, funds move from a USDC vault through a USD account to the payroll bank account. output.vaultId selects the USD account; destination.id selects the bank account.
Step 1 — Get quotes
POST /api/external/transactions/v2/quote/
REST request body
{
"intent": {
"input": {
"asset": "USDC",
"amount": "10000.00"
},
"output": {
"asset": "USD",
"vaultId": "vault_usd_settlement"
},
"source": {
"type": "VAULT",
"id": "vault_usdc_treasury",
"chain": "ETHEREUM"
},
"destination": {
"type": "BANK_ACCOUNT",
"id": "bank_account_usd_payroll",
"paymentRail": "ACH"
}
}
}Field | Type | Required | Description |
|---|---|---|---|
intent | TransactionIntentRequest | Yes | Quote criteria for the requested ramp or FX transaction. |
intent.source | TransferPartyData | Yes | Required source endpoint. Put its blockchain or payment rail on this party. |
intent.destination | TransferPartyData | Yes | Required destination endpoint. Put its blockchain or payment rail on this party. |
input.asset / output.asset | string | See description | Both asset fields are required. input is spent; output is received. |
input.amount / output.amount | string | See description | For quotes, provide exactly one non-null amount: input.amount or output.amount. Omit the other amount. |
source.chain / destination.chain | string | No | Blockchain identifiers for crypto legs. |
source.paymentRail / destination.paymentRail | string | No | Payment-rail identifiers for fiat or provider legs. |
Response
{
"quotes": [
{
"quoteId": "quote_ramp_payroll_1042",
"rate": "1",
"fees": {
"amount": "25.00",
"asset": "USDC"
},
"input": {
"asset": "USDC",
"amount": "10000.00"
},
"output": {
"asset": "USD",
"amount": "9975.00",
"vaultId": "vault_usd_settlement"
}
}
]
}JavaScript SDK
const quoteResponse = await apiClient.getQuote({
"intent": {
"input": {
"asset": "USDC",
"amount": "10000.00"
},
"output": {
"asset": "USD",
"vaultId": "vault_usd_settlement"
},
"source": {
"type": "VAULT",
"id": "vault_usdc_treasury",
"chain": "ETHEREUM"
},
"destination": {
"type": "BANK_ACCOUNT",
"id": "bank_account_usd_payroll",
"paymentRail": "ACH"
}
}
});
console.log(quoteResponse.quotes);Omitted fields stay omitted. For quote-only execution, the SDK sends intent as null.
Step 2 — Execute the selected quote
POST /api/external/transactions/intent/create/
REST request body
{
"intent": null,
"quoteId": "quote_ramp_payroll_1042",
"externalId": "payroll-top-up-1042",
"memo": "Convert 10000 USDC to USD for payroll"
}Execute a quote by sending its quoteId. Do not repeat intent or send category, routeAccounts, or subOrgId. The API returns HTTP 201 with a full Transaction; the SDK returns Promise<Transaction>. Optional fields depend on the payment route and status.
Response
{
"id": "transaction_ramp_payroll_1042",
"orgId": "org_example",
"vaultId": "vault_usdc_treasury",
"status": "PENDING",
"transactionType": "OUTGOING",
"category": "RAMP",
"subCategory": "TRADE_WITHDRAW",
"createdAt": "2026-09-16T10:00:00Z",
"updatedAt": "2026-09-16T10:00:00Z",
"isDeleted": false,
"createdById": "api_user_example",
"externalId": "payroll-top-up-1042",
"memo": "Convert 10000 USDC to USD for payroll",
"asset": "USDC",
"amount": "10000.00",
"source": {
"type": "VAULT",
"id": "vault_usdc_treasury",
"name": "USDC Treasury",
"chain": "ETHEREUM"
},
"destination": {
"type": "BANK_ACCOUNT",
"id": "bank_account_usd_payroll",
"name": "USD Payroll",
"paymentRail": "ACH"
},
"intent": {
"input": {
"asset": "USDC",
"amount": "10000.00"
},
"output": {
"asset": "USD",
"vaultId": "vault_usd_settlement",
"amount": "9975.00"
},
"source": {
"type": "VAULT",
"id": "vault_usdc_treasury",
"chain": "ETHEREUM"
},
"destination": {
"type": "BANK_ACCOUNT",
"id": "bank_account_usd_payroll",
"paymentRail": "ACH"
}
},
"quoteResponse": {
"quoteId": "quote_ramp_payroll_1042",
"rate": "1",
"fees": {
"amount": "25.00",
"asset": "USDC"
},
"input": {
"asset": "USDC",
"amount": "10000.00"
},
"output": {
"asset": "USD",
"amount": "9975.00",
"vaultId": "vault_usd_settlement"
}
},
"operations": [
{
"source": {
"type": "VAULT",
"id": "vault_usdc_treasury",
"name": "USDC Treasury",
"chain": "ETHEREUM"
},
"destination": {
"type": "BANK_ACCOUNT",
"id": "bank_account_usd_payroll",
"name": "USD Payroll",
"paymentRail": "ACH"
},
"balanceChanges": null,
"sequence": 1,
"type": "TRADE_WITHDRAW",
"status": "PENDING",
"provider": "Provider"
}
],
"balanceChanges": {
"changes": [
{
"party": {
"type": "VAULT",
"id": "vault_usdc_treasury",
"name": "USDC Treasury",
"chain": "ETHEREUM"
},
"asset": "USDC",
"amount": "-10000.00",
"chain": "ETHEREUM"
},
{
"party": {
"type": "BANK_ACCOUNT",
"id": "bank_account_usd_payroll",
"name": "USD Payroll",
"paymentRail": "ACH"
},
"asset": "USD",
"amount": "9975.00",
"paymentRail": "ACH"
}
]
}
}JavaScript SDK
const transaction = await apiClient.createTransactionFromIntent({
"quoteId": "quote_ramp_payroll_1042",
"externalId": "payroll-top-up-1042",
"memo": "Convert 10000 USDC to USD for payroll"
});
console.log(transaction);If execution returns a PENDING transaction, the SDK signs and submits the associated change approval and then retrieves the updated transaction.
Step 3 — Track the payroll conversion
Retrieve the transaction through GET /api/external/transactions/transaction_ramp_payroll_1042/ or the SDK until COMPLETED, FAILED, or DECLINED.
You can also receive webhook notifications when the transaction reaches COMPLETED, FAILED, or DECLINED. See Webhooks for more information.
const transaction = await apiClient.getTransactionById("transaction_ramp_payroll_1042");
console.log(transaction.id, transaction.status);Mark an on-ramp bank deposit done (when required)
For a USD-to-USDC on-ramp, use a BANK_ACCOUNT source and VAULT destination. Select the USD account with input.vaultId, set input.amount, and choose the source paymentRail and destination chain.
After funding via depositInstructions, mark the separate APPROVED settlement deposit done when required. This on-ramp example uses transaction_onramp_deposit_2042; it is separate from the payroll off-ramp.
POST /api/external/transactions/mark_deposit_done/
REST request body
{
"transactionId": "transaction_onramp_deposit_2042"
}This endpoint applies only to an APPROVED TRANSFER / DEPOSIT in a quote-driven settlement flow. The response is a deposit excerpt; SUBMITTED does not complete the parent conversion.
Response
{
"id": "transaction_onramp_deposit_2042",
"status": "SUBMITTED",
"category": "TRANSFER",
"subCategory": "DEPOSIT",
"asset": "USD",
"amount": "10000.00"
}JavaScript SDK
await apiClient.markDepositDone("transaction_onramp_deposit_2042");