> For the complete documentation index, see [llms.txt](https://docs.tokenbot.com/home/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tokenbot.com/home/api-docs/authentication.md).

# Authentication

TokenBot supports a few authentication methods depending on which API you're calling.

| API         | Methods                                                             |
| ----------- | ------------------------------------------------------------------- |
| REST API    | **API key** (primary) or **signed request** (CLI fast-path)         |
| GraphQL API | CLI **signed request** (canonical) or **JWT** bearer token (legacy) |

***

## REST API Authentication

### API Key (primary)

Send your API key via the `X-API-Key` header:

```bash
curl https://api.tokenbot.com/v1/exchanges \
  -H "X-API-Key: tb_live_your_api_key"
```

You can also pass the same key as a bearer token — it's treated identically:

```bash
curl https://api.tokenbot.com/v1/exchanges \
  -H "Authorization: Bearer tb_live_your_api_key"
```

> Note: the REST API does **not** verify standalone JWTs. `Authorization: Bearer <value>` is interpreted as an API key.

#### API Key Format

| Environment | Format          | Example             |
| ----------- | --------------- | ------------------- |
| Production  | `tb_live_<...>` | `tb_live_a1b2c3...` |
| Test        | `tb_test_<...>` | `tb_test_a1b2c3...` |

#### Managing API Keys

Create and manage keys with the CLI:

```bash
tokenbot apikey create --name "ci-bot" --env live
tokenbot apikey list
tokenbot apikey revoke <id>
```

Or via the REST endpoints (these require a key with **ADMIN** permission):

| Operation | Endpoint                       |
| --------- | ------------------------------ |
| Create    | `POST /v1/api-keys`            |
| List      | `GET /v1/api-keys`             |
| Revoke    | `DELETE /v1/api-keys/:id`      |
| Rotate    | `POST /v1/api-keys/:id/rotate` |

### Signed Request (CLI fast-path)

The `tokenbot` CLI authenticates with a **secp256k1 keypair** instead of an API key. Each request carries four headers and a signature; no key is transmitted. The REST API verifies the signature first, and falls back to API-key auth when these headers are absent.

| Header           | Value                                             |
| ---------------- | ------------------------------------------------- |
| `x-tb-pubkey`    | Your compressed public key (hex)                  |
| `x-tb-timestamp` | Unix milliseconds                                 |
| `x-tb-nonce`     | 16 random bytes (hex)                             |
| `x-tb-sig`       | secp256k1 signature (hex) of the canonical string |

The **canonical string** that gets signed is:

```
${METHOD}\n${path}\n${timestamp}\n${nonce}\n${sha256(body)}
```

where `path` includes the query string and `body` is the raw request body (the empty string hashes to the SHA-256 of `""`). Requests are accepted within a ±60-second clock-skew window, and nonces are remembered for a 10-minute replay window.

> This scheme is implemented for you by `@tokenbot-org/cli-core`; you normally don't construct it by hand. It's documented here so server integrations can verify it.

***

## GraphQL API Authentication

The production GraphQL API is an **Express server** (deployed on ECS Fargate) at `https://gql-api.tokenbot.com/graphql`. It accepts two auth methods:

1. **CLI signed request (canonical)** — the same `x-tb-*` signed-request scheme used by the REST API (see above). This is how the `tokenbot` CLI authenticates and how new integrations should authenticate. No password, OAuth, passkey, or 2FA flow is involved.
2. **JWT bearer token (legacy)** — an `Authorization: Bearer <access_token>` token, retained only for back-compat.

Real-time subscriptions authenticate the graphql-ws handshake with the same signed-request scheme (method `CONNECT`, path `/graphql`) — see [Subscriptions](/home/api-docs/graphql-api/subscriptions.md).

> **Deprecated auth surface:** the password `login` / `register`, OAuth (`google_auth`, `x_auth`, `apple_auth`, `telegram_auth`), passkey / WebAuthn, and 2FA (`generate_2fa`, `enable_2fa`, `verify_2fa_code`, `disable_2fa`) mutations are dashboard-era and **`@deprecated`** — they still resolve but are slated for removal in v2.0, so they are intentionally **not documented as usable endpoints here**. Authenticate programmatic clients with the CLI signed-request scheme or a REST **API key** instead. The full deprecated list is in [Mutations](/home/api-docs/graphql-api/mutations.md).

> Heads-up: GraphQL previously ran on AWS AppSync with Cognito. That has been retired — there is no Cognito, AppSync API key, or `x-api-key` auth anymore.

***

## Security Best Practices

* Never commit API keys to version control.
* Rotate keys periodically via `POST /v1/api-keys/:id/rotate` (or `tokenbot apikey`).
* Use the minimum required permissions for each key.
* Protect your CLI identity — choose a strong `~/.tokenbot` passphrase; your secp256k1 private key never leaves your machine.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.tokenbot.com/home/api-docs/authentication.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
