Skip to main content

Forwarding Address API Reference

Protocol

The API uses JSON-RPC 2.0 over HTTP POST with Content-Type: application/json.

Authentication

Most methods are public. Only the activation call (account_activateForwardingAddress) requires authentication: send Authorization: Bearer <account_api_key>. Account API keys are issued by Candide on request.


Discovery

forwarding_getRoutes

Returns all routes from a given source chain with their available tokens and fees. This is the single source of truth for which destination chains and tokens are supported. Routes, tokens, and fees can change dynamically.

Parameters:

NameTypeRequiredDescription
sourceChainIdnumberYesSource chain ID to get routes from

Request:

{
"jsonrpc": "2.0",
"id": 1,
"method": "forwarding_getRoutes",
"params": [{ "sourceChainId": 1 }]
}

Response:

{
"jsonrpc": "2.0",
"id": 1,
"result": {
"routes": [
{
"sourceChainId": 1,
"sourceChainName": "Ethereum",
"destinationChainId": 42161,
"destinationChainName": "Arbitrum One",
"tokens": [
{
"address": "0x0000000000000000000000000000000000000000",
"symbol": "ETH",
"decimals": 18,
"destinationAddress": "0x0000000000000000000000000000000000000000",
"feeBps": 50
},
{
"address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"symbol": "USDT",
"decimals": 6,
"destinationAddress": "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
"feeBps": 50
}
]
}
]
}
}

Token fields:

FieldDescription
addressToken contract address on the source chain. 0x000...000 represents native ETH
symbolHuman-readable token symbol
decimalsToken decimal places (source chain)
destinationAddressToken contract address on the destination chain. Use this when verifying arrival or displaying the output token
feeBpsService fee in basis points (50 = 0.5%)

forwarding_getMinimumAmount

Returns the minimum deposit amount per bridge for a specific route. Use this to validate user input before calling forwarding_estimateOutput. Minimums are bridge-specific because each bridge has its own threshold below which deposits are not processed.

Parameters:

NameTypeRequiredDescription
sourceChainIdnumberYesSource chain ID
destinationChainIdnumberYesDestination chain ID
tokenaddressYesToken address on the source chain

Request:

{
"jsonrpc": "2.0",
"id": 1,
"method": "forwarding_getMinimumAmount",
"params": [{
"sourceChainId": 1,
"destinationChainId": 42161,
"token": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
}]
}

Response:

{
"jsonrpc": "2.0",
"id": 1,
"result": {
"bridges": {
"across": { "minAmount": "500000" },
"oft": { "minAmount": "1000000" }
}
}
}
FieldDescription
bridgesObject keyed by bridge identifier. Each entry contains a minAmount in the smallest unit of the source token. A deposit below every bridge's minimum will not be forwarded

Core

forwarding_getAddress

Computes the deterministic CREATE2 proxy address for a given parameter set. Pure computation with no side effects. Safe to call repeatedly. The same inputs always produce the same address.

Parameters:

NameTypeRequiredDescription
recipientaddressYesDestination address that receives forwarded tokens
custodialWithdraweraddressYesEmergency recovery address that can withdraw stuck funds after a timelock. For most integrations, use the platform's address. See custodialWithdrawer
destinationChainIdnumberYesTarget chain ID where assets will be delivered
saltbytes32NoOptional 32-byte hex value. Use different salts to generate multiple forwarding addresses for the same recipient

Request:

{
"jsonrpc": "2.0",
"id": 1,
"method": "forwarding_getAddress",
"params": [{
"recipient": "0xAbCdEf0123456789AbCdEf0123456789AbCdEf01",
"custodialWithdrawer": "0xAbCdEf0123456789AbCdEf0123456789AbCdEf01",
"destinationChainId": 10
}]
}

Response:

{
"jsonrpc": "2.0",
"id": 1,
"result": {
"address": "0xDEF456..."
}
}

account_activateForwardingAddress

Activates relayer monitoring for a forwarding address on specified source chains. Returns the address, active status, and TTL expiration timestamp.

Requires authentication

Send Authorization: Bearer <account_api_key> with this request. Keys are issued by Candide. Each account can have up to 500 active forwarding addresses; refreshing an existing address does not count against the cap. Exceeding the cap returns error -32013.

Key behaviors:

  • Idempotent: calling again resets the TTL. Use this to keep an address active.
  • TTL-based: monitoring expires after the TTL. The address must be reactivated to resume forwarding.
  • Reusable: call activate again after expiration.
  • Same-chain forwarding: the destination chain is automatically included in the monitored set. You do not need to pass it in sourceChainIds to accept deposits on the destination chain itself.

Parameters:

NameTypeRequiredDescription
recipientaddressYesDestination recipient address
custodialWithdraweraddressYesWithdrawal-authorized address. See custodialWithdrawer
destinationChainIdnumberYesTarget chain ID
sourceChainIdsnumber[]YesArray of source chain IDs to activate monitoring on
saltbytes32NoOptional salt (must match the one used in forwarding_getAddress)

Request:

{
"jsonrpc": "2.0",
"id": 1,
"method": "account_activateForwardingAddress",
"params": [{
"recipient": "0xAbCdEf0123456789AbCdEf0123456789AbCdEf01",
"custodialWithdrawer": "0xAbCdEf0123456789AbCdEf0123456789AbCdEf01",
"destinationChainId": 10,
"sourceChainIds": [1, 42161]
}]
}

Response:

{
"jsonrpc": "2.0",
"id": 1,
"result": {
"address": "0xDEF456...",
"active": true,
"expiresAt": 1741132800
}
}
FieldDescription
expiresAtUnix timestamp (seconds) when monitoring expires. Do not hardcode this value; the default TTL may change

forwarding_getActivation

Checks the activation status of a forwarding address across all source chains it was registered on.

note

This endpoint tracks activation status (whether the relayer is monitoring this address), not deposit or forwarding completion status.

Parameters:

NameTypeRequiredDescription
addressaddressYesThe forwarding address to check

Request:

{
"jsonrpc": "2.0",
"id": 1,
"method": "forwarding_getActivation",
"params": [{
"address": "0xDEF456..."
}]
}

Response:

{
"jsonrpc": "2.0",
"id": 1,
"result": {
"address": "0xDEF456...",
"sourceChains": [
{
"sourceChainId": 1,
"status": "active",
"expiresAt": 1741132800
},
{
"sourceChainId": 42161,
"status": "expired",
"expiredAt": 1740528000
}
]
}
}

Estimation

forwarding_estimateOutput

Estimates the output amount a recipient will receive after relayer and bridge protocol fees. Returns the best available bridge for the route. This method is decoupled from forwarding addresses: it takes chain IDs directly and does not require the address to be activated.

Parameters:

NameTypeRequiredDescription
sourceChainIdnumberYesSource chain where the deposit originates
destinationChainIdnumberYesDestination chain ID
tokenaddressYesToken address on source chain (0x000...000 for native ETH)
amountstringYesInput amount in smallest unit (e.g. "1000000000000000000" for 1 ETH)

Request:

{
"jsonrpc": "2.0",
"id": 1,
"method": "forwarding_estimateOutput",
"params": [{
"sourceChainId": 1,
"destinationChainId": 42161,
"token": "0x0000000000000000000000000000000000000000",
"amount": "1000000000000000000"
}]
}

Response:

{
"jsonrpc": "2.0",
"id": 1,
"result": {
"destinationChainId": 42161,
"outputToken": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
"outputTokenSymbol": "USDC",
"bridge": "across",
"outputAmount": "994005000",
"relayerBotFee": "5000000",
"bridgeProtocolFee": "995000"
}
}
FieldDescription
bridgeIdentifier of the bridge selected for this route (e.g. "across", "oft")
outputTokenToken contract address on the destination chain
outputAmountAmount the recipient receives, in the smallest unit of the output token
relayerBotFeeRelayer service fee in smallest unit (source token decimals). Same-chain forwards return "0"
bridgeProtocolFeeBridge protocol fee in smallest unit (source token decimals)
note

To format outputAmount for display, look up the output token's decimals from forwarding_getRoutes (the matching destinationAddress on the route's token list).


Status

forwarding_getStatus

Returns confirmed forwards for a recipient on a destination chain, including per-bridge delivery statuses. Use this to track when a deposit has been picked up and whether it has been delivered, attested, refunded, etc.

Parameters:

NameTypeRequiredDescription
recipientaddressYesDestination recipient address
destinationChainIdnumberYesDestination chain ID

Request:

{
"jsonrpc": "2.0",
"id": 1,
"method": "forwarding_getStatus",
"params": [{
"recipient": "0xAbCdEf0123456789AbCdEf0123456789AbCdEf01",
"destinationChainId": 10
}]
}

Response:

{
"jsonrpc": "2.0",
"id": 1,
"result": {
"transfers": [
{
"sourceTxHash": "0x123...abc",
"sourceChainId": 1,
"proxyAddress": "0xDEF456...",
"createdAt": 1741132800,
"bridgeStatuses": [
{
"bridge": "across",
"status": "delivered",
"destinationTxHash": "0x789...def"
}
]
}
]
}
}
FieldDescription
transfersArray of confirmed forwards routed through the proxy address derived from recipient
bridgeStatuses[].statusOne of pending, attested, delivered, failed, expired, refunded

Emergency Recovery

The relayer auto-deploys the proxy contract on first deposit, so integrators typically do not need to deploy it manually. If tokens are stuck in a forwarding address (e.g. the relayer did not process them), the proxy must be deployed before funds can be withdrawn directly on-chain.

There is no JSON-RPC method for deploy or withdraw. Both actions are performed on-chain from a user's wallet. Direct users to the recovery frontend, which handles the deploy and withdraw transactions for the recipient or custodialWithdrawer.


TypeScript Types

These types match the API response shapes and can serve as a reference for building your integration.

interface RouteToken {
address: string;
symbol: string;
decimals: number;
destinationAddress: string; // token address on destination chain
feeBps: number; // basis points (50 = 0.5%)
}

interface Route {
sourceChainId: number;
sourceChainName: string;
destinationChainId: number;
destinationChainName: string;
tokens: RouteToken[];
}

interface RoutesResult {
routes: Route[];
}

interface MinimumAmountResult {
bridges: {
[bridgeName: string]: { minAmount: string }; // smallest unit, source token decimals
};
}

interface AddressResult {
address: string;
}

interface ActivationResult {
address: string;
active: boolean;
expiresAt: number; // Unix timestamp (seconds)
}

interface SourceChainActivation {
sourceChainId: number;
status: "active" | "expired";
expiresAt?: number; // present when active
expiredAt?: number; // present when expired
}

interface ActivationStatus {
address: string;
sourceChains: SourceChainActivation[];
}

interface EstimateResult {
destinationChainId: number;
outputToken: string;
outputTokenSymbol: string;
bridge: string; // bridge identifier selected for the route
outputAmount: string; // smallest unit, output token decimals
relayerBotFee: string; // smallest unit, source token decimals
bridgeProtocolFee: string; // smallest unit, source token decimals
}

Changelog

The Forwarding Address API is in alpha and evolves quickly. Breaking changes and new capabilities are tracked here so integrators can see what to update.

2026-05-06

Changed

  • forwarding_activate has been renamed to account_activateForwardingAddress and now requires Authorization: Bearer <account_api_key>. Other methods remain public. Request an account API key from Candide.

Added

  • Per-account cap of 500 active forwarding addresses. Refreshing an existing address does not count against the cap. Exceeding the cap returns error code -32013.
  • New forwarding_getStatus endpoint. Returns confirmed forwards for a recipient on a destination chain, with per-bridge delivery statuses (pending, attested, delivered, failed, expired, refunded).
  • Same-chain forwards is now fee free. Only the gas cost is taken into account in the relayer fee.

2026-04-22

Added

  • New source and destination chain support: Tempo. Supported tokens are USDC.e, USDT (Tempo's native token), and USDT0. Query forwarding_getRoutes with Tempo's chain ID to see accepted tokens and fees.

2026-04-14

Added

  • New forwarding_getMinimumAmount endpoint. Returns per-bridge minimum deposit amounts for a given source chain, destination chain, and token. Call this before forwarding_estimateOutput to validate user input.
  • New source and destination chain support: BNB Chain and Base. Query forwarding_getRoutes with the chain's ID to see the accepted tokens and fees.
  • forwarding_estimateOutput response now includes a bridge field identifying which bridge was selected for the route.
  • forwarding_activate now automatically includes the destination chain in the monitored set, so same-chain forwarding works without passing it in sourceChainIds.

Changed

  • forwarding_getRoutes parameter sourceChainId is now required. The endpoint returns all routes originating from that source chain. Call it once per source chain to build the full map of supported destinations.
  • RouteToken no longer includes a minAmount field. Minimums are now bridge-specific and returned by forwarding_getMinimumAmount.
  • forwarding_estimateOutput response no longer includes outputDecimals. To format outputAmount, read the output token's decimals from forwarding_getRoutes (match on the route's destinationAddress).

Removed

  • forwarding_estimateOutput no longer accepts a mode parameter. The service selects the best available bridge automatically and returns it in the response bridge field.
  • forwarding_setMode has been removed. Bridging strategy is no longer user-configurable per address.
  • forwarding_deploy has been removed as a JSON-RPC method. The relayer auto-deploys the proxy on first deposit. For emergency recovery of stuck funds, users deploy and withdraw on-chain from their own wallet via the recovery frontend.