Send Cross-Border Payments

How do I create and execute a remittance plan?

Send funds from a Cybrid trading account to a foreign bank account using the remittance product.
Cross-border payments include automatic currency conversion and competitive exchange rates.

ℹ️

Enable remittance

Contact Cybrid support to enable the remittance feature on your bank.

Overview

The remittance process involves four main steps:

  1. Create a remittance plan
  2. Wait for planning to complete
  3. Execute the plan
  4. Monitor execution completion
flowchart LR
  %% Subgraph
  subgraph RP["Remittance Process"]
    direction LR
    A("📝 Create Remittance Plan")
    B("⏳ Planning In Progress")
    C("⚙️ Execute Plan")
    D("📊 Monitor Execution Completion")

    A --> B --> C --> D
  end

  %% Styling
  classDef step fill:#F5F7FF,stroke:#5B6CFF,stroke-width:1.5px,color:#1A1A1A;
  classDef container fill:#EEF1FF,stroke:#3F51FF,stroke-width:2px,color:#1A1A1A;

  class A,B,C,D step;
  class RP container;

Prerequisites

Before you begin, ensure you have:

The source trading account must:

  • Be in created state
  • Belong to a verified customer (not frozen, not rejected)

The destination external bank account must:

  • Have kind: raw_routing_details
  • Be in completed state
  • Meet KYC requirements for the destination country and currency
ℹ️

Country-specific guides

Each destination corridor has specific requirements for participant types, source accounts,
recipient KYC, and bank account routing. See the corridor-specific guides:

Step 1: Create a remittance plan

Create a plan that calculates estimated amounts, fees, and exchange rates.

Request

POST /api/plans
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json

{
  "type": "remittance",
  "customer_guid": "customer_guid",
  "source_account": {
    "guid": "source_account_guid"
  },
  "destination_account": {
    "guid": "destination_account_guid",
    "amount": 10000
  },
  "purpose_of_transaction": "family_support",
  "travel_rule_info": {
    "ultimate_originating_party_guid": "originating_party_guid",
    "ultimate_receiving_party_guid": "receiving_party_guid"
  }
}

Request fields

  • type (required) - Set to remittance for cross-border payments.

  • customer_guid or bank_guid (required) - The owner of the plan. Use customer_guid for
    customer-owned plans or bank_guid for bank-owned plans. These fields are mutually exclusive.

  • source_account (required) - The trading account funding the remittance.

    • guid - Required. The trading account identifier.
    • amount - Optional. The amount to withdraw from the source account in base units.
  • destination_account (required) - The external bank account receiving the funds.

    • guid - Required. The external bank account identifier.
    • amount - Optional. The amount to deposit in the destination account in base units.
⚠️

Amount specification

You must specify EITHER source_account.amount OR destination_account.amount, but not both or
neither. When you specify the destination amount, the system calculates the required source amount
(including fees and exchange rates). When you specify the source amount, the system calculates the
resulting destination amount.

  • purpose_of_transaction (conditionally required) - Required for certain destination countries.
    Example values include: family_support, education, gift, medical_treatment, salary_payment,
    loan_payment, and other. See the API reference
    for the full list of supported values.

  • travel_rule_info (optional) - Required when the originator or receiver differs from the account
    holders. Valid entity types for parties: customer, counterparty, bank.

    • ultimate_originating_party_guid - Required when the funds originate from someone other than the
      trading account holder (for example, a bank acting on behalf of a customer).
    • ultimate_receiving_party_guid - Required when the final beneficiary differs from the external
      bank account holder.
  • supporting_documents (optional) - Logical document declarations attached to the plan, for
    corridors that require partner-supplied documentation. Each entry groups one or more pre-uploaded
    file GUIDs under a declared type.

    • type (required) - Document type. One of invoice, purchase_order, delivery_slip,
      contract, bill_of_lading, or others. Which types are required or accepted depends on the
      destination corridor and participant type. See the corridor-specific guides.
    • file_guids (required) - Array of file GUIDs in completed state. Files are uploaded via the
      customer-scoped File Upload endpoint, so each
      file_guid must belong to a customer (the same customer that owns the plan, or — for
      bank-owned plans — a customer linked to the plan's parties). Each file must be uploaded with a
      type matching the document type (for example, an invoice document references files
      uploaded with type: invoice). Allowed MIME types: application/pdf, image/jpeg,
      image/png.
    • document_reference_number (optional) - A reference number identifying the document, such as an
      invoice number. Required for B2B payouts to certain corridors (for example, India and the
      Dominican Republic), where exactly one supporting document must carry it.

    Limits: up to 3 documents per plan and up to 3 files per document. Upload files via
    File Upload and wait for state: "completed" before
    referencing them here. Non-remittance plan types reject this field with invalid_parameter (422).

  • labels (optional) - Array of strings to tag the plan. Use labels to track and filter plans
    by your own workflow identifiers (for example, a payroll run or batch reconciliation job). Maximum
    8 labels per plan, 64 characters each. When labels are set, the labels field appears in the
    plan response; the key is omitted for unlabeled plans.

Response

The plan returns in storing state while the system calculates rates and fees.

Step 2: Wait for planning to complete

Poll the plan endpoint until the state changes to completed, indicating it's ready for execution.

GET /api/plans/plan_guid
Authorization: Bearer YOUR_TOKEN
{
  "created_at": "2025-10-04T12:59:15.732645Z",
  "updated_at": "2025-10-04T12:59:17.249897Z",
  "expires_at": "2025-10-04T13:29:15.732645Z",
  "guid": "plan_guid",
  "state": "completed",
  "type": "remittance",
  "customer_guid": "customer_guid",
  "failure_code": null,
  "stages": [
    {
      "created_at": "2025-10-04T12:59:17.132720Z",
      "updated_at": "2025-10-04T12:59:17.132720Z",
      "guid": "stage_guid",
      "type": "payout",
      "failure_code": null,
      "state": "planned",
      "source_account": {
        "guid": "source_account_guid",
        "asset": "USDC",
        "type": "trading",
        "bank_guid": "bank_guid",
        "customer_guid": "customer_guid",
        "counterparty_guid": null,
        "requested_amount": null,
        "quoted_amount": 5531070,
        "executed_amount": null
      },
      "destination_account": {
        "guid": "destination_account_guid",
        "asset": "MXN",
        "type": "external_bank_account",
        "bank_guid": "bank_guid",
        "customer_guid": "customer_guid",
        "counterparty_guid": "counterparty_guid",
        "requested_amount": 10000,
        "quoted_amount": 10000,
        "executed_amount": null
      },
      "fees": [
        {
          "type": "bank",
          "asset": "USDC",
          "quoted_amount": 27518,
          "executed_amount": null
        },
        {
          "type": "platform",
          "asset": "USDC",
          "quoted_amount": 27518,
          "executed_amount": null
        },
        {
          "type": "network",
          "asset": "ETH",
          "quoted_amount": 100000000000,
          "executed_amount": null
        }
      ],
      "identifiers": [],
      "links": []
    }
  ],
  "supporting_documents": [],
  "source_account": {
    "guid": "source_account_guid",
    "asset": "USDC",
    "type": "trading",
    "bank_guid": "bank_guid",
    "customer_guid": "customer_guid",
    "counterparty_guid": null,
    "requested_amount": null,
    "quoted_amount": 5531070,
    "executed_amount": null
  },
  "destination_account": {
    "guid": "destination_account_guid",
    "asset": "MXN",
    "type": "external_bank_account",
    "bank_guid": "bank_guid",
    "customer_guid": "customer_guid",
    "counterparty_guid": "counterparty_guid",
    "requested_amount": 10000,
    "quoted_amount": 10000,
    "executed_amount": null
  },
  "fees": [
    {
      "type": "bank",
      "asset": "USDC",
      "quoted_amount": 27518,
      "executed_amount": null
    },
    {
      "type": "platform",
      "asset": "USDC",
      "quoted_amount": 27518,
      "executed_amount": null
    },
    {
      "type": "network",
      "asset": "ETH",
      "quoted_amount": 100000000000,
      "executed_amount": null
    }
  ],
  "travel_rule_info": {
    "originating_party": {
      "participant_guid": "customer_guid",
      "type": "customer"
    },
    "receiving_party": {
      "participant_guid": "counterparty_guid",
      "type": "counterparty"
    },
    "ultimate_originating_party": {
      "participant_guid": "bank_guid",
      "type": "bank"
    },
    "ultimate_receiving_party": {
      "participant_guid": "counterparty_guid",
      "type": "counterparty"
    }
  }
}
⚠️

Plan expiration

Plans expire after a configured period (see the expires_at field in the response). An expired
plan cannot be executed and results in a plan_expired error. Check the plan state before
execution.

Webhook support available

Subscribe to plan.completed and plan.failed events to receive real-time notifications
instead of polling. See the webhooks guide for setup.

ℹ️

Polling recommendations

Poll every 2-5 seconds for plan completion. Plans typically complete within 10-30 seconds.
Implement exponential backoff for longer-running operations.

Step 3: Execute the remittance plan

Execute the plan by creating an execution.

❗️

Currency conversion fees

The remittance process involves currency conversions to facilitate the cross-border payment. If
the final withdrawal to the destination bank account fails after conversions occur, any reversals
may incur fees.

❗️

Verify routing details

Perform test deposits for new bank accounts and double-check all external bank account routing
details before execution. Common issues that cause withdrawal failures include:

  • Incorrect CLABE numbers or routing codes
  • Mismatched account holder names
  • Invalid or closed bank accounts
  • Incorrect bank identifiers

Automated retry guidance

Only remittance failures with error codes external_server_error and market_volatility are valid
for automated retries. Other error codes, such as invalid_destination_account, should not be
retried automatically and typically require manual review and correction of beneficiary or routing
details.

POST /api/executions
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json

{
  "plan_guid": "plan_guid"
}

Response

The execution returns in storing state while the platform processes the remittance.

Step 4: Monitor execution completion

Poll the execution endpoint until the state changes to completed.

Webhook support available

Subscribe to execution.completed and execution.failed events to receive real-time
notifications instead of polling. See the webhooks guide
for setup.

ℹ️

Polling recommendations

Poll every 5-10 seconds for execution completion. Executions can take several minutes depending
on the destination country and payment rail. Implement exponential backoff for longer operations.

GET /api/executions/execution_guid
Authorization: Bearer YOUR_TOKEN
{
  "created_at": "2025-10-04T14:25:22.816775Z",
  "updated_at": "2025-10-04T14:28:48.663787Z",
  "guid": "execution_guid",
  "state": "completed",
  "type": "remittance",
  "plan_guid": "plan_guid",
  "customer_guid": "customer_guid",
  "failure_code": null,
  "stages": [
    {
      "created_at": "2025-10-04T14:24:55.865059Z",
      "updated_at": "2025-10-04T14:28:48.562584Z",
      "guid": "stage_guid",
      "type": "payout",
      "failure_code": null,
      "state": "completed",
      "source_account": {
        "guid": "source_account_guid",
        "asset": "USDC",
        "type": "trading",
        "bank_guid": "bank_guid",
        "customer_guid": "customer_guid",
        "counterparty_guid": null,
        "requested_amount": null,
        "quoted_amount": 5532205,
        "executed_amount": 5532205
      },
      "destination_account": {
        "guid": "destination_account_guid",
        "asset": "MXN",
        "type": "external_bank_account",
        "bank_guid": "bank_guid",
        "customer_guid": "customer_guid",
        "counterparty_guid": "counterparty_guid",
        "requested_amount": 10000,
        "quoted_amount": 10000,
        "executed_amount": 10000
      },
      "fees": [
        {
          "type": "bank",
          "asset": "USDC",
          "quoted_amount": 27524,
          "executed_amount": 27524
        },
        {
          "type": "platform",
          "asset": "USDC",
          "quoted_amount": 27524,
          "executed_amount": 27524
        },
        {
          "type": "network",
          "asset": "ETH",
          "quoted_amount": 100000000000,
          "executed_amount": 100000000000
        }
      ],
      "identifiers": [],
      "links": []
    }
  ],
  "source_account": {
    "guid": "source_account_guid",
    "asset": "USDC",
    "type": "trading",
    "bank_guid": "bank_guid",
    "customer_guid": "customer_guid",
    "counterparty_guid": null,
    "requested_amount": null,
    "quoted_amount": 5532205,
    "executed_amount": null
  },
  "destination_account": {
    "guid": "destination_account_guid",
    "asset": "MXN",
    "type": "external_bank_account",
    "bank_guid": "bank_guid",
    "customer_guid": "customer_guid",
    "counterparty_guid": "counterparty_guid",
    "requested_amount": 10000,
    "quoted_amount": 10000,
    "executed_amount": 10000
  },
  "fees": [
    {
      "type": "bank",
      "asset": "USDC",
      "quoted_amount": 27524,
      "executed_amount": 27524
    },
    {
      "type": "platform",
      "asset": "USDC",
      "quoted_amount": 27524,
      "executed_amount": 27524
    },
    {
      "type": "network",
      "asset": "ETH",
      "quoted_amount": 100000000000,
      "executed_amount": 100000000000
    }
  ],
  "travel_rule_info": {
    "originating_party": {
      "participant_guid": "customer_guid",
      "type": "customer"
    },
    "receiving_party": {
      "participant_guid": "counterparty_guid",
      "type": "counterparty"
    },
    "ultimate_originating_party": {
      "participant_guid": "bank_guid",
      "type": "bank"
    },
    "ultimate_receiving_party": {
      "participant_guid": "counterparty_guid",
      "type": "counterparty"
    }
  }
}

Understand the response

Plan and execution responses share a common structure with the following key fields:

Source account

  • quoted_amount - The cryptocurrency amount calculated at planning time
  • executed_amount - The actual cryptocurrency amount withdrawn (populated after execution)

If you specified source_account.amount in the request, the quoted amount matches the requested
amount. For the remittance product, the executed amount matches the quoted amount.

Destination account

  • quoted_amount - The destination currency amount calculated at planning time
  • executed_amount - The actual amount deposited in the external bank account

If you specified destination_account.amount in the request, the quoted amount matches the
requested amount.

Fees

Remittance fees include platform fees, bank fees, and network fees:

  • quoted_amount - The estimated fee at planning time
  • executed_amount - The actual fee charged at execution time
⚠️

Fee variability

Network fees, especially for cryptocurrency conversions, may vary between quote and execution due
to blockchain network conditions. The executed_amount reflects the actual fees charged.

Stages

Stages represent the individual steps of a plan. The remittance product uses a single payout stage
that transfers funds from the trading account to the external bank account.

Each stage includes two arrays for rail-issued reconciliation data:

  • identifiers - Array of {type, value} entries with rail-issued references (for example, the
    utr returned by India IMPS, NEFT, and RTGS). Always present; may be empty until the payout
    settles.
  • links - Array of {type, value} entries with rail-issued URLs (for example, receipt links).
    Always present; may be empty.

Allowed type values vary by rail. Filter by type and ignore unknown entries to stay
forward-compatible. See the corridor-specific guides for the identifier and link types each rail
surfaces.

Supporting documents

The plan response echoes supporting_documents for partner-side reconciliation, with each entry
shaped as {guid, type, document_reference_number, files: [{guid, filename, content_type}]}.
document_reference_number appears only on the document that carries a reference number — for B2B
payouts to corridors that require one (for example, India and the Dominican Republic), exactly one
document in the array carries it. The array is empty when no documents are attached.
supporting_documents lives on the plan only — execution responses do not include it.

Error handling

Plan creation errors (HTTP 422)

Error codeDescription
unknown_bank_exceptionBank not found
no_customer_exceptionCustomer not found
frozen_customer_exceptionCustomer is frozen
rejected_customer_exceptionCustomer is rejected
unverified_customer_exceptionCustomer not verified
no_source_account_exceptionSource account not found

Execution creation errors

Error CodeDescription
plan_expiredPlan has expired and cannot be executed
invalid_parameterPlan not in valid state or already executed

List plans and executions

List plans

Retrieve plans filtered by customer, state, label, or other criteria.

GET /api/plans?customer_guid=customer_guid&state=completed
Authorization: Bearer YOUR_TOKEN

List executions

Retrieve executions for a specific plan or customer.

GET /api/executions?plan_guid=plan_guid
Authorization: Bearer YOUR_TOKEN

See the Plans API reference and
Executions API reference for all available
filters.

Reference

For supported destination currencies, payment rails, upcoming corridors, and amount base unit
conventions, see Supported Corridors.

Plan states

StateDescription
storingInitial state while the system creates the plan
planningThe system calculates rate quotes and fees
completedPlan is ready for execution
failedPlanning failed (check failure_code)

Execution states

StateDescription
storingInitial state while the system creates the execution
executingRemittance is in progress
completedRemittance completed successfully
failedExecution failed (check failure_code)