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

# Build a market-data bot

> Discover Shield Swap markets, load indexed state, request routes, and recover after data-source failures.

This guide covers data collection and route lookup. It does not cover record selection, proving, transaction submission, or claims.

## Before you start

You need:

* Node.js with built-in `fetch`
* an invited wallet
* an `ss_...` API token stored outside source control
* exact-integer handling for token amounts and field identifiers

Pool and token discovery are public. Routes, history, positions, swaps, balances, and detailed market reads require the API token.

## 1. Create an API client

```javascript theme={"languages":{"custom":["/languages/leo.tmLanguage.json"]}}
const baseUrl = "https://api.swap.shield.fi";
const apiToken = process.env.SHIELD_SWAP_API_TOKEN;

if (!apiToken) {
  throw new Error("Set SHIELD_SWAP_API_TOKEN before starting the bot");
}

async function getJson(path, { publicEndpoint = false } = {}) {
  const response = await fetch(`${baseUrl}${path}`, {
    headers: publicEndpoint
      ? {}
      : { Authorization: `Bearer ${apiToken}` },
  });

  if (!response.ok) {
    throw new Error(`${path} returned ${response.status}`);
  }

  return response.json();
}
```

Create the token through the wallet-session flow in [Authentication](./authentication).

## 2. Discover tokens and pools

```javascript theme={"languages":{"custom":["/languages/leo.tmLanguage.json"]}}
const [{ data: tokens }, { data: pools }] = await Promise.all([
  getJson("/tokens", { publicEndpoint: true }),
  getJson("/pools?limit=100&offset=0", { publicEndpoint: true }),
]);
```

Continue requesting pool pages until `data` is empty or `pagination` shows that all rows have been returned. Keep the exact pool key, token IDs, fee, and scale values.

## 3. Load the data your strategy uses

Do not fetch every endpoint for every pool. Request only the resources needed by the strategy:

* `GET /pools/{key}` for public pool metadata
* `GET /pools/{key}/stats` for current indexed statistics
* `GET /pools/{key}/trades` for trade history
* `GET /pools/{key}/ohlcv` for candles
* `GET /swaps` for indexed swap history

When the API encodes an amount as a JSON string, parse it with an arbitrary-precision integer type. Never pass it through JavaScript `number`.

## 4. Request a route

```javascript theme={"languages":{"custom":["/languages/leo.tmLanguage.json"]}}
const query = new URLSearchParams({
  token_in: inputToken,
  token_out: outputToken,
  amount_in: "1000000",
});

const route = await getJson(`/route?${query}`);
```

The router returns at most three hops. A route is current indexed guidance, not an execution guarantee. Before submission, apply the transaction's price limit, minimum output, deadline, record checks, and final-state reconciliation.

## 5. Refresh state safely

Use request timeouts, bounded exponential backoff, jitter, and a maximum retry count.

| Response            | Bot action                                         |
| ------------------- | -------------------------------------------------- |
| `401`               | Replace or reissue the API token                   |
| `403`               | Stop; the wallet does not have the required access |
| `404` from `/route` | Treat the route as unavailable                     |
| `429`               | Wait before retrying                               |
| transient `5xx`     | Retry within the bounded policy                    |

If the bot uses a browser wallet session, it can request a short-lived WebSocket ticket and follow the [WebSocket feed](./websocket). After any disconnect, reload REST state before acting on new events.

## Transaction boundary

The API supplies indexed data, routes, and current input schemas. Your wallet or proving client still owns:

* token-record selection and reservation
* transaction construction and signing
* proof generation and submission
* swap-output claim handling
* accepted, rejected, and unknown transaction states
* final public-state and record reconciliation

Continue with [Transaction execution](../developers/transaction-execution) when the bot must submit trades.
