> ## Documentation Index
> Fetch the complete documentation index at: https://docs.eco.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Circle Gateway deposits

> Create and fund a quoted deposit address for USDC delivery into Circle Gateway.

Circle Gateway deposits let you fund a Gateway balance through a source-chain USDC deposit. Your application requests a quoted address, the user funds it, and Eco publishes the intent for solver fulfillment. The funding transaction, intent publication, and Gateway credit are separate stages.

## Prerequisites

* A supported source-chain wallet with USDC
* A recipient address for the Gateway balance on Polygon
* Source-chain gas for a direct transfer, or a wallet that supports the [gasless funding methods](/programmable-addresses/funding-methods)
* A delivery check through Circle Gateway, or an Eco v1 API key for intent tracking

The documented source chains are Base, OP Mainnet, and Arbitrum One, with Gateway on Polygon as the destination. Check [chain support](/resources/supported-chains-tokens) and confirm availability for your deposit request before funding. A Routes-supported chain is not necessarily enabled for this deposit flow.

## API conventions

Base URL: `https://api.eco.com`. Circle Gateway endpoints use `/v1/circle-gateway/` and do not require an API key. Create and deposit lookup responses have a `{ data: ... }` envelope; gasless submit and job status responses use the v1 job format.

No requests-per-second quota is published. Handle `429` with backoff and honor `Retry-After` when present. The [endpoint reference](/api-reference/v1/gateway-create) includes request schemas and success and error examples.

## Step 1: Create a quoted deposit address

Use `POST /v1/circle-gateway/deposit-addresses`. Set the amount in USDC base units and provide the depositor and Gateway recipient. Optional `refundRecipient` defaults to the depositor.

The following server-side TypeScript example creates an address and reads its current record. It does not transfer tokens.

```typescript theme={null}
import process from 'node:process';
import { getAddress } from 'viem';

async function main(): Promise<void> {
  const depositor = process.env.ECO_DEPOSITOR;
  const recipient = process.env.ECO_GATEWAY_RECIPIENT;
  if (!depositor || !recipient) {
    throw new Error('Set ECO_DEPOSITOR and ECO_GATEWAY_RECIPIENT');
  }

  async function request<T>(path: string, body?: unknown): Promise<T> {
    const response = await fetch(`https://api.eco.com/v1/circle-gateway${path}`, {
      method: body === undefined ? 'GET' : 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: body === undefined ? undefined : JSON.stringify(body),
      signal: AbortSignal.timeout(30_000),
    });
    const text = await response.text();
    if (!response.ok) throw new Error(`HTTP ${response.status}: ${text}`);
    return JSON.parse(text) as T;
  }

  const { data } = await request<{
    data: { vaultAddress: string; amount: string; deadline: number };
  }>('/deposit-addresses', {
    sourceChainId: 8453,
    amount: '1000000',
    recipient: getAddress(recipient),
    depositor: getAddress(depositor),
  });
  console.log(data);
  console.log(await request(
    `/deposit-addresses/${data.vaultAddress}?sourceChainId=8453`,
  ));
}

main().catch((error: unknown) => {
  console.error(error instanceof Error ? error.message : error);
  process.exitCode = 1;
});
```

A successful create request returns `201` with `data.vaultAddress`, `data.amount`, and `data.deadline` (Unix seconds). Repeating the same pending, unexpired request returns the existing address. Always retain and use the latest returned address, amount, and deadline together.

## Step 2: Fund the address

Choose a [funding method](/programmable-addresses/funding-methods):

| Method | User action |
| - | - |
| Direct transfer | Send the quoted USDC amount to `vaultAddress` and pay source-chain gas. |
| ERC-3009 | Sign a transfer authorization with `to` equal to `vaultAddress`, then submit it through the API. |
| EIP-2612 | Sign a permit with `spender` equal to `vaultAddress`, then submit it through the API. |

The address must receive at least the quoted amount before its deadline. Prefer the quoted amount exactly; do not assume an overpayment increases the destination credit.

Gasless funding means the user does not submit a gas-paying funding transaction. Check the quote separately for fees.

## Step 3: Poll for completion

Read [`GET /v1/circle-gateway/deposit-addresses/{vaultAddress}`](/api-reference/v1/gateway-lookup) with the original `sourceChainId`. The response includes the deposit `state` and `intentHash`.

| State | Meaning |
| - | - |
| `PENDING` | The deposit is waiting for sufficient funding. |
| `FUNDING_DETECTED` | The quoted funding amount has been detected. |
| `PUBLISHED` | The deposit intent has been published. This does not confirm Gateway credit. |
| `EXPIRED_UNFUNDED` | The deadline passed before sufficient funding was recorded. |
| `FAILED` | Deposit processing failed; inspect the funding and recovery state. |
| `REFUNDED_BY_USER` | The service recorded a user refund. |
| `RECOVERY_PUBLISHED` | A recovery intent was published; its publication is not a completed refund. |

For gasless funding, also read [`GET /v1/circle-gateway/deposit-addresses/status`](/api-reference/v1/gateway-status) with the bare UUID from `job.id`, without the `gasless:` prefix. Inspect `subStatuses[]` and transaction hashes if the job fails or completes only partially.

Confirm delivery through the recipient's [Circle Gateway balance](https://developers.circle.com/gateway), or track the returned delivery intent using [`GET /v1/intents/status`](/api-reference/v1/intent-status), which requires a v1 API key. If the deposit response includes `stitched.destinationIntentHash`, use that destination intent for delivery tracking.

## Troubleshooting

* **Invalid request (`400`):** check address formats, source chain, amount, and required fields. Deposit-address errors use `validationErrors` or a `details` envelope; they are not all v1 problem responses.
* **Unknown deposit (`404`):** use the address and source chain from the same create response.
* **Funding below the quote:** the balance must reach the quoted amount before the deadline. Do not top up an expired quote without checking its recovery state.
* **Failed gasless job:** inspect the source transaction hashes and deposit record before signing again. A failed job does not prove that funds never left the wallet.
* **Published but not credited:** check the delivery intent and Gateway balance. Do not count intent publication as payment completion.

Refund and recovery paths depend on the recorded state and onchain conditions. Expiry or a failed status does not itself confirm returned funds.

## Next steps

* [Gasless signing examples](/programmable-addresses/funding-methods)
* [Circle Gateway API reference](/api-reference/v1/gateway-create)
* [Testnet setup](/programmable-addresses/circle-gateway-testnet)
