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:

  1. Create a simulation — Preview the transfer details, fees, and exchange rates.
  2. 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

FieldTypeRequiredDescription
beneficiaryIdstringYesThe ID of the source beneficiary (sender)
targetBeneficiaryIdstringYesThe ID of the target beneficiary (receiver)
fromobjectYesThe amount to transfer from the source beneficiary
from.currencyCodestringYesCurrency code of the amount being sent (e.g., USDC, USD)
from.valuenumberYesThe amount to transfer
toCurrencyCodestringYesThe 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

FieldTypeDescription
idstringUnique simulation ID. Use this to execute the transaction
beneficiaryIdstringThe source beneficiary ID
fromobjectThe source amount and currency
toobjectThe destination amount and currency (after fees/conversion)
transactionDetailsobjectBreakdown of conversion rates and applicable fees
executedbooleanWhether this simulation has already been used to create a transaction
expiresAtstringISO 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

FieldTypeRequiredDescription
simulationIdstringYesThe simulation ID obtained from Step 1
beneficiaryIpstringYesThe IP address of the beneficiary initiating the transfer

Optional fields

FieldTypeDescription
transferPurposestringA description of the transfer purpose
memostringAn optional memo attached to the transaction
paymentReferencestringAn 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

FieldTypeDescription
idstringUnique transaction ID
simulationIdstringThe simulation used to create this transaction
beneficiaryIdstringThe source beneficiary (sender)
targetBeneficiaryIdstringThe target beneficiary (receiver)
fromobjectThe debited amount and currency
toobjectThe credited amount and currency
statusstringCurrent status of the transaction (see Transaction statuses)
transactionDetailsobjectBreakdown 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

ParameterTypeRequiredDescription
beneficiaryIdstringNoFilter by beneficiary. Returns transactions where the beneficiary is either the source or the target
statusstringNoFilter by transaction status (e.g., SUCCEEDED, PROCESSING)
fromDatestringNoFilter transactions created on or after this date (YYYY-MM-DD)
toDatestringNoFilter transactions created on or before this date (YYYY-MM-DD)
pagenumberNoPage number for pagination (default: 0)
sizenumberNoPage 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 beneficiaryId in the response always represents the source (sender), and targetBeneficiaryId always represents the target (receiver), regardless of which beneficiary you used to query.


Transaction statuses

StatusDescription
CREATEDTransaction has been created and is being initialized
PENDINGTransaction is pending processing
PROCESSINGTransaction is actively being processed
SUCCEEDEDTransaction completed successfully — funds have been moved
FAILEDTransaction failed during processing
CANCELLEDTransaction was cancelled
EXPIREDTransaction expired before completion

Error scenarios

ScenarioHTTP StatusDescription
Insufficient funds in source beneficiary400The source beneficiary does not have enough balance
Invalid or expired simulation400The simulation ID is invalid or has expired
Simulation already executed400The simulation has already been used to create a transaction
Source and target are the same beneficiary400Cannot transfer to the same beneficiary
Beneficiary not found404The specified beneficiary ID does not exist
Unauthorized401Invalid or missing authentication token