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

# Server-side integration

> Call Rheon from your own backend with an API key, and keep your own UI.

This is the path for a product that already has its own deposit screen. You keep
your UI; we price the route, hand back an unsigned transaction, and tell you when
the money landed.

It is the same three calls the widget makes, on the same rails. The only
differences are the `/v1` prefix and an API key -
see [Authentication](/api-reference/authentication).

<Note>
  Non-custodial throughout. We never hold the funds and never sign: the transaction
  we return is unsigned and your user's wallet signs it. Nothing sits with us
  between the payer and the merchant.
</Note>

## The flow

<Steps>
  <Step title="Price it">
    `POST /v1/deposit/quote` with where the money comes from, where it should
    land, and the amount.

    Decide which side the amount pins down. `exact-in` means the payer spends
    exactly that and whatever arrives, arrives. `target-out` (exact out) means a
    fixed figure must land and the payer's side flexes to cover it - this is the
    one you want when you are collecting a set price.

    See [Quote a deposit](/api-reference/deposit-quote).
  </Step>

  <Step title="Build the transaction">
    `POST /v1/deposit/transaction` with the quote you got back. You receive an
    unsigned transaction, and an approval transaction before it when the token
    allowance is not enough.

    See [Build the transaction](/api-reference/deposit-transaction).
  </Step>

  <Step title="Let the user sign">
    Your frontend submits it from the user's wallet. Nothing reaches us here.
  </Step>

  <Step title="Track it">
    `POST /v1/deposit/status` with the receipt from the submitted transaction.
    Poll it until it is done.

    See [Check status](/api-reference/deposit-status).
  </Step>
</Steps>

## Settling somewhere other than Arbitrum

By default the money lands as USDC on Arbitrum. To settle elsewhere, name both
`destination.chain` and `destination.token` on the quote. Both or neither - the
chain alone would keep Arbitrum's token address on a chain where it does not
exist, so we refuse it.

Your key has to be enabled for that chain as a destination. If it is not, you get
`403 chain_not_allowed` rather than a quote you could not have used. That is your
account setup talking, not a security control - see
[Authentication](/api-reference/authentication).

## Quotes expire

A quote reserves liquidity, so it is only good for a short window and the window is
short on purpose. Two things follow for your UI:

* Show the user how long is left, and give them a way to ask for a fresh quote.
* Do not build a transaction from a quote you have been sitting on. Re-quote and
  build from the new one.

## Before you go live

<Check>Handle `403 chain_not_allowed` - it means the corridor was never yours, so retrying will not help.</Check>
<Check>Handle `429` by backing off, not by retrying immediately.</Check>
<Check>Treat `no_route` as a normal, temporary answer - liquidity moves.</Check>
<Check>Keep the key on your server and out of anything a browser can read.</Check>
