CanopyAPI docs

Payout destinations

Choose where each user's deposit settles, on any chain Canopy delivers to. Learn what a 201 confirms and what it does not.

Each payment intent can name its own settlement destination. This is live. Settlements pay the address you name.

Two settings must both be on before Canopy accepts a destination. You turn the first on or off in the dashboard. Only Canopy can turn on the second. Read this page before you send payoutWallet, payoutNamespace, or payoutChainReference in a live create call.

Name a destination on an intent

POST /api/v1/intents takes three optional fields for this:

  • payoutWallet (1 to 64 characters).
  • payoutNamespace ("eip155" or "solana").
  • payoutChainReference (1 to 64 characters).

Sending any one of the three counts as naming a destination.

If you omit payoutNamespace and payoutChainReference, both default to the settle chain. So payoutWallet alone means that address on the settle chain. Sending payoutNamespace or payoutChainReference without payoutWallet returns a 400.

curl -X POST https://www.canopypay.io/api/v1/intents \
  -H "Authorization: Bearer cnpy_sk_live_a1b2c3_<64 hex chars>" \
  -H "Canopy-Version: 2026-09-01" \
  -H "Content-Type: application/json" \
  -d '{
    "merchantReference": "order_10031",
    "payoutWallet": "0x9f2a1c7b3e5d8a604c1f2b9e7d3a5c8b6e4f1d20",
    "payoutNamespace": "eip155",
    "payoutChainReference": "8453"
  }'

The destination is write-once. It is set when the intent is created, and the API cannot update an intent. To settle to a different address, create another intent.

If you turn off your account setting later, intents you already created keep their destination and still settle there.

The two settings

A create that names a destination is accepted only when both of these are on. Canopy checks them in this order. Each returns its own error. You can fix the first yourself. Only Canopy can fix the second.

SettingWho controls itError when off
Per-intent destinations on your account. On by default.You, in the dashboard under account → Payments400 Per-intent destinations are disabled for this account. Enable them in the dashboard.
The settle-chain route's confirmedPayoutMode is DynamicCanopy only400 Route does not accept a per-intent destination

If both are off, you see the account setting error first.

Handle the two errors separately. The first goes away as soon as you turn the setting back on. The second goes away only when Canopy turns on Dynamic mode for the route.

A create with no destination fields skips both checks. It settles to your account payout wallet.

Where Canopy can deliver

Canopy can deliver to these four chains and no others:

PairChainDelivery
eip155:4663Robinhood Chain (settle chain)Direct
eip155:8453BaseCross-chain, through egress
eip155:42161ArbitrumCross-chain, through egress
solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpSolanaCross-chain, through egress

The create returns an error when:

  • The chain is not in this list: Destination chain is not a supported settlement destination.
  • The wallet does not fit its namespace: Destination wallet is malformed for its namespace.

Canopy checks the chain first. A bad address on an unsupported chain returns the chain error.

Address rules:

  • eip155: the address must be checksummed. The zero address is not accepted.
  • solana: the address must base58-decode to exactly 32 bytes. The all-zero address is not accepted.

Delivery to Base, Arbitrum or Solana goes through an egress vault that Canopy configures. If it is not configured, settlement stops with egress_not_configured. Canopy checks a cross-chain destination when you create the intent, but a successful create does not guarantee delivery.

How Canopy picks the destination

In Dynamic mode, Canopy picks the destination when the deposit settles. It uses the user's active intent.

  • No active intent: settlement stops with no_intent_destination.
  • More than one: settlement stops with ambiguous_intent_destination.

Canopy never guesses. Keep at most one active intent per user per destination. A route in Fixed mode does not read intents at all.

What a 201 does not promise

Canopy checks confirmedPayoutMode when you create the intent. The route's mode can change on-chain before the deposit settles, so that check is only a snapshot.

At settlement, Canopy reads the route's live on-chain payoutMode inside prepare(). That read decides. The account setting is checked only at create time. This is why an intent you already created keeps settling to its destination after you turn the setting off.

Sending the exact same create again returns the same intent. A repeat that names a different destination returns a 409.

See also