# Keeping every token

> Keep a backend's copy of every token current by polling with since.

This page is part of the Intear API docs. The Intear API is at `https://api.intea.rs` and `wss://api.intea.rs/ws`, with no API key. https://docs.intear.tech/api/llms-full.txt has all of its pages in one file, and https://docs.intear.tech/llms.txt lists every page of the Intear docs.

A backend that keeps every token doesn't need to download all of them each time. Poll [`tokens.get`](https://docs.intear.tech/api/reference/tokens.md#tokensget) (or `GET /tokens`) with `since` set to the `height` of the result before, and get only what changed:

1. Fetch every token once, and remember the result's `height`.
2. Every few seconds, fetch again with `since` set to that `height`.
3. If the result has `"resumed": true`, `rows` are only the tokens that changed, each with every field you asked for. Replace them, drop the tokens in `left`, which stopped matching `where`, and remember the new `height`.
4. If it has `"resumed": false`, the server couldn't work out what changed (it restarted since), and `rows` has every token. Start over with them.

```js
/**
 * Turns a table into `{ <key>: { <column>: value } }`, keyed by its first column, for tables where
 * it's unique, so not balances or positions
 */
function tableToObjects({ columns, rows }) {
  const objects = {};
  for (const row of rows) {
    const object = {};
    columns.slice(1).forEach((column, i) => (object[column] = row[i + 1]));
    objects[String(row[0])] = object;
  }
  return objects;
}

const params = new URLSearchParams({ fields: 'symbol,decimals,price_usd' });
if (since !== undefined) params.set('since', String(since));
const response = await fetch(`https://api.intea.rs/tokens?${params}`);
const result = await response.json();
if (!response.ok) throw new Error(result.error.message);

if (!result.resumed) tokens.clear(); // every token is in rows
for (const [token, fields] of Object.entries(tableToObjects(result))) tokens.set(token, fields);
for (const token of result.left ?? []) tokens.delete(token);
// Poll again with `since: result.height`
```

The whole file, tested in CI: https://docs.intear.tech/snippets/js/src/intear-api.js

`since` can't be combined with `sort`, `limit` or `offset`, and the other params have to be the same as in the earlier request.

With `min_change`, the values are the ones subscribers with the same thresholds were sent. A threshold is kept for 10 minutes after it was last used, so polling more often than that with `since` only gets what crossed it.
