Internal Transfers
Move funds between beneficiaries within the same integrator account
Internal transfers allow you to move funds between two beneficiaries within the same integrator account. This is useful for wallet-to-wallet transfers, balance redistribution, or any case where funds need to move between beneficiaries without leaving the platform.
The process follows the standard two-step transaction flow:
- Create a simulation — Preview the transfer details, fees, and exchange rates.
- Execute the transaction — Confirm and execute the transfer using the simulation.
Prerequisites
- Both the source and target beneficiaries must belong to the same integrator.
- The source beneficiary must have sufficient funds in the specified currency.
Step 1: Create a simulation
Create a simulation to preview the internal transfer before execution.
curl -X POST "https://api.sandbox.caliza.com/core-api/v1/simulations" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {{ACCESS_TOKEN}}" \
-d '{
"beneficiaryId": "{{SOURCE_BENEFICIARY_ID}}",
"targetBeneficiaryId": "{{TARGET_BENEFICIARY_ID}}",
"from": {
"currencyCode": "USDC",
"value": 500.00
},
"toCurrencyCode": "USDC"
}'Request fields
| Field | Type | Required | Description |
|---|---|---|---|
beneficiaryId | string | Yes | The ID of the source beneficiary (sender) |
targetBeneficiaryId | string | Yes | The ID of the target beneficiary (receiver) |
from | object | Yes | The amount to transfer from the source beneficiary |
from.currencyCode | string | Yes | Currency code of the amount being sent (e.g., USDC, USD) |
from.value | number | Yes | The amount to transfer |
toCurrencyCode | string | Yes | The destination currency code. Use the same value as from.currencyCode for same-currency transfers, or a different code (e.g., USD to USDC) for conversions |
Response
{
"id": "sim_abc123",
"integratorId": "your-integrator-id",
"beneficiaryId": "source-beneficiary-id",
"from": {
"currencyCode": "USDC",
"value": "500.00"
},
"to": {
"currencyCode": "USDC",
"value": "500.00"
},
"flowOfFundsId": "fof_xyz789",
"transactionDetails": {
"conversionDetails": {
"effectiveTransactionValue": "500.00",
"clientRate": "1.00"
},
"feeDetails": {
"totalFees": {
"currencyCode": "USDC",
"value": "0.00"
}
}
},
"executed": false,
"createdDate": "2025-01-15T10:30:00Z",
"lastModifiedDate": "2025-01-15T10:30:00Z",
"expiresAt": "2025-01-15T10:35:00Z"
}Response fields
| Field | Type | Description |
|---|---|---|
id | string | Unique simulation ID. Use this to execute the transaction |
beneficiaryId | string | The source beneficiary ID |
from | object | The source amount and currency |
to | object | The destination amount and currency (after fees/conversion) |
transactionDetails | object | Breakdown of conversion rates and applicable fees |
executed | boolean | Whether this simulation has already been used to create a transaction |
expiresAt | string | ISO 8601 timestamp. The simulation must be executed before this time |
Simulations have a limited validity window. You must execute the transaction before
expiresAt, otherwise the simulation will expire and a new one must be created.
Step 2: Execute the transaction
Use the simulation ID to execute the internal transfer. The target beneficiary is already defined in the simulation, so you only need to provide the simulation ID and the beneficiary IP.
curl -X POST "https://api.sandbox.caliza.com/core-api/v1/transactions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {{ACCESS_TOKEN}}" \
-d '{
"simulationId": "{{SIMULATION_ID}}",
"beneficiaryIp": "203.0.113.50"
}'Request fields
| Field | Type | Required | Description |
|---|---|---|---|
simulationId | string | Yes | The simulation ID obtained from Step 1 |
beneficiaryIp | string | Yes | The IP address of the beneficiary initiating the transfer |
Optional fields
| Field | Type | Description |
|---|---|---|
transferPurpose | string | A description of the transfer purpose |
memo | string | An optional memo attached to the transaction |
paymentReference | string | An optional payment reference |
Response
{
"id": "txn_def456",
"simulationId": "sim_abc123",
"integratorId": "your-integrator-id",
"beneficiaryId": "source-beneficiary-id",
"targetBeneficiaryId": "target-beneficiary-id",
"from": {
"currencyCode": "USDC",
"value": "500.00"
},
"to": {
"currencyCode": "USDC",
"value": "500.00"
},
"status": "CREATED",
"flowOfFundsId": "fof_xyz789",
"transactionDetails": {
"conversionDetails": {
"effectiveTransactionValue": "500.00",
"clientRate": "1.00"
},
"feeDetails": {
"totalFees": {
"currencyCode": "USDC",
"value": "0.00"
}
}
},
"createdDate": "2025-01-15T10:30:15Z",
"lastModifiedDate": "2025-01-15T10:30:15Z"
}Response fields
| Field | Type | Description |
|---|---|---|
id | string | Unique transaction ID |
simulationId | string | The simulation used to create this transaction |
beneficiaryId | string | The source beneficiary (sender) |
targetBeneficiaryId | string | The target beneficiary (receiver) |
from | object | The debited amount and currency |
to | object | The credited amount and currency |
status | string | Current status of the transaction (see Transaction statuses) |
transactionDetails | object | Breakdown of conversion and fee details |
Step 3: Retrieve transactions
Internal transfer transactions are visible to both the source and target beneficiaries. When querying transactions by beneficiaryId, the API returns all transactions where the specified beneficiary is either the sender or the receiver.
curl -X GET "https://api.sandbox.caliza.com/core-api/v1/transactions?beneficiaryId={{BENEFICIARY_ID}}" \
-H "Authorization: Bearer {{ACCESS_TOKEN}}"Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
beneficiaryId | string | No | Filter by beneficiary. Returns transactions where the beneficiary is either the source or the target |
status | string | No | Filter by transaction status (e.g., SUCCEEDED, PROCESSING) |
fromDate | string | No | Filter transactions created on or after this date (YYYY-MM-DD) |
toDate | string | No | Filter transactions created on or before this date (YYYY-MM-DD) |
page | number | No | Page number for pagination (default: 0) |
size | number | No | Page size (default: 20) |
Response
{
"content": [
{
"id": "txn_def456",
"simulationId": "sim_abc123",
"beneficiaryId": "source-beneficiary-id",
"targetBeneficiaryId": "target-beneficiary-id",
"from": {
"currencyCode": "USDC",
"value": "500.00"
},
"to": {
"currencyCode": "USDC",
"value": "500.00"
},
"status": "SUCCEEDED",
"createdDate": "2025-01-15T10:30:15Z",
"lastModifiedDate": "2025-01-15T10:31:00Z"
}
],
"totalElements": 1,
"totalPages": 1,
"size": 20,
"number": 0
}The
beneficiaryIdin the response always represents the source (sender), andtargetBeneficiaryIdalways represents the target (receiver), regardless of which beneficiary you used to query.
Transaction statuses
| Status | Description |
|---|---|
CREATED | Transaction has been created and is being initialized |
PENDING | Transaction is pending processing |
PROCESSING | Transaction is actively being processed |
SUCCEEDED | Transaction completed successfully — funds have been moved |
FAILED | Transaction failed during processing |
CANCELLED | Transaction was cancelled |
EXPIRED | Transaction expired before completion |
Error scenarios
| Scenario | HTTP Status | Description |
|---|---|---|
| Insufficient funds in source beneficiary | 400 | The source beneficiary does not have enough balance |
| Invalid or expired simulation | 400 | The simulation ID is invalid or has expired |
| Simulation already executed | 400 | The simulation has already been used to create a transaction |
| Source and target are the same beneficiary | 400 | Cannot transfer to the same beneficiary |
| Beneficiary not found | 404 | The specified beneficiary ID does not exist |
| Unauthorized | 401 | Invalid or missing authentication token |
Updated 7 days ago
