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

# Track deposits

> Poll deposit status by source transaction hash and handle terminal outcomes.

Poll `GET /deposits` by source transaction hash to track a deposit through settlement. Use [webhooks](/deposits/headless/processing-and-tracking/webhooks) for event-driven updates.

## Poll a deposit

Query the `GET /deposits` endpoint with the `txHash` parameter to look up a deposit by its source transaction hash.

```ts theme={null}
const DEPOSIT_SERVICE_URL =
    "https://v1.orchestrator.rhinestone.dev/deposit-processor";
const API_KEY = "YOUR_RHINESTONE_API_KEY";

const txHash = "0xabc123...";

const response = await fetch(
    `${DEPOSIT_SERVICE_URL}/deposits?txHash=${txHash}`,
    {
        headers: { "x-api-key": API_KEY },
    },
);

const { deposits } = await response.json();
```

### Response

Each item in the `deposits` array has the following shape:

| Field | Type | Description |
| - | - | - |
| `id` | `string` | Unique deposit identifier |
| `chain` | `string` | Source chain (CAIP-2) |
| `txHash` | `string` | Source transaction hash |
| `token` | `string` | Deposit token address |
| `amount` | `string` | Deposit amount (raw token units) |
| `sender` | `string` | Sender address |
| `account` | `string` | Registered account address |
| `targetChain` | `string` | Destination chain (CAIP-2) |
| `targetToken` | `string` | Destination token address |
| `status` | `string` | In-progress: `"pending"`, `"processing"`, `"delayed"`, `"expecting_refund"`. Terminal: `"completed"`, `"failed"`, `"rejected"`, `"refunded"`, `"ignored"` |
| `sourceTxHash` | `string \| null` | Bridge source transaction hash |
| `destinationTxHash` | `string \| null` | Bridge destination transaction hash |
| `sourceAmount` | `string \| null` | Bridge source amount |
| `destinationAmount` | `string \| null` | Bridge destination amount |
| `errorCode` | `string \| null` | [Error code](/deposits/headless/processing-and-tracking/deposit-processing#error-codes) if the deposit failed |
| `createdAt` | `string` | ISO 8601 timestamp of when the deposit was detected |
| `completedAt` | `string \| null` | ISO 8601 timestamp of when the deposit completed |
| `retryable` | `boolean` | Whether a failed deposit can be retried — `false` for non-retryable errors and policy rejections |
| `isSpam` | `boolean` | Flagged as spam (token has no known price); omitted from results unless you pass `includeSpam=true` |
| `timing` | `object \| undefined` | Optional arrival estimate: `expectedSeconds`, `softDelaySeconds`, `escalatedDelaySeconds`, measured from `createdAt`. Served only while the deposit is in flight (`pending`, `processing`, `delayed`) |

The `timing` estimate is indicative, never a deadline or an SLA. It is resolved per
request, so it can change between reads, and it is omitted whenever no estimate is
available — treat its absence as normal. Full schema:
[`GET /deposits`](/api-reference/deposit-service/utilities/list-deposits).
The [deposit modal](/deposits/overview/widget/callbacks-and-error-handling#arrival-estimates) uses it to set
the user's expectation while a deposit is in flight.

### Polling loop

Poll until the deposit reaches a terminal status (`completed`, `failed`, `rejected`, `refunded`, or `ignored`):

```ts theme={null}
const TERMINAL = new Set(["completed", "failed", "rejected", "refunded", "ignored"]);

async function waitForDeposit(txHash: string): Promise<void> {
    const url = `${DEPOSIT_SERVICE_URL}/deposits?txHash=${txHash}`;
    const headers = { "x-api-key": API_KEY };

    while (true) {
        const response = await fetch(url, { headers });
        const { deposits } = await response.json();
        const deposit = deposits[0];

        if (!deposit) {
            // Deposit not yet indexed — wait and retry
            await new Promise((r) => setTimeout(r, 1_000));
            continue;
        }

        if (TERMINAL.has(deposit.status)) {
            // `rejected` carries an errorCode (whitelist/minimum); see deposit-rejected
            console.log("Deposit settled:", deposit.status, deposit.errorCode ?? deposit.destinationTxHash);
            return;
        }

        // Still in progress (`processing` / `expecting_refund`) — poll again
        await new Promise((r) => setTimeout(r, 1_000));
    }
}
```

<Tip>
  A 1-second interval works well for most use cases. Most deposits complete
  within seconds.
</Tip>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.