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

# Authentication

> Credentials for the trading and data surface - what to get, where to send it.

Every production call carries a credential. Miss it and the trading endpoints answer `401 AUTH_REQUIRED` while the streaming endpoint declines the handshake outright.

TetraFi uses three credential types, each with a distinct job:

| Credential                                    | Header / transport                        | Used for                                                                               |
| --------------------------------------------- | ----------------------------------------- | -------------------------------------------------------------------------------------- |
| **API key** (`tfk_test_...` / `tfk_live_...`) | `X-API-Key` header                        | The programmatic trading path: quotes, order preflight, order submission, order status |
| **JWT Bearer**                                | `Authorization: Bearer <jwt>`             | Workspace administration: service accounts, key management, dashboards                 |
| **SIWE signature**                            | `POST /api/v1/auth/challenge` → `/verify` | Linking and authenticating wallets                                                     |

Compliance-sensitive operations (such as order submission) may additionally require the `X-TetraFi-Attestation` header.

## Getting a Key

Create a service account in your workspace and issue a key for it from the dashboard (**Workspace → Service Accounts → API Keys**). Keys are scoped — **Read**, **Trade**, or **Admin** — so a quoting integration only needs `Trade`. Use `tfk_test_` keys against the sandbox and `tfk_live_` keys in production.

Not on a workspace yet? Reach the team [via support](/support) and they'll get one set up.

## Sending Credentials

<Tabs>
  <Tab title="REST APIs">
    For HTTP requests (RFQ, Router, Trade History), authenticate with the `X-API-Key` header:

    ```python theme={null} theme={null}
    YOUR_API_KEY = "tfk_live_..."

    headers = {"X-API-Key": YOUR_API_KEY}
    ```

    With curl:

    ```bash theme={null} theme={null}
    curl -H "X-API-Key: tfk_live_..." ...
    ```
  </Tab>

  <Tab title="WebSocket">
    For WebSocket connections (price feed and order events), pass your credential as a `token` query parameter on the connection URL — browsers cannot set custom headers on a WebSocket handshake:

    ```python theme={null} theme={null}
    import websockets

    ws_url = "wss://api.tetrafi.io/api/v1/ws?token=tfk_live_..."

    async with websockets.connect(ws_url) as ws:
        ...
    ```
  </Tab>
</Tabs>

## Access With and Without a Key

| API                 | Without key                                  | With key                                                 |
| ------------------- | -------------------------------------------- | -------------------------------------------------------- |
| **Price feed (WS)** | Handshake refused                            | Every subscribed corridor streams live                   |
| **RFQ API**         | `401 AUTH_REQUIRED` - nothing quoted         | Signed-and-executable firm quotes                        |
| **Router API**      | `401 AUTH_REQUIRED` - no quotes are returned | Ranked executable candidates across all eligible sources |
| **Trade History**   | Not accessible                               | Your workspace's complete trade record                   |

Wire the whole flow against the sandbox on a `tfk_test_` key first; flip to `tfk_live_` only when the loop is proven.

## Rate Limits

Throughput is metered at two levels - the individual key and the workspace it belongs to. If your use case needs more headroom, [talk to the team](/support).

## Handling Keys Safely

A key is a secret: it belongs on your backend, never in client bundles, public repos, or anything a browser's network tab can see.

Think a key leaked? Kill it in the dashboard and mint a fresh one - or [loop in the team](/support) if you need a hand.
