Migrate to Plans and Executions

How do I move deposits, withdrawals, and remittances from quotes, transfers, and trades to plans and executions?

Plans and executions replace quotes, transfers, and trades for fiat deposits, withdrawals, and remittances. A plan prices the whole movement up front, and one execution runs it as a series of stages. A remittance that took a funding transfer, a trade, and a payout now takes a deposit plan and a remittance plan.

⚠️

Required in Canada

Canadian money movement must use plans and executions to adhere to newly approved regulatory flows. See the CA Remittance Integration Guide for the complete Canadian flow.

Prerequisites

  • Add the plans:read, plans:execute, executions:read, and executions:execute scopes to your API credentials.

Map concepts

Quotes, transfers, and tradesPlans and executions
POST /api/quotesPOST /api/plans. The plan carries the price and an expires_at.
POST /api/transfers, POST /api/tradesPOST /api/executions with the plan_guid.
One transfer or trade per stepOne execution with ordered stages (for example deposit, trade, payout, withdrawal). Each stage has its own state.
deliver_amount or receive_amount on the quoteamount on source_account or destination_account.
external_bank_account_guid on the transferAccount guid on source_account and destination_account.
Participants on the transfercustomer_guid or bank_guid on the plan.
payment_rail on the transferpayment_rail on the external bank account side: source_account for a deposit, destination_account for a withdrawal.
security_question and security_answer on the transfersecurity_question and security_answer on destination_account.
identifiers on the transfer (for example gateway_url)links and identifiers on each stage in stages.
Transfer or trade failure_codePlan and execution failure_code, with per-stage failure_code.
transfer.* and trade.* webhooksplan.* and execution.* webhooks. Stages have no webhook events.

Map operations

OperationBeforeAfter: plan typeStages
Deposit fiatFunding quote (side: deposit) + funding transferdepositdeposit
Withdraw fiatFunding quote (side: withdrawal) + funding transferwithdrawalwithdrawal
Remit from a fiat balanceTrading quote + trade, then a remittance plan from the trading accountremittance from the fiat accounttrade, payout

Migrate a deposit

Before, a funding quote and a funding transfer:

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

{
  "product_type": "funding",
  "customer_guid": "customer_guid",
  "asset": "CAD",
  "side": "deposit",
  "deliver_amount": 10000
}

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

{
  "quote_guid": "quote_guid",
  "transfer_type": "funding",
  "payment_rail": "etransfer",
  "source_participants": [
    {"type": "customer", "guid": "customer_guid", "amount": 10000}
  ],
  "destination_participants": [
    {"type": "customer", "guid": "customer_guid", "amount": 10000}
  ]
}
POST /api/plans
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN

{
  "type": "deposit",
  "customer_guid": "customer_guid",
  "source_account": {
    "guid": "external_bank_account_guid",
    "amount": 10000,
    "payment_rail": "etransfer"
  },
  "destination_account": {
    "guid": "fiat_account_guid"
  }
}

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

{
  "plan_guid": "plan_guid"
}

Poll GET /api/plans/{plan_guid} until state is completed or failed. Create the execution only for a completed plan, before expires_at.

The deposit before this change used the e-Transfer gateway without an external bank account. A deposit plan needs an external bank account as its source. See Update Canadian e-Transfer flows.

Migrate a remittance

Before, CAD was traded to USDC_SOL with a quote and a trade, and the remittance plan used the trading account as its source. After, the remittance plan uses the fiat account as its source and runs the trade as its first stage.

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

{
  "type": "remittance",
  "customer_guid": "customer_guid",
  "source_account": {
    "guid": "trading_account_usdc_sol_guid",
    "amount": 72000000
  },
  "destination_account": {
    "guid": "recipient_external_bank_account_guid"
  },
  "purpose_of_transaction": "family_support"
}
POST /api/plans
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN

{
  "type": "remittance",
  "customer_guid": "customer_guid",
  "source_account": {
    "guid": "fiat_account_guid",
    "amount": 10000
  },
  "destination_account": {
    "guid": "recipient_external_bank_account_guid"
  },
  "purpose_of_transaction": "family_support"
}
ℹ️

Intermediate accounts

The customer still needs a trading account for the trade stage; Cybrid selects it when only one is eligible. Pass intermediate_accounts only when the customer has more than one eligible account of the same asset for a stage.

Read stage links

Provider links such as the Interac e-Transfer gateway_url move from the transfer's identifiers to the stage's links. Poll GET /api/executions/{execution_guid} and read the link from the matching stage:

{
  "guid": "execution_guid",
  "type": "deposit",
  "state": "executing",
  "stages": [
    {
      "guid": "stage_guid",
      "type": "deposit",
      "state": "executing",
      "links": [
        {
          "type": "gateway_url",
          "value": "gateway_url"
        }
      ]
    }
  ]
}

Update webhooks and failure handling

  • Subscribe to plan.planning, plan.completed, plan.failed, execution.executing, execution.completed, and execution.failed. See Webhooks.
  • Read plan failures from the plan failure_code.
  • Read execution failures from the execution failure_code, and from the stage failure_code to see which stage failed. Interac e-Transfer codes such as payment_request_expired, recipient_cancelled, and invalid_security_question are reported on the execution.
  • Plans expire. Executing a plan after expires_at returns 422 with plan_expired; create a new plan.

Update Canadian e-Transfer flows

  • Deposits need a customer-owned account. A deposit plan's source is the customer's Interac e-Transfer external bank account. See Use a customer-owned Interac e-Transfer account.
  • Deposit bank account required. Creating an execution for a deposit to a fiat account without a main deposit bank account is rejected with no_deposit_bank_account. See Deposit Bank Account Requirement.
  • Withdrawals carry the security pair on the destination. Send security_question and security_answer on destination_account with payment_rail set to etransfer.

Next steps


Did this page help you?