# xchgo API

Add cross-chain swaps and reusable conversion addresses from a trusted backend.

- Base URL: `https://xchgo.com/api/v1`
- OpenAPI: `https://xchgo.com/api/v1/openapi.json`
- Node SDK: `https://xchgo.com/sdk/xchgo-client.mjs`
- Support: `support@xchgo.com`

## Credentials

Each partner receives a key ID and shared secret. Keep both on your backend. The
SDK signs requests automatically.

```js
import {
  createXchgoClient,
  createIdempotencyKey
} from "./xchgo-client.mjs";

const xchgo = createXchgoClient({
  baseUrl: process.env.XCHGO_API_BASE,
  audience: process.env.XCHGO_API_AUDIENCE,
  keyId: process.env.XCHGO_KEY_ID,
  sharedSecret: process.env.XCHGO_SHARED_SECRET,
  userId: customer.id
});
```

Set `XCHGO_API_AUDIENCE=https://xchgo.com`.

## One-time swaps

1. Load `GET /assets` and `GET /pairs`.
2. Request `POST /quotes`.
3. Display the returned amount, fee, limits, and expiry.
4. Create with `POST /swaps` using the quote ID.
5. Wait for `depositAddress`, then track `GET /swaps/{id}`.

```js
const { quote } = await xchgo.quote({
  sourceAsset: "BTC",
  sourceNetwork: "BTC",
  destinationAsset: "ETH",
  destinationNetwork: "ETH",
  sourceAmount: "0.01",
  rateType: "best",
  refundMode: "sender"
});

const idempotencyKey = createIdempotencyKey();
const result = await xchgo.createSwap({
  sourceAsset: "BTC",
  sourceNetwork: "BTC",
  destinationAsset: "ETH",
  destinationNetwork: "ETH",
  sourceAmount: "0.01",
  destinationAddress: customer.ethAddress,
  rateType: quote.rateType,
  refundMode: "sender",
  quoteId: quote.id
}, { idempotencyKey });
```

Persist the idempotency key before creating the swap. If the response is lost,
retry the identical body with the same key. A response is not always terminal;
track `terminal` and `actionRequired`.

## Reusable conversion addresses

1. `POST /permanent-routes/challenges`
2. Sign the returned message with the destination wallet.
3. `POST /permanent-routes`
4. `GET /permanent-routes/{id}/deposits`

The same partner user and verified destination recover the existing route. Use
the addresses, status, fee cap, minimum, and automatic-processing maximum returned
by the API. Deposits below the minimum accumulate only with later deposits of
the same asset. Call `POST /permanent-routes/{id}/expect-deposit` before an
expected payment for faster polling.

## Endpoints

| Method | Path |
| --- | --- |
| GET | `/health` |
| GET | `/assets` |
| GET | `/pairs` |
| POST | `/quotes` |
| GET, POST | `/swaps` |
| GET | `/swaps/{id}` |
| GET, PUT | `/partner/webhook` |
| GET, PUT | `/partner/markup` |
| GET | `/partner/earnings` |
| POST | `/permanent-routes/challenges` |
| GET, POST | `/permanent-routes` |
| GET | `/permanent-routes/{id}` |
| GET | `/permanent-routes/{id}/deposits` |
| POST | `/permanent-routes/{id}/expect-deposit` |

Full request and response schemas are in OpenAPI.

## Errors

Errors use `{ "error": { "code": "…", "message": "…" } }`. Correct invalid
requests, refresh unavailable or expired quotes, and retry rate limits or
temporary service errors with backoff. Use `Retry-After` when returned.
