# Forwarding Address API Reference

Alpha

The Forwarding Address API is in alpha. Breaking changes are expected. Do not move large amounts of funds through forwarding addresses during the alpha period.

## Protocol[​](#protocol "Direct link to Protocol")

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

## Authentication[​](#authentication "Direct link to 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[​](#discovery "Direct link to Discovery")

### `forwarding_getRoutes`[​](#forwarding_getroutes "Direct link to 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:

| Name            | Type     | Required | Description                        |
| --------------- | -------- | -------- | ---------------------------------- |
| `sourceChainId` | `number` | Yes      | Source 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:

| Field                | Description                                                                                                     |
| -------------------- | --------------------------------------------------------------------------------------------------------------- |
| `address`            | Token contract address on the source chain. `0x000...000` represents native ETH                                 |
| `symbol`             | Human-readable token symbol                                                                                     |
| `decimals`           | Token decimal places (source chain)                                                                             |
| `destinationAddress` | Token contract address on the destination chain. Use this when verifying arrival or displaying the output token |
| `feeBps`             | Service fee in basis points (50 = 0.5%)                                                                         |

***

### `forwarding_getMinimumAmount`[​](#forwarding_getminimumamount "Direct link to 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:

| Name                 | Type      | Required | Description                       |
| -------------------- | --------- | -------- | --------------------------------- |
| `sourceChainId`      | `number`  | Yes      | Source chain ID                   |
| `destinationChainId` | `number`  | Yes      | Destination chain ID              |
| `token`              | `address` | Yes      | Token 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" }

    }

  }

}
```

| Field     | Description                                                                                                                                                                 |
| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `bridges` | Object 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[​](#core "Direct link to Core")

### `forwarding_getAddress`[​](#forwarding_getaddress "Direct link to 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:

| Name                  | Type      | Required | Description                                                                                                                                                                                                                                                              |
| --------------------- | --------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `recipient`           | `address` | Yes      | Destination address that receives forwarded tokens                                                                                                                                                                                                                       |
| `custodialWithdrawer` | `address` | Yes      | Emergency recovery address that can withdraw stuck funds after a timelock. For most integrations, use the platform's address. See [custodialWithdrawer](https://docs.candide.dev/account-abstraction/research/forwarding-address-guide/.md#the-custodialwithdrawer-role) |
| `destinationChainId`  | `number`  | Yes      | Target chain ID where assets will be delivered                                                                                                                                                                                                                           |
| `salt`                | `bytes32` | No       | Optional 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`[​](#account_activateforwardingaddress "Direct link to 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:

| Name                  | Type       | Required | Description                                                                                                                                                               |
| --------------------- | ---------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `recipient`           | `address`  | Yes      | Destination recipient address                                                                                                                                             |
| `custodialWithdrawer` | `address`  | Yes      | Withdrawal-authorized address. See [custodialWithdrawer](https://docs.candide.dev/account-abstraction/research/forwarding-address-guide/.md#the-custodialwithdrawer-role) |
| `destinationChainId`  | `number`   | Yes      | Target chain ID                                                                                                                                                           |
| `sourceChainIds`      | `number[]` | Yes      | Array of source chain IDs to activate monitoring on                                                                                                                       |
| `salt`                | `bytes32`  | No       | Optional 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

  }

}
```

| Field       | Description                                                                                              |
| ----------- | -------------------------------------------------------------------------------------------------------- |
| `expiresAt` | Unix timestamp (seconds) when monitoring expires. Do not hardcode this value; the default TTL may change |

***

### `forwarding_getActivation`[​](#forwarding_getactivation "Direct link to 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:

| Name      | Type      | Required | Description                     |
| --------- | --------- | -------- | ------------------------------- |
| `address` | `address` | Yes      | The 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[​](#estimation "Direct link to Estimation")

### `forwarding_estimateOutput`[​](#forwarding_estimateoutput "Direct link to 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:

| Name                 | Type      | Required | Description                                                            |
| -------------------- | --------- | -------- | ---------------------------------------------------------------------- |
| `sourceChainId`      | `number`  | Yes      | Source chain where the deposit originates                              |
| `destinationChainId` | `number`  | Yes      | Destination chain ID                                                   |
| `token`              | `address` | Yes      | Token address on source chain (`0x000...000` for native ETH)           |
| `amount`             | `string`  | Yes      | Input 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"

  }

}
```

| Field               | Description                                                                                    |
| ------------------- | ---------------------------------------------------------------------------------------------- |
| `bridge`            | Identifier of the bridge selected for this route (e.g. `"across"`, `"oft"`)                    |
| `outputToken`       | Token contract address on the destination chain                                                |
| `outputAmount`      | Amount the recipient receives, in the smallest unit of the output token                        |
| `relayerBotFee`     | Relayer service fee in smallest unit (source token decimals). Same-chain forwards return `"0"` |
| `bridgeProtocolFee` | Bridge protocol fee in smallest unit (source token decimals)                                   |

note

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

***

## Status[​](#status "Direct link to Status")

### `forwarding_getStatus`[​](#forwarding_getstatus "Direct link to 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:

| Name                 | Type      | Required | Description                   |
| -------------------- | --------- | -------- | ----------------------------- |
| `recipient`          | `address` | Yes      | Destination recipient address |
| `destinationChainId` | `number`  | Yes      | Destination 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"

          }

        ]

      }

    ]

  }

}
```

| Field                     | Description                                                                           |
| ------------------------- | ------------------------------------------------------------------------------------- |
| `transfers`               | Array of confirmed forwards routed through the proxy address derived from `recipient` |
| `bridgeStatuses[].status` | One of `pending`, `attested`, `delivered`, `failed`, `expired`, `refunded`            |

***

## Emergency Recovery[​](#emergency-recovery "Direct link to 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](https://forwarding-address.candidelabs.com/), which handles the deploy and withdraw transactions for the `recipient` or `custodialWithdrawer`.

***

## TypeScript Types[​](#typescript-types "Direct link to 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[​](#changelog "Direct link to 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[​](#2026-05-06 "Direct link to 2026-05-06")

**Changed**

* `forwarding_activate` has been renamed to [`account_activateForwardingAddress`](#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`](#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[​](#2026-04-22 "Direct link to 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`](#forwarding_getroutes) with Tempo's chain ID to see accepted tokens and fees.

### 2026-04-14[​](#2026-04-14 "Direct link to 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`](#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](https://forwarding-address.candidelabs.com/).
