Exchanges
Exchanges in Caliza allow you to convert between different currencies within a beneficiary's account — for example, converting USDC to USD, USDT to USD, or USDC to USDT. To perform an exchange, follow a two-step process:
- Simulate the exchange to get a quote.
- Execute the exchange based on the simulation.
See the sections below for more details on each step.
Simulate the exchange
To simulate an exchange using the Caliza API, you can use the following cURL command. Make sure to replace the following:
YOUR_TOKENwith your actual API tokenbeneficiaryIdwith the ID of the beneficiary you want to simulate the exchange for.
See an example request and response below:
See an example request below:
curl -s --location --request POST 'https://api.sandbox.caliza.com/core-api/v2/simulations' \
--header "Authorization: Bearer Your_Token" \
--header 'Content-Type: application/json' \
--data '{
"from": {
"currencyCode": "USDC",
"value": 500
},
"to": {
"currencyCode": "USD"
},
"beneficiaryId": "69261109adcc7b2db705a123"
}'Where:
from: An object containing details about the source of funds, including currency code and value.to: An object containing details about the destination of funds, including currency code.beneficiaryId: The ID of the beneficiary associated with the exchange.
Common exchange pairs include:
- USDC → USD: Convert USDC stablecoin to US dollars.
- USDT → USD: Convert USDT stablecoin to US dollars.
- USD → USDC: Convert US dollars to USDC stablecoin.
- USD → USDT: Convert US dollars to USDT stablecoin.
- USDC → USDT: Convert between stablecoins.
- USDT → USDC: Convert between stablecoins.
The response should look like this:
{
"id": "34c9dfe7-12da-4119-8beb-4db895c01a47",
"integratorId": "6920925fdbadfe09b1bf9e5e",
"beneficiaryId": "69261109adcc7b2db705a123",
"from": {
"currencyCode": "USDC",
"value": 500.00
},
"to": {
"currencyCode": "USD",
"value": 495.00
},
"flowOfFundsId": "55b778b2-1d8e-48fb-8229-0386d0f33fe0",
"transactionDetails": {
"conversionDetails": {
"effectiveTransactionValue": 495.00,
"marketExchangeRate": 1.00
},
"feeDetails": {
"totalFees": {
"currencyCode": "USDC",
"value": 5.00
},
"integratorFee": {
"currencyCode": "USDC",
"value": 0.00
},
"taxes": {
"currencyCode": "USDC",
"value": 0.00
}
}
},
"executed": false,
"guaranteedRate": true,
"rateValidityInMinutes": 15,
"expiresAt": "2025-11-27T15:00:00Z",
"createdDate": "2025-11-27T14:45:00Z",
"lastModifiedDate": "2025-11-27T14:45:00Z"
}Where:
id: The unique identifier for the simulation.integratorId: The ID of the integrator associated with the simulation.beneficiaryId: The ID of the beneficiary associated with the simulation.from: An object containing details about the source of funds, including currency code and value.to: An object containing details about the destination of funds, including currency code and value.flowOfFundsId: The unique identifier for the flow of funds associated with the simulation.transactionDetails: An object containing details about the transaction, including conversion details and fee details.executed: A boolean indicating whether the simulation has been executed.guaranteedRate: A boolean indicating whether the rate is guaranteed.rateValidityInMinutes: The validity period of the rate in minutes.expiresAt: The expiration date and time of the simulation.createdDate: The date and time when the system created the simulation.lastModifiedDate: The date and time when the system last modified the simulation.
Adding your own spread
When an exchange involves a currency conversion (for example USDC → BRL), you can add your own spread on top of Caliza's spread. That spread becomes your revenue on the conversion. You set it by passing a customFees object with an INTEGRATOR_SPREAD value on the simulation request.
- The value is expressed in basis points (BPS), where
100 BPS = 1%. A value of10means a0.10%markup. - The value must be
≥ 0. Passing0(or omittingcustomFees) disables your spread; Caliza's spread always applies. - It only affects the currency-conversion (FX) leg of an operation. Same-currency flows are unaffected.
How the rates relate
A converted amount is built up in two markup tiers on top of the raw market rate. Each margin is revenue for a different party:
| Rate | Public field | What it is | Revenue gap |
|---|---|---|---|
| Market rate | marketExchangeRate | Raw mid-market FX rate | — |
| Caliza rate | calizaRate | Market rate + Caliza spread | Market → Caliza = Caliza's revenue |
| Integrator rate | integratorRate | Caliza rate + your spread | Caliza → Integrator = your revenue |
The two margins stack, so the integrator rate is the least favorable of the three. The beneficiary receives the amount converted at the integrator rate.
Request
curl -s --location --request POST 'https://api.sandbox.caliza.com/core-api/v2/simulations' \
--header "Authorization: Bearer Your_Token" \
--header 'Content-Type: application/json' \
--data '{
"from": {
"currencyCode": "USDC",
"value": 500
},
"to": {
"currencyCode": "BRL"
},
"customFees": {
"INTEGRATOR_SPREAD": 100
},
"beneficiaryId": "69261109adcc7b2db705a123"
}'Where customFees.INTEGRATOR_SPREAD is your spread in basis points (here 100 BPS = 1%).
Response
The simulation (and later the transaction) reports the rate tiers under conversionDetails, and each margin as an item under feeDetails.spreadFees[] — a CALIZA item for Caliza's revenue and an INTEGRATOR_SPREAD item for yours:
"transactionDetails": {
"conversionDetails": {
"effectiveTransactionValue": 2633.76,
"marketExchangeRate": 5.40000000,
"clientRate": 5.32019704,
"calizaRate": 5.32019704,
"integratorRate": 5.26752183
},
"feeDetails": {
"spreadFees": [
{
"type": "CALIZA",
"spreadBasisPoint": 150,
"marketRate": 5.40000000,
"effectiveRate": 5.32019704,
"calizaRate": 5.32019704,
"calculatedFee": 39.90
},
{
"type": "INTEGRATOR_SPREAD",
"spreadBasisPoint": 100,
"marketRate": 5.40000000,
"effectiveRate": 5.26752183,
"calizaRate": 5.26752183,
"calculatedFee": 26.34
}
]
}
}Worked example
Converting 500 USDC → BRL at a market rate of 5.40, with a Caliza spread of 150 BPS and your spread of 100 BPS:
- At the market rate (
5.40000000):500 × 5.40 = 2700.00 BRL. - At the Caliza rate (
5.32019704):500 × 5.32019704 ≈ 2660.10 BRL. The39.90 BRLgap is Caliza's revenue (theCALIZAspread item). - At the integrator rate (
5.26752183):500 × 5.26752183 ≈ 2633.76 BRL. The26.34 BRLgap is your revenue (theINTEGRATOR_SPREADspread item).
The beneficiary receives 2633.76 BRL — the amount converted at the integrator rate.
Passing
INTEGRATOR_SPREAD: 0or omittingcustomFeesdisables your spread, sointegratorRateequalscalizaRateand noINTEGRATOR_SPREADitem is returned. Caliza's spread always applies regardless.
Execute the exchange
After simulating and agreeing on the from and to values, you'll need to execute the exchange.
To execute the exchange using the Caliza API, you can use the following cURL command. Make sure to replace YOUR_TOKEN with your actual API token and simulationId with the ID of the simulation you want to execute:
curl 'https://api.sandbox.caliza.com/core-api/v1/transactions' \
--header 'Authorization: Bearer YOUR_TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"simulationId": "{{simulationId}}",
"beneficiaryIp": "{{beneficiaryIp}}"
}'Where:
simulationId: The ID of the simulation you want to execute.beneficiaryIp: The IP address of the beneficiary initiating the exchange.
The response includes details about the executed exchange, including its status and timestamps. The response should look like this:
{
"id": "5d097212-9902-4d86-beec-c578640105f4",
"simulationId": "34c9dfe7-12da-4119-8beb-4db895c01a47",
"integratorId": "6920925fdbadfe09b1bf9e5e",
"beneficiaryId": "69261109adcc7b2db705a123",
"status": "PROCESSING",
"from": {
"currencyCode": "USDC",
"value": 500.00
},
"to": {
"currencyCode": "USD",
"value": 495.00
},
"transactionDetails": {
"conversionDetails": {
"effectiveTransactionValue": 495.00,
"marketExchangeRate": 1.00
},
"feeDetails": {
"totalFees": {
"currencyCode": "USDC",
"value": 5.00
}
}
},
"localInfo": null,
"blockchainInfo": null,
"createdDate": "2025-11-27T15:00:00Z",
"lastModifiedDate": "2025-11-27T15:00:00Z"
}Where:
id: The unique identifier for the exchange.simulationId: The ID of the simulation associated with the exchange.integratorId: The ID of the integrator associated with the exchange.beneficiaryId: The ID of the beneficiary associated with the exchange.status: The current status of the exchange (e.g., PROCESSING, COMPLETED).from: An object containing details about the source of funds, including currency code and value.to: An object containing details about the destination of funds, including currency code and value.transactionDetails: An object containing details about the transaction, including conversion details and fee details.localInfo: An object containing local payment information (if applicable).blockchainInfo: An object containing blockchain-related information (if applicable).
Get the exchange status
To check the status of an exchange using the Caliza API, you can use the following cURL command.
See the example request below:
curl --location --globoff 'https://api.sandbox.caliza.com/core-api/v1/transactions/{{transaction_id}}' \
--header 'Authorization: Bearer YOUR_TOKEN'Where transaction_id is the ID of the exchange you want to check.
The response should look like this:
{
"id": "5d097212-9902-4d86-beec-c578640105f4",
"simulationId": "34c9dfe7-12da-4119-8beb-4db895c01a47",
"integratorId": "6920925fdbadfe09b1bf9e5e",
"beneficiaryId": "69261109adcc7b2db705a123",
"status": "SUCCEEDED",
"from": {
"currencyCode": "USDC",
"value": 500.00
},
"to": {
"currencyCode": "USD",
"value": 495.00
},
"transactionDetails": {
"conversionDetails": {
"effectiveTransactionValue": 495.00,
"marketExchangeRate": 1.00
},
"feeDetails": {
"totalFees": {
"currencyCode": "USDC",
"value": 5.00
}
}
},
"localInfo": null,
"createdDate": "2025-11-27T15:00:00Z",
"lastModifiedDate": "2025-11-27T15:05:00Z",
"settledAt": "2025-11-27T15:05:00Z"
}Where:
id: The unique identifier for the exchange.simulationId: The ID of the simulation associated with the exchange.integratorId: The ID of the integrator associated with the exchange.beneficiaryId: The ID of the beneficiary associated with the exchange.status: The current status of the exchange (e.g., SUCCEEDED, FAILED).from: An object containing details about the source of funds, including currency code and value.to: An object containing details about the destination of funds, including currency code and value.transactionDetails: An object containing details about the transaction, including conversion details and fee details.localInfo: An object containing local payment information (if applicable).createdDate: The date and time when the system created the exchange.lastModifiedDate: The date and time when the system last modified the exchange.settledAt: The date and time when the exchange was settled (if applicable).
This allows you to monitor the exchanges made by beneficiaries and track their statuses effectively.
Webhook events for exchanges
When an exchange is completed, Caliza will send a webhook event to notify you about the successful exchange. The relevant webhook event for exchanges completed is as follows:
{
"operation": "TRANSACTION_COMPLETED",
"resourceId": "{{transaction_id}}",
"createdAt": "2025-04-17T22:10:23.476151179",
"integratorId": "{{integrator_id}}",
"beneficiaryId": "{{beneficiary_id}}",
"message": null,
"success": true,
"data": {
"callbackType": "transactionCallback",
"id": "{{transaction_id}}",
"integratorId": "{{integrator_id}}",
"beneficiaryId": "{{beneficiary_id}}",
"simulationId": null,
"foFTransactionType": "REGULAR_TRANSACTION",
"amountToBeConverted": {
"currencyCode": "USDC",
"value": 100.00
},
"from": {
"currencyCode": "USDC",
"value": 100.00
},
"to": {
"currencyCode": "USD",
"value": 100.00
},
"totalFees": {
"currencyCode": "USD",
"value": 0.0000
},
"totalTaxes": {
"currencyCode": "USD",
"value": 0.0000
},
"status": "TRANSACTION_COMPLETED",
"fiatAccountId": null,
"recipientId": null,
"fundingWallet": {{funding_wallet_address}},
"targetWallet": null,
"depositTransactionHash": null,
"withdrawalTransactionHash": null,
"flowOfFundsId": {{flow_of_funds_id}},
"localTargetAccount": null,
"exchangeRate": null,
"settlement": false
}
}Where:
operation: The type of operation that triggered the webhook (for example,TRANSACTION_COMPLETED).resourceId: The ID of the transaction associated with the webhook event.createdAt: The timestamp when the webhook event was created.integratorId: The ID of the integrator associated with the transaction.beneficiaryId: The ID of the beneficiary associated with the transaction.data: An object containing detailed information about the transaction, including its status and amounts.
You can use these webhook events to track exchange status and take appropriate actions based on each transaction.
Related Articles
Updated 3 months ago
