curl --request POST \
--url https://api.sandbox.capa.fi/api/partner/v2/on-ramp \
--header 'Content-Type: application/json' \
--header 'partner-api-key: <api-key>' \
--data '
{
"userId": "8374f327-38bd-4b0b-b8a7-2524599eb903",
"destinationWalletAddress": "0x4d2f3d8f83b6f2f8e0f3f4f3f3f3f3f3f3f3f3f3",
"quoteId": "<string>",
"fiatAmount": 123,
"cryptoAmount": 123,
"fiatCurrency": "MXN",
"blockchainSymbol": "POL",
"tokenSymbol": "USDC",
"premiumSpread": 123
}
'import requests
url = "https://api.sandbox.capa.fi/api/partner/v2/on-ramp"
payload = {
"userId": "8374f327-38bd-4b0b-b8a7-2524599eb903",
"destinationWalletAddress": "0x4d2f3d8f83b6f2f8e0f3f4f3f3f3f3f3f3f3f3f3",
"quoteId": "<string>",
"fiatAmount": 123,
"cryptoAmount": 123,
"fiatCurrency": "MXN",
"blockchainSymbol": "POL",
"tokenSymbol": "USDC",
"premiumSpread": 123
}
headers = {
"partner-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'partner-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
userId: '8374f327-38bd-4b0b-b8a7-2524599eb903',
destinationWalletAddress: '0x4d2f3d8f83b6f2f8e0f3f4f3f3f3f3f3f3f3f3f3',
quoteId: '<string>',
fiatAmount: 123,
cryptoAmount: 123,
fiatCurrency: 'MXN',
blockchainSymbol: 'POL',
tokenSymbol: 'USDC',
premiumSpread: 123
})
};
fetch('https://api.sandbox.capa.fi/api/partner/v2/on-ramp', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sandbox.capa.fi/api/partner/v2/on-ramp",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'userId' => '8374f327-38bd-4b0b-b8a7-2524599eb903',
'destinationWalletAddress' => '0x4d2f3d8f83b6f2f8e0f3f4f3f3f3f3f3f3f3f3f3',
'quoteId' => '<string>',
'fiatAmount' => 123,
'cryptoAmount' => 123,
'fiatCurrency' => 'MXN',
'blockchainSymbol' => 'POL',
'tokenSymbol' => 'USDC',
'premiumSpread' => 123
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"partner-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.sandbox.capa.fi/api/partner/v2/on-ramp"
payload := strings.NewReader("{\n \"userId\": \"8374f327-38bd-4b0b-b8a7-2524599eb903\",\n \"destinationWalletAddress\": \"0x4d2f3d8f83b6f2f8e0f3f4f3f3f3f3f3f3f3f3f3\",\n \"quoteId\": \"<string>\",\n \"fiatAmount\": 123,\n \"cryptoAmount\": 123,\n \"fiatCurrency\": \"MXN\",\n \"blockchainSymbol\": \"POL\",\n \"tokenSymbol\": \"USDC\",\n \"premiumSpread\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("partner-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.sandbox.capa.fi/api/partner/v2/on-ramp")
.header("partner-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"userId\": \"8374f327-38bd-4b0b-b8a7-2524599eb903\",\n \"destinationWalletAddress\": \"0x4d2f3d8f83b6f2f8e0f3f4f3f3f3f3f3f3f3f3f3\",\n \"quoteId\": \"<string>\",\n \"fiatAmount\": 123,\n \"cryptoAmount\": 123,\n \"fiatCurrency\": \"MXN\",\n \"blockchainSymbol\": \"POL\",\n \"tokenSymbol\": \"USDC\",\n \"premiumSpread\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sandbox.capa.fi/api/partner/v2/on-ramp")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["partner-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"userId\": \"8374f327-38bd-4b0b-b8a7-2524599eb903\",\n \"destinationWalletAddress\": \"0x4d2f3d8f83b6f2f8e0f3f4f3f3f3f3f3f3f3f3f3\",\n \"quoteId\": \"<string>\",\n \"fiatAmount\": 123,\n \"cryptoAmount\": 123,\n \"fiatCurrency\": \"MXN\",\n \"blockchainSymbol\": \"POL\",\n \"tokenSymbol\": \"USDC\",\n \"premiumSpread\": 123\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"id": "63f51f11-6869-47b0-a109-ddb50ef20efb",
"userId": "8374f327-38bd-4b0b-b8a7-2524599eb903",
"status": "PENDING_PAYMENT",
"cryptoAmount": 2500,
"fiatAmount": 50000,
"crossFiatAmount": 0,
"exchangeRate": 19.53964594161554,
"tokenSymbol": "USDC",
"blockchainSymbol": "POL",
"fiatCurrency": "MXN",
"premiumSpread": 0.01,
"forwardingDays": 2,
"effectiveForwardingDays": 4,
"forwardingSettlementDate": "2026-03-14T03:25:27.495Z",
"createdAt": "2025-05-14T10:00:00Z",
"completedAt": null,
"destinationWalletAddress": "0x7796d4f304bd84171ee6730ad0f69c07a47e786d",
"bankAccount": {
"country": "MX",
"accountIdentifier": "014680260346007120",
"bankName": "Santander",
"isVerified": true
}
}
}Create On-Ramp
curl --request POST \
--url https://api.sandbox.capa.fi/api/partner/v2/on-ramp \
--header 'Content-Type: application/json' \
--header 'partner-api-key: <api-key>' \
--data '
{
"userId": "8374f327-38bd-4b0b-b8a7-2524599eb903",
"destinationWalletAddress": "0x4d2f3d8f83b6f2f8e0f3f4f3f3f3f3f3f3f3f3f3",
"quoteId": "<string>",
"fiatAmount": 123,
"cryptoAmount": 123,
"fiatCurrency": "MXN",
"blockchainSymbol": "POL",
"tokenSymbol": "USDC",
"premiumSpread": 123
}
'import requests
url = "https://api.sandbox.capa.fi/api/partner/v2/on-ramp"
payload = {
"userId": "8374f327-38bd-4b0b-b8a7-2524599eb903",
"destinationWalletAddress": "0x4d2f3d8f83b6f2f8e0f3f4f3f3f3f3f3f3f3f3f3",
"quoteId": "<string>",
"fiatAmount": 123,
"cryptoAmount": 123,
"fiatCurrency": "MXN",
"blockchainSymbol": "POL",
"tokenSymbol": "USDC",
"premiumSpread": 123
}
headers = {
"partner-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'partner-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
userId: '8374f327-38bd-4b0b-b8a7-2524599eb903',
destinationWalletAddress: '0x4d2f3d8f83b6f2f8e0f3f4f3f3f3f3f3f3f3f3f3',
quoteId: '<string>',
fiatAmount: 123,
cryptoAmount: 123,
fiatCurrency: 'MXN',
blockchainSymbol: 'POL',
tokenSymbol: 'USDC',
premiumSpread: 123
})
};
fetch('https://api.sandbox.capa.fi/api/partner/v2/on-ramp', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sandbox.capa.fi/api/partner/v2/on-ramp",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'userId' => '8374f327-38bd-4b0b-b8a7-2524599eb903',
'destinationWalletAddress' => '0x4d2f3d8f83b6f2f8e0f3f4f3f3f3f3f3f3f3f3f3',
'quoteId' => '<string>',
'fiatAmount' => 123,
'cryptoAmount' => 123,
'fiatCurrency' => 'MXN',
'blockchainSymbol' => 'POL',
'tokenSymbol' => 'USDC',
'premiumSpread' => 123
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"partner-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.sandbox.capa.fi/api/partner/v2/on-ramp"
payload := strings.NewReader("{\n \"userId\": \"8374f327-38bd-4b0b-b8a7-2524599eb903\",\n \"destinationWalletAddress\": \"0x4d2f3d8f83b6f2f8e0f3f4f3f3f3f3f3f3f3f3f3\",\n \"quoteId\": \"<string>\",\n \"fiatAmount\": 123,\n \"cryptoAmount\": 123,\n \"fiatCurrency\": \"MXN\",\n \"blockchainSymbol\": \"POL\",\n \"tokenSymbol\": \"USDC\",\n \"premiumSpread\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("partner-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.sandbox.capa.fi/api/partner/v2/on-ramp")
.header("partner-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"userId\": \"8374f327-38bd-4b0b-b8a7-2524599eb903\",\n \"destinationWalletAddress\": \"0x4d2f3d8f83b6f2f8e0f3f4f3f3f3f3f3f3f3f3f3\",\n \"quoteId\": \"<string>\",\n \"fiatAmount\": 123,\n \"cryptoAmount\": 123,\n \"fiatCurrency\": \"MXN\",\n \"blockchainSymbol\": \"POL\",\n \"tokenSymbol\": \"USDC\",\n \"premiumSpread\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sandbox.capa.fi/api/partner/v2/on-ramp")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["partner-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"userId\": \"8374f327-38bd-4b0b-b8a7-2524599eb903\",\n \"destinationWalletAddress\": \"0x4d2f3d8f83b6f2f8e0f3f4f3f3f3f3f3f3f3f3f3\",\n \"quoteId\": \"<string>\",\n \"fiatAmount\": 123,\n \"cryptoAmount\": 123,\n \"fiatCurrency\": \"MXN\",\n \"blockchainSymbol\": \"POL\",\n \"tokenSymbol\": \"USDC\",\n \"premiumSpread\": 123\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"id": "63f51f11-6869-47b0-a109-ddb50ef20efb",
"userId": "8374f327-38bd-4b0b-b8a7-2524599eb903",
"status": "PENDING_PAYMENT",
"cryptoAmount": 2500,
"fiatAmount": 50000,
"crossFiatAmount": 0,
"exchangeRate": 19.53964594161554,
"tokenSymbol": "USDC",
"blockchainSymbol": "POL",
"fiatCurrency": "MXN",
"premiumSpread": 0.01,
"forwardingDays": 2,
"effectiveForwardingDays": 4,
"forwardingSettlementDate": "2026-03-14T03:25:27.495Z",
"createdAt": "2025-05-14T10:00:00Z",
"completedAt": null,
"destinationWalletAddress": "0x7796d4f304bd84171ee6730ad0f69c07a47e786d",
"bankAccount": {
"country": "MX",
"accountIdentifier": "014680260346007120",
"bankName": "Santander",
"isVerified": true
}
}
}Idempotency
Retry safely without creating duplicate transactions: pass an optionalIdempotency-Key header (UUIDv4). A retry with the same key and body replays the original response. See the Idempotency Guide for the full contract.
curl --request POST \
--url https://api.sandbox.capa.fi/api/partner/v2/on-ramp \
--header 'Content-Type: application/json' \
--header 'partner-api-key: <partner-api-key>' \
--header 'Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000' \
--data '...'
Field Relationships
- Provide
quoteIdOR (fiatCurrency+blockchainSymbol+tokenSymbol). When a quote is used, currency/token fields are inherited from the quote. - Provide either
fiatAmountorcryptoAmount, not both. - Provide either
destinationWalletAddress(inline) orwalletAddressId(reference to a saved wallet).
Integration Flow
Create a user
Complete KYC verification
Get a quote (optional)
Create on-ramp transaction
POST /api/partner/v2/on-ramp (this endpoint) — returns bank account details for the fiat depositUser deposits fiat
bankAccount response field.Important Notes
- User must be KYC-verified before creating transactions.
- Wallet type must match blockchain: An EVM wallet cannot be used on a Solana chain, and vice versa.
- Amount limits: Fiat and crypto amounts must fall within the min/max thresholds defined in your partner agreement.
Use Cases
- Buy Crypto: Enable users to purchase cryptocurrency using fiat deposited via bank transfer.
- B2C Integration: Let individual users on-ramp from within your app.
- Automated Purchases: Programmatically initiate fiat-to-crypto conversions for your users.
Error Codes
Common Errors
| HTTP Status | Code | Message |
|---|---|---|
| 401 | UNAUTHORIZED | ”API Key is missing” |
| 401 | UNAUTHORIZED | ”Invalid API Key format” |
| 401 | UNAUTHORIZED | ”Invalid API Key” |
| 403 | INVALID_PARTNER_FLOW | ”The partner has an invalid flow.” |
Verified User Errors
| HTTP Status | Code | Message |
|---|---|---|
| 400 | REQUIRED_USER_ID_ERROR | ”This endpoint requires a user id to be provided” |
| 403 | USER_NOT_VERIFIED_ERROR | ”User is not allowed to perform the operations because has not completed the KYC verification.” |
Endpoint-Specific Errors
| HTTP Status | Code | Message |
|---|---|---|
| 400 | INVALID_USER_INPUT_ERROR | ”Invalid User Input” |
| 400 | BAD_REQUEST | ”address must be a valid address” |
| 400 | BAD_REQUEST | ”Either quoteId or fiatCurrency, blockchainSymbol, tokenSymbol, and at least one of fiatAmount or cryptoAmount must be provided” |
| 400 | BAD_REQUEST | ”Fiat currency is disabled or does not exist” |
| 400 | BAD_REQUEST | ”This blockchain and token combination is disabled or does not exist” |
| 400 | QUOTE_EXPIRED | ”Quote has expired” |
| 400 | BAD_REQUEST | ”Quote is not valid for ON_RAMP” |
| 400 | INVALID_TOKEN_OPERATION_ERROR | ”Token cannot be operated as OTC, only stable coins are allowed” |
| 400 | BAD_REQUEST | ”Either walletAddressId or destinationWalletAddress must be provided” |
| 400 | BAD_REQUEST | ”Cannot create transaction: No supported banks configured for user with id: “ |
| 400 | INVALID_FIAT_AMOUNT_ERROR | ”Fiat amount is outside of the allowed range for ON_RAMP. Should be between and “ |
| 400 | INVALID_TOKEN_AMOUNT_ERROR | ”Token amount is outside of the allowed range for ON_RAMP. Should be between and ” |
Authorizations
API key for the affiliated partner performing the request.
Headers
Optional. Unique key (UUIDv4 recommended) to safely retry this request without creating a duplicate transaction. A retry with the same key and body replays the original response. See /docs/idempotency.
16 - 128"550e8400-e29b-41d4-a716-446655440000"
Body
Identifier for the user
"8374f327-38bd-4b0b-b8a7-2524599eb903"
Wallet address of the user making the transaction.
"0x4d2f3d8f83b6f2f8e0f3f4f3f3f3f3f3f3f3f3f3"
Identifier for the quote to be used for the transaction.
Amount of fiat currency to be converted to crypto currency.
Amount of cryptocurrency to be received in conversion.
Identifier for the fiat currency which the user will rec.
MXN, DOP, USD, EUR "MXN"
Identifier for the blockchain to token from which the conversion will be made. BSC is only available for transactions over 50,000 MXN.
POL, SOL, ETH, BSC "POL"
Identifier for the token from which the conversion will be made.
USDC, USDT "USDC"
Spread percentage to be applied to the exchange rate