This page explains how to send, receive, and manage Canton Coin and CIP-56 tokens. Each operation is a v0_CreateTransactionOrder intent with parameters.type set to Canton, and your policies and approvals apply to it like any other transaction order.
Before you start, complete the account setup. For more information, see Set up Canton accounts with the API.
| Operation | Use it to |
|---|---|
NativeTransfer | Send Canton Coin. |
TokenTransfer | Send a CIP-56 token. |
Withdraw | Cancel an outgoing two-step transfer offer that the receiver hasn't acted on. |
Accept | Accept an incoming two-step transfer offer. |
Reject | Reject an incoming two-step transfer offer and return the assets to the sender. |
To submit an order, follow the dry run, propose, and check steps in Submit each order.
If the receiver has an active pre-approval for the asset, the transfer settles directly. Otherwise, it creates a two-step transfer offer, and the Holdings that fund it stay locked until the receiver accepts or rejects it, you withdraw it, or it expires. For background, see Transfer pre-approvals and two-step transfers.
The dry run and the submission both check that the receiver party exists on the network. If it doesn't, the order fails with an invalid destination error.
This example sends 25 CC to a counterparty:
{
"payload": {
"id": "b4f8d2a6-3c1e-4b9f-a7d5-1e3c5a7f9b2d",
"accountId": "3f7c1a9e-5b2d-4c8f-a6e1-9d3b7f5c2a8e",
"ledgerId": "canton-mainnet",
"parameters": {
"type": "Canton",
"operation": {
"type": "NativeTransfer",
"destination": {
"type": "Address",
"address": "c::1220e2b5a8d1c4f7e0b3a6d9c2f5b8e1a4d7c0f3b6e9a2d5c8f1b4e7a0d3c6f9b2e5"
},
"amount": "250000000000",
"executeBefore": "2026-10-31T17:00:00Z",
"memo": "INV-2026-0931"
}
},
"description": "Settlement to counterparty",
"customProperties": {},
"type": "v0_CreateTransactionOrder"
}
}A TokenTransfer takes the same fields as a NativeTransfer, plus the token's tickerId. This example sends 1,000 units of a CIP-56 token:
{
"payload": {
"id": "d7a3e9c5-2f4b-4d8a-b6e2-8c4a6f2d9b1e",
"accountId": "3f7c1a9e-5b2d-4c8f-a6e1-9d3b7f5c2a8e",
"ledgerId": "canton-mainnet",
"parameters": {
"type": "Canton",
"operation": {
"type": "TokenTransfer",
"destination": {
"type": "Address",
"address": "c::1220e2b5a8d1c4f7e0b3a6d9c2f5b8e1a4d7c0f3b6e9a2d5c8f1b4e7a0d3c6f9b2e5"
},
"amount": "10000000000000",
"tickerId": "8e4b2d6f-1a3c-4f7e-b9d2-6c8a0e2f4b7d",
"memo": "INV-2026-0932"
}
},
"description": "Token settlement to counterparty",
"customProperties": {},
"type": "v0_CreateTransactionOrder"
}
}| Field | Description |
|---|---|
operation.destination | The receiver. Use an Address destination with the receiver's party ID, an Endpoint destination, or an Account destination for another Ripple Custody account. |
operation.amount | The amount in the smallest unit, as a string. Canton assets use 10 decimal places, so 1 CC is "10000000000". |
operation.tickerId | TokenTransfer only. The ticker ID of the CIP-56 token. |
operation.executeBefore | Optional. The deadline, in ISO 8601 format, for the receiver to accept a two-step transfer offer. The default is 30 days after submission. It has no effect when the transfer settles directly. |
operation.memo | Optional. A reference of up to 255 characters that the network stores in the transfer's on-ledger metadata. Both the sender and the receiver can see it. |
Canton orders don't take a feeStrategy, and they don't support maximumFee. Ripple Custody rejects a Canton order that sets maximumFee.
The executeBefore deadline applies only to two-step transfer offers:
- Canton Coin: After the deadline passes, the network releases the sender's locked Holdings automatically. You don't need to withdraw the offer.
- Other CIP-56 tokens: After the deadline passes, the receiver can't accept the offer. To release the locked Holdings, submit a
Withdraworder.
A transfer that settles directly through a pre-approval completes when the network commits it and doesn't expire.
Canton accepts a prepared transaction for 24 hours. The window starts when Ripple Custody prepares the transaction, and signing and execution must both happen within it. If the window closes first, the network rejects the transaction. The preparation time is part of the signed transaction, so you can't extend the window: submit the order again, so that it's prepared and signed again.
The signing window is separate from executeBefore:
executeBeforeis how long the receiver has to accept a two-step transfer offer. It defaults to 30 days, and the sender can set it shorter.- The signing window is how long Ripple Custody has to get from preparing a transaction to executing it. It applies to every Canton order, including
AcceptandReject.
To accept or reject an offer, the offer must still be before its executeBefore deadline. Ripple Custody then prepares the Accept or Reject transaction, and the 24-hour signing window starts.
You can withdraw an outgoing two-step transfer offer until the receiver accepts or rejects it. Withdrawing cancels the offer and returns the locked Holdings to your account. You can't withdraw a transfer that settled directly.
Set contractId to the contract ID of the offer. You can find it in the ledgerData of the outgoing transaction. For more information, see Find the contract ID of a transfer offer.
{
"payload": {
"id": "f1c5a9e3-7b2d-4f6c-8a4e-9d2f6b1c5a8e",
"accountId": "3f7c1a9e-5b2d-4c8f-a6e1-9d3b7f5c2a8e",
"ledgerId": "canton-mainnet",
"parameters": {
"type": "Canton",
"operation": {
"type": "Withdraw",
"contractId": "00a4c7e1f3b6d9a2c5e8f1b4d7a0c3e6f9b2d5a8c1e4f7b0d3a6c9e2f5b8d1a4c7ca121220f6d9b2e5a8c1f4d7b0e3a6c9f2d5b8e1a4c7f0d3b6e9a2c5f8d1b4e7a0c3"
}
},
"description": "Withdraw expired transfer offer",
"customProperties": {},
"type": "v0_CreateTransactionOrder"
}
}To receive assets, share the account's party ID with the sender. To get the party ID, see Step 2: Create the party.
If the account has a pre-approval for the asset, the transfer settles directly and you don't need to do anything. If it doesn't, the transfer arrives as a two-step offer that you accept or reject before its deadline. For more information, see Accept or reject an incoming transfer offer.
In both cases, the incoming assets then enter quarantine, like incoming assets on every other ledger. Your quarantine release policies apply without any Canton-specific change. For more information, see Receive assets and Transaction screening.
Pre-approvals don't bypass quarantine. A pre-approval only means that the network settles the transfer without a signature from the receiver.
To accept an offer, submit an Accept order with the offer's contract ID. The network moves the assets into your account.
{
"payload": {
"id": "a2e6c1f5-8d3b-4a7e-9c5f-3b8d2a6e1c4f",
"accountId": "3f7c1a9e-5b2d-4c8f-a6e1-9d3b7f5c2a8e",
"ledgerId": "canton-mainnet",
"parameters": {
"type": "Canton",
"operation": {
"type": "Accept",
"contractId": "00b8e2d5a1c4f7b0e3d6a9c2f5e8b1d4a7c0f3e6b9d2a5c8f1e4b7d0a3c6f9e2b5d8ca121220a3f6c9e2b5d8a1f4c7e0b3d6a9f2c5e8b1d4a7f0c3e6b9d2a5f8c1e4b7"
}
},
"description": "Accept incoming Canton Coin offer",
"customProperties": {},
"type": "v0_CreateTransactionOrder"
}
}To reject an offer, submit the same payload with operation.type set to Reject. The network returns the assets to the sender.
Ripple Custody records each two-step transfer offer when it detects the offer on the ledger. To find the contract ID:
- Call the List transactions operation, filtered by the account.
- Find the transaction for the offer. Its
ledgerTransactionData.ledgerDataobject hastypeset toCanton. - Read the
contractIdfield.
The ledgerData object also shows the sender, receiver, amount, instrumentId, and executeBefore deadline of the offer. For all fields, see Transaction ledger data.
Use the standard account and transaction operations for Canton accounts:
- To view balances, see Check account balances. An account has a separate balance for Canton Coin and for each CIP-56 token.
- To view history, see View and audit transactions with the API.
- To refresh a balance that you think is out of date, see Force an account balance update. Ripple Custody rebuilds the balance from the account's current Holdings on the validator.
Keep the following behavior in mind:
- A Canton transaction is final as soon as the network commits it. Canton has no reorganizations.
- Ripple Custody learns a transaction's ledger ID (the Canton update ID) only after the network sequences it. Until then, the transaction has the
Broadcastingstatus without a ledger transaction ID. - A Canton Coin Holding that expires because of holding fees appears as a transfer with no receiver.
Ripple Custody emits the same events and webhooks for Canton transactions as for other ledgers. For more information, see Events and webhooks.
Each outgoing transfer spends whole Holdings, up to a limit of 100 per transfer. A transfer that settles directly also reserves its Holdings until it completes. For background, see Holdings. Two situations need attention.
If an account holds many small Holdings, a large transfer can need more Holdings than one transfer can spend and fail, even though the balance covers it.
To fix this, merge the Holdings. Send a self-transfer: a NativeTransfer or TokenTransfer with the account's own party ID as the destination, for an amount that the Holdings to merge add up to. The network replaces them with one Holding.
If an account has one large Holding, a second transfer that starts while the first is in progress fails, even though the balance covers both.
To fix this, split the Holding. Send a self-transfer for less than the Holding's amount. The network creates a Holding for the amount that you sent and a change Holding for the rest, so the account can fund two transfers at a time.
- Every Canton operation, including the setup orders,
Accept,Reject, andWithdraw, is av0_CreateTransactionOrderintent. Your transaction order policies apply to all of them. To treat operations differently, for example to require fewer approvals for pre-approval setup than for transfers, write your policies to distinguish them. For more information, see Policies. - Approvers review the exact receiver, amount, instrument, and contract ID that the vault signs. The vault refuses to sign a prepared transaction that doesn't match the approved intent. For the checks, see Architecture.
- Long approval flows don't affect incoming transfers to pre-approved accounts, because the receiver doesn't sign them.
- For a two-step transfer offer, the approval flow for
AcceptorRejectmust finish before the offer's deadline.