> The index of these docs, for agents: https://traktor.fun/llms.txt

# Quickstart

A first request and a first stream subscription, made with a new API key.

Every step below works on the Free plan, which a new account starts on.

## Create a key

Sign in on traktor.fun and open the [API tab](https://traktor.fun/profile?tab=api) of your profile. Create a key there and copy it: the dialog shows it once, and the API keeps only its hash.

Keep the key in your environment, never in code. The dialog offers this line ready to copy:

```bash
export TRAKTOR_API_KEY=tk_live_…
```

## Make a request

Send the key as a bearer token. This request asks for the five newest events on the signal feed:

```bash cURL
curl -s "https://api.traktor.fun/v1/signals?limit=5" \
  -H "Authorization: Bearer $TRAKTOR_API_KEY"
```

```ts TypeScript
const response = await fetch("https://api.traktor.fun/v1/signals?limit=5", {
  headers: { Authorization: `Bearer ${process.env.TRAKTOR_API_KEY}` },
});
const body = await response.json();
if (!response.ok) throw new Error(`${response.status} ${body.error.code}: ${body.error.message}`);
console.log(body.data.length, body.meta.page.cursor);
```

```python Python
import os
import requests

response = requests.get(
    "https://api.traktor.fun/v1/signals",
    params={"limit": 5},
    headers={"Authorization": f"Bearer {os.environ['TRAKTOR_API_KEY']}"},
)
body = response.json()
if not response.ok:
    raise SystemExit(f"{response.status_code} {body['error']['code']}: {body['error']['message']}")
print(len(body["data"]), body["meta"]["page"]["cursor"])
```

`data` holds the events. For the next page, send `meta.page.cursor` back as `cursor` with the same filters and order ([Paging](https://traktor.fun/docs/signals.md#paging)). A refused request answers with an error and its `code`: [Authentication](https://traktor.fun/docs/authentication.md) covers a `401`, and [Errors](https://traktor.fun/docs/errors.md) lists every code.

## Open the stream

Connect with the `traktor.v1` subprotocol, send your key in the first frame, then subscribe to a filter:

```ts TypeScript
const ws = new WebSocket("wss://api.traktor.fun/v1/stream", "traktor.v1");
ws.onmessage = (message) => {
  const frame = JSON.parse(String(message.data));
  if (frame.op === "hello") ws.send(JSON.stringify({ op: "auth", id: "auth-1", key: process.env.TRAKTOR_API_KEY }));
  else if (frame.op === "ack" && frame.re === "auth-1") ws.send(JSON.stringify({ op: "subscribe", id: "sub-1", sub: "big-buys", filter: { side: "buy", minUsd: "1k" } }));
  else if (frame.op === "events") for (const trade of frame.d) console.log(trade.chain, trade.usdAmount);
  else if (frame.op === "error" || frame.op === "bye") console.error(frame);
};
```

```python Python
import asyncio
import json
import os

import websockets


async def main():
    async with websockets.connect("wss://api.traktor.fun/v1/stream", subprotocols=["traktor.v1"]) as ws:
        await ws.send(json.dumps({"op": "auth", "id": "auth-1", "key": os.environ["TRAKTOR_API_KEY"]}))
        async for message in ws:
            frame = json.loads(message)
            if frame["op"] == "ack" and frame["re"] == "auth-1":
                await ws.send(json.dumps({"op": "subscribe", "id": "sub-1", "sub": "big-buys", "filter": {"side": "buy", "minUsd": "1k"}}))
            elif frame["op"] == "events":
                for trade in frame["d"]:
                    print(trade["chain"], trade["usdAmount"])
            elif frame["op"] in ("error", "bye"):
                print(frame)


asyncio.run(main())
```

- `hello` arrives first. The key travels only in the `auth` frame, never in the URL.
- Each `events` frame carries a batch of trades in `d`, one trade per element.

The stream carries only `origin: "live"` trades: one Traktor recovers later, with `origin` `sweep` or `backfill`, never reaches it. [Resume](https://traktor.fun/docs/stream.md#resume) covers picking up where you left off after a disconnect.

## Set up a coding agent

Paste this prompt into a coding agent. It sends the agent to `llms.txt` first, and tells it to read your key from the environment, never from the chat.

```text
Set up the Traktor API in this project.
Read https://traktor.fun/llms.txt first, then the pages it lists that this task needs.

- The base URL is https://api.traktor.fun and every route sits under /v1; the streams connect at wss://api.traktor.fun.
- Read the key from the TRAKTOR_API_KEY environment variable. Authenticate a REST request with `Authorization: Bearer $TRAKTOR_API_KEY`; on the `traktor.v1` stream, send the key in the first frame, the `auth` op.
- Never ask the user to paste an API key into the chat. If TRAKTOR_API_KEY is not set, ask them to create a key at https://traktor.fun/profile?tab=api and export it in their shell.
- The API reads market data and manages the account's alerts and notifications; no route places, changes or cancels an order or moves funds, so never offer to trade for the user: trading happens in the traktor app.
- Branch on an error's `code`, never its message; https://traktor.fun/docs/errors.md lists every code.
- Every page of these docs is Markdown at its URL plus .md, and https://traktor.fun/llms-full.txt holds them all.
```
