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

> ## Agent Instructions
> To integrate AGG, start with Quickstart: REST (https://docs.agg.market/quickstart/rest), then Order lifecycle & statuses (https://docs.agg.market/concepts/order-lifecycle).
> Track every trade until it reaches a terminal status. Before retrying a failed or timed-out call, read Errors, retries & idempotency (https://docs.agg.market/concepts/errors).
> The API reference is generated from https://docs.agg.market/openapi/openapi.json.

# Funding & withdrawals

> Deposit addresses, balances, and withdrawals tracked to a final state, for managed accounts

<Info>
  **You'll need:** a signed-in user ([Authentication & sessions](/concepts/authentication)).
  **Result:** the user's deposit addresses, a funded balance, and a withdrawal polled to
  `completed`, `partial`, or `failed`.
</Info>

In a managed account, each user gets deposit addresses on the supported chains. The user deposits
to any of them, without picking a venue first. AGG tracks the balance per chain and moves funds to
the venue a trade routes to. Self-custody users fund from their own wallet instead; see
[Self-custody trading](/recipes/self-custody).

All calls below are user-tier: send `x-app-id` and the user's `Authorization: Bearer` token.

## 1. Get deposit addresses

`GET /execution/deposit-addresses` returns `202` with `{ "ready": false }` while the addresses are
being created. Poll until it returns `200`.

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.agg.market/execution/deposit-addresses \
    -H "x-app-id: $AGG_APP_ID" \
    -H "Authorization: Bearer $ACCESS_TOKEN"
  ```

  ```ts SDK theme={null}
  let deposit = await client.getDepositAddresses();
  while (!deposit.ready) {
    await new Promise((r) => setTimeout(r, 2000));
    deposit = await client.getDepositAddresses();
  }
  ```
</CodeGroup>

```json theme={null}
{
  "ready": true,
  "evmAddress": "0x8e2d6a1c4f7b0e3d9a5c2f8b1e6d4a7c0f3b9e25",
  "svmAddress": "5Hq3sT8mZr2vKc9Lw4NpXy7BdJfGa6UeRk1oQi3VtC8n",
  "supportedChains": [
    { "chainId": 137, "name": "Polygon", "tokens": [{ "symbol": "USDC", "address": "0x3c49...3359", "decimals": 6 }] },
    { "chainId": 8453, "name": "Base", "tokens": [{ "symbol": "USDC", "address": "0x8335...2913", "decimals": 6 }] }
  ]
}
```

`evmAddress` receives on every EVM chain in `supportedChains`. `svmAddress` receives on Solana.
Only send the tokens listed for each chain. Treat `supportedChains` as the source of truth; it can
change.

The `wallets.ready` webhook fires when a user's addresses are created.

## 2. Deposit and wait for the balance

The user sends a supported token to the address. The deposit shows in the balance after on-chain
confirmation. There is no confirm call on your side. The `deposits.confirmed` webhook fires for
each confirmed deposit.

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.agg.market/execution/balances \
    -H "x-app-id: $AGG_APP_ID" \
    -H "Authorization: Bearer $ACCESS_TOKEN"
  ```

  ```ts SDK theme={null}
  const balances = await client.getManagedBalances();
  ```
</CodeGroup>

```json theme={null}
{
  "cash": [
    {
      "tokenSymbol": "USDC",
      "totalRaw": "125000000",
      "availableRaw": "125000000",
      "reservedRaw": "0",
      "decimals": 6,
      "chains": [{ "chainId": 137, "balanceRaw": "100000000", "decimals": 6 }]
    }
  ],
  "positions": [{ "venue": "polymarket", "balance": 16.2, "costBasis": 15.3 }]
}
```

`availableRaw` is what can be spent now. `reservedRaw` is held for open limit orders and trades in
progress. Amounts are integer strings in the token's decimals: `125000000` with 6 decimals is 125
USDC. Pass `custody=self` to read the user's linked self-custody wallets instead.

To keep a minimum USDC balance on one chain after trades, see
[Managed balance refills](/recipes/managed-balance-refills).

## 3. Withdraw

Withdrawals always come from the managed balance, to any address on a supported destination chain.
Supported tokens are `USDC`, `USDC.e`, and `USDT`. Amounts are in the destination token's atomic
units (6 decimals, or 18 on BNB Chain). The minimum is one whole token. Fees come out of the
amount.

### Show the maximum

For a **Max** button, ask how much can actually arrive after fees:

```bash theme={null}
curl -X POST https://api.agg.market/execution/withdrawable/quote \
  -H "x-app-id: $AGG_APP_ID" -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "content-type: application/json" \
  -d '{ "tokenSymbol": "USDC", "destinationChainId": 8453 }'
# -> { "maxDeliverableRaw": "124880000", "rawBalanceRaw": "125000000", "decimals": 6, ... }
```

When the user picks Max, send `"max": true` on the withdrawal. The server caps the amount to what
can be delivered.

### Preview before submitting

Optional, but show it before the user confirms:

```bash theme={null}
curl -X POST https://api.agg.market/execution/withdraw/preview \
  -H "x-app-id: $AGG_APP_ID" -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "content-type: application/json" \
  -d '{
    "amountRaw": "50000000",
    "tokenSymbol": "USDC",
    "destinationAddress": "0x2f9a4c7e1b3d6f8a0c5e9b2d4f7a1c3e6b8d0f52",
    "destinationChainId": 8453
  }'
```

The response has `receiveAmountRaw`, `feeRaw`, `pricingStatus` (`quoted` or `unviable`),
`unviableReason`, and `quoteExpiresAt`. The preview creates nothing.

### Submit

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.agg.market/execution/withdraw \
    -H "x-app-id: $AGG_APP_ID" -H "Authorization: Bearer $ACCESS_TOKEN" \
    -H "content-type: application/json" \
    -d '{
      "requestId": "8a3f5c2e-1b7d-4e9a-9c6f-2d4b8e1a7c30",
      "amountRaw": "50000000",
      "tokenSymbol": "USDC",
      "destinationAddress": "0x2f9a4c7e1b3d6f8a0c5e9b2d4f7a1c3e6b8d0f52",
      "destinationChainId": 8453
    }'
  ```

  ```ts SDK theme={null}
  const withdrawal = await client.withdrawManaged({
    requestId: crypto.randomUUID(),
    amountRaw: "50000000",
    tokenSymbol: "USDC",
    destinationAddress: "0x2f9a4c7e1b3d6f8a0c5e9b2d4f7a1c3e6b8d0f52",
    destinationChainId: 8453,
  });
  ```
</CodeGroup>

The response has a `withdrawalId` and `status: "pending"`.

`requestId` is an optional UUID that makes an exact-amount withdrawal safe to retry: the same
`requestId` and body return the original withdrawal instead of sending twice, and a changed body
returns `409`. Do not combine `requestId` with `max`.

### Poll to a final state

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.agg.market/execution/withdrawals/$WITHDRAWAL_ID \
    -H "x-app-id: $AGG_APP_ID" -H "Authorization: Bearer $ACCESS_TOKEN"
  ```

  ```ts SDK theme={null}
  const terminal = new Set(["completed", "partial", "failed"]);
  let w = await client.getWithdrawalStatus(withdrawal.withdrawalId);
  while (!terminal.has(w.status)) {
    await new Promise((r) => setTimeout(r, 3000));
    w = await client.getWithdrawalStatus(withdrawal.withdrawalId);
  }
  ```
</CodeGroup>

| `status` | Terminal | Meaning |
| - | - | - |
| `pending` | No | Accepted, not started. |
| `bridging` | No | Moving funds across chains. |
| `transferring` | No | Same-chain transfer in progress. |
| `completed` | Yes | Delivered. `completedAmountRaw` is the amount delivered. |
| `partial` | Yes | Some sources delivered. See `completedAmountRaw` and `sources[]`. |
| `failed` | Yes | Nothing delivered. See `errorMessage`. |

`legs[]` and `sources[]` carry per-transfer status and `txHash` values.

## Related

<CardGroup cols={2}>
  <Card title="Managed balance refills" href="/recipes/managed-balance-refills">
    Keep a USDC minimum on a chosen chain.
  </Card>

  <Card title="Webhooks" href="/recipes/webhooks/overview">
    `wallets.ready` and `deposits.confirmed` events.
  </Card>
</CardGroup>
