> ## 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.

# API quickstart

> Set up the Deposit API and process your first cross-chain deposit.

Register a managed account, deposit USDC on one chain, and receive it on another.

<Tip>
  Building in React? The [deposit widget](/deposits/widget/quickstart) ships this flow as
  a component — UI, funding methods, withdrawals and refunds included — on top of the
  same API.
</Tip>

<Warning>
  This runs on mainnet and moves real funds. The deposit step below sends 1 USDC —
  keep it small until the flow works end to end.
</Warning>

## Prerequisites

* A [Rhinestone API key](https://tally.so/r/wg22x4)
* A wallet with USDC on Arbitrum

<Steps>
  <Step title="Configure your client">
    Set up gas sponsorship so deposit bridging is covered. This is a one-time call per API key.

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

    const response = await fetch(`${DEPOSIT_SERVICE_URL}/setup`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "x-api-key": API_KEY,
      },
      body: JSON.stringify({
        params: {
          sponsorship: {
            "eip155:8453": { gas: "all" }, // Base
            "eip155:42161": { gas: "all" }, // Arbitrum
          },
        },
      }),
    });

    console.log(`Setup: ${response.status}`);
    ```

    You should see `Setup: 200`.
  </Step>

  <Step title="Register a managed account">
    Register a server-managed account with a target chain and token. The service creates a smart account deterministically from your API key and the salt you provide, and returns deposit addresses.

    ```ts theme={null}
    import { keccak256, toHex } from "viem";

    // Use any unique identifier per user (e.g., internal user ID)
    const salt = keccak256(toHex("user-123"));

    const RECIPIENT = "0xYOUR_RECIPIENT_ADDRESS";
    const TARGET_CHAIN = "eip155:8453"; // Base
    const TARGET_TOKEN = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"; // USDC on Base

    const registerResponse = await fetch(
      `${DEPOSIT_SERVICE_URL}/register-managed`,
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "x-api-key": API_KEY,
        },
        body: JSON.stringify({
          account: {
            salt,
            target: {
              chain: TARGET_CHAIN,
              token: TARGET_TOKEN,
              recipient: RECIPIENT,
            },
          },
        }),
      },
    );

    const { evmDepositAddress, solanaDepositAddress } =
      await registerResponse.json();
    console.log(`EVM deposit address: ${evmDepositAddress}`);
    console.log(`Solana deposit address: ${solanaDepositAddress}`);
    ```

    You should see two deposit addresses printed. The `evmDepositAddress` is where users send tokens on any supported EVM chain.
  </Step>

  <Step title="Verify registration">
    ```ts theme={null}
    const check = await fetch(`${DEPOSIT_SERVICE_URL}/check/${evmDepositAddress}`, {
      headers: { "x-api-key": API_KEY },
    });
    const checkData = await check.json();
    console.log(checkData);
    ```

    You should see:

    ```json theme={null}
    {
      "isRegistered": true,
      "targetChain": "eip155:8453",
      "targetToken": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "sources": [
        { "chain": "eip155:8453", "depositAddress": "<evmDepositAddress>" },
        { "chain": "eip155:42161", "depositAddress": "<evmDepositAddress>" },
        { "chain": "eip155:10", "depositAddress": "<evmDepositAddress>" }
      ]
    }
    ```
  </Step>

  <Step title="Deposit tokens">
    Transfer USDC to the deposit address on Arbitrum. The deposit service detects it and bridges it to Base automatically.

    ```ts theme={null}
    import {
      createWalletClient,
      http,
      encodeFunctionData,
      erc20Abi,
      parseUnits,
    } from "viem";
    import { privateKeyToAccount } from "viem/accounts";
    import { arbitrum } from "viem/chains";

    const funder = privateKeyToAccount("0xYOUR_FUNDING_KEY");
    const walletClient = createWalletClient({
      account: funder,
      chain: arbitrum,
      transport: http(),
    });

    // USDC on Arbitrum
    const USDC = "0xaf88d065e77c8cC2239327C5EDb3A432268e5831";

    const txHash = await walletClient.sendTransaction({
      to: USDC,
      data: encodeFunctionData({
        abi: erc20Abi,
        functionName: "transfer",
        args: [evmDepositAddress, parseUnits("1", 6)],
      }),
    });

    console.log(`Deposit tx: ${txHash}`);
    ```
  </Step>

  <Step title="Check deposit status">
    Poll the deposits endpoint by transaction hash to track the bridging progress. See [status tracking](/deposits/api/status-tracking#polling) for the full response schema.

    ```ts theme={null}
    async function waitForDeposit(txHash: string) {
      const url = `${DEPOSIT_SERVICE_URL}/deposits?txHash=${txHash}`;

      while (true) {
        const response = await fetch(url, {
          headers: { "x-api-key": API_KEY },
        });
        const { deposits } = await response.json();
        const deposit = deposits[0];

        if (deposit?.status === "completed") {
          console.log("Deposit completed:", deposit.destinationTxHash);
          return deposit;
        }

        if (deposit?.status === "failed") {
          console.error("Deposit failed:", deposit.errorCode);
          return deposit;
        }

        await new Promise((r) => setTimeout(r, 1_000));
      }
    }

    await waitForDeposit(txHash);
    ```

    Once bridging completes, the deposit status changes to `completed` and includes the destination transaction hash. The USDC is now at the recipient address on Base.
  </Step>
</Steps>

## Next steps

<CardGroup cols={2}>
  <Card title="Initial setup" icon="settings" href="/deposits/api/initial-setup">
    Webhooks, sponsorship rules, and deposit whitelists.
  </Card>

  <Card title="Account registration" icon="user-plus" href="/deposits/api/account-registration">
    User-owned accounts, session configuration, and output token rules.
  </Card>

  <Card title="Deposit processing" icon="arrow-right-left" href="/deposits/api/deposit-processing">
    Deposit lifecycle, retries, and status tracking.
  </Card>

  <Card title="Status tracking" icon="activity" href="/deposits/api/status-tracking">
    Track deposits via polling or webhooks.
  </Card>
</CardGroup>
