# Quickstart

> Create an API key and read your first rows from the Aggre data API in a few minutes.

Page: https://docs.aggre.org/quickstart · Section: Get started · All pages: https://docs.aggre.org/llms.txt

You need an account in the console, an API key, and any HTTP client. The data API is called from a server, script or agent: it sends no CORS headers, so a browser page cannot call it directly.

## 1. Create a key {#create-a-key}

1. Open the [console](https://app.aggre.org/login) and sign in with one of the providers it offers. The first sign-in creates your personal account; there is no separate sign-up.
2. Open **API keys** in your account and create a key. Give it a name you will recognise.
3. Copy the secret. It looks like `aggre_sk_` followed by 43 characters, and **it is shown once**. Only a hash is stored, so a lost key cannot be recovered; create a new one and revoke the old one.

Keep the key out of source control and logs. More on keys, quotas and revocation: [Authentication](https://docs.aggre.org/authentication.md) and [API keys in the console](https://docs.aggre.org/console/api-keys.md).

```bash
export AGGRE_API_KEY="aggre_sk_..."
```

## 2. Check the key {#check-the-key}

`GET /v1/whoami` describes the key you call with (never its secret) and what it has used in its current period.

```bash
curl -s https://api.aggre.org/v1/whoami \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

The answer has this shape (values are illustrative):

```json
{
  "data": {
    "key_id": "6b0e0c1e-0000-0000-0000-000000000000",
    "key_prefix": "aggre_sk_ab12cd34",
    "name": "my first key",
    "account": "my-handle",
    "rate_policy": "default",
    "ip_allowlist_configured": false,
    "usage": { "period": "month", "limit": 100000, "used": 2 }
  }
}
```

If you get `401 unauthorized`, the key is missing, mistyped or revoked. The header `X-API-Key: aggre_sk_...` is accepted as an alternative to `Authorization: Bearer`.

## 3. See what exists {#list-datasets}

```bash
curl -s https://api.aggre.org/v1/datasets \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

Each entry is `{ "id", "title", "path", "store_kind" }`. `path` is where to read the dataset, for example `/v1/finance/market/candles_1d`.

## 4. Read rows {#read-rows}

Daily candles of one instrument, newest first, three rows:

```bash
curl -s "https://api.aggre.org/v1/finance/market/candles_1d?instrument_id=OKX:SPOT:SOL-USDC&limit=3" \
  -H "Authorization: Bearer $AGGRE_API_KEY"
```

Every data route answers in the same envelope ([Response format](https://docs.aggre.org/concepts/response-format.md)):

```json
{
  "data": [
    { "instrument_id": "OKX:SPOT:SOL-USDC", "venue": "OKX", "product": "SPOT", "symbol": "SOLUSDC",
      "ts": 1767139200000, "open": 0, "high": 0, "low": 0, "close": 0, "volume": 0, "quote_volume": null, "version": 0 }
  ],
  "meta": { "source": "okx", "status": "ok", "fetchedAt": "2026-01-01T00:00:00Z", "dataDate": "2025-12-31T00:00:00Z", "message": null },
  "next_cursor": null
}
```

The numbers above are placeholders to show the shape, not data. Look at `meta.status`: `ok`, `stale` (our last read is older than the dataset's window) or `empty` (nothing matched or nothing has been read yet).

The same call from code:

```python
import os, requests

r = requests.get(
    "https://api.aggre.org/v1/finance/market/candles_1d",
    params={"instrument_id": "OKX:SPOT:SOL-USDC", "limit": 3},
    headers={"Authorization": f"Bearer {os.environ['AGGRE_API_KEY']}"},
    timeout=30,
)
r.raise_for_status()
body = r.json()
print(body["meta"]["status"], len(body["data"]))
```

```javascript
const res = await fetch(
  "https://api.aggre.org/v1/finance/market/candles_1d?instrument_id=OKX:SPOT:SOL-USDC&limit=3",
  { headers: { Authorization: `Bearer ${process.env.AGGRE_API_KEY}` } },
);
if (!res.ok) throw new Error(`${res.status} ${(await res.json()).error.code}`);
const { data, meta, next_cursor } = await res.json();
```

## 5. Handle the common failures {#failures}

| You see | Meaning | Do |
|---|---|---|
| `400 invalid_request` | An unknown or repeated query parameter, or a value out of range. Parameters are strict, never ignored. | Fix the request. |
| `401 unauthorized` | No key, a wrong key, or a revoked key. | Check the header and the key. |
| `429 rate_limited` | Too many requests from your IP. | Wait `Retry-After` seconds and retry. |
| `429 usage_limit_exceeded` | The key's quota for its period is spent. | Do not retry; use another key or wait for the period to roll. |
| `503 terms_unread` | The source's publisher terms have not been recorded as read yet. | Not retryable now. See [Freshness and availability](https://docs.aggre.org/concepts/freshness.md). |

Every response carries `x-request-id`; quote it when you ask for help. The full list is in [Errors](https://docs.aggre.org/concepts/errors.md).

## Next

- Page through results: [Pagination](https://docs.aggre.org/concepts/pagination.md).
- Pick data: [Datasets](https://docs.aggre.org/datasets.md) and the [Data API reference](https://docs.aggre.org/api/data.md).
- Show data to people: [Attribution](https://docs.aggre.org/concepts/attribution.md) (`credit` and `attribution` must be shown with the rows).
