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

# Authentication

> How to authenticate against the Totalis REST API and WebSocket — scoped API keys for programmatic clients and Privy JWTs for the web dashboard.

The Totalis API accepts two authentication schemes:

* **API key** — for programmatic clients (bots, scripts, server-side integrations). Sent as the `X-API-Key` header. Works on both REST and WebSocket.
* **Privy JWT** — used by the web dashboard. Sent as `Authorization: Bearer <jwt>`. The session signer underpinning the JWT also signs vault transactions in the browser.

Either scheme works on every authenticated endpoint, with one exception: `POST /v1/api-keys` (create a new API key) requires a Privy JWT, or an API key that holds the `keys:manage` scope.

## Getting your API key

Generate an API key from the [Totalis Dashboard](https://app.totalis.trade):

1. Log in to [app.totalis.trade](https://app.totalis.trade)
2. Navigate to your account settings
3. Create a new API key, name it, and **choose its scopes** (see below)
4. Copy the full key immediately

<Warning>
  The full API key is only displayed at creation time. Save it securely — you will not be able to retrieve it later.
</Warning>

## Using your API key

Send your API key in the `X-API-Key` header with every request:

```bash theme={null}
curl -X GET https://api.totalis.trade/v1/portfolio \
  -H "X-API-Key: <your-api-key>"
```

For WebSocket connections, authenticate after connecting:

```json theme={null}
{
  "type": "auth",
  "api_key": "<your-api-key>"
}
```

## Scopes

Every API key carries a set of **scopes** — the capabilities you select at creation. A request to an endpoint whose scope the key lacks is rejected with `403` (`insufficient_scope`). Grant only what a given integration needs.

| Scope            | Grants                                                                       | Risk   |
| ---------------- | ---------------------------------------------------------------------------- | ------ |
| `account:read`   | View account profile and username.                                           | low    |
| `markets:read`   | Browse markets and exclusion groups.                                         | low    |
| `positions:read` | View quote requests, portfolio, stats, and P\&L.                             | low    |
| `balances:read`  | View wallet and vault balances and delegation status.                        | low    |
| `trading:write`  | Create, modify, commit, and cancel quote requests (place parlays).           | medium |
| `funds:deposit`  | Move USDC into the vault.                                                    | low    |
| `funds:withdraw` | Move USDC out of the vault/wallet to any address. **Can drain the account.** | high   |
| `account:write`  | Change username and profile settings.                                        | medium |
| `tx:sign`        | Submit arbitrary signed Solana transactions.                                 | high   |
| `keys:manage`    | Create, list, and revoke API keys. Lets a key mint more keys.                | high   |
| `mm:quote`       | Read RFQs and submit/confirm quotes as a market maker.                       | medium |

<Note>
  A read-only integration (dashboards, reconciliation) needs only the `*:read` scopes. A trading bot
  adds `trading:write` (and `funds:deposit` if it tops up the vault). Reserve `funds:withdraw`,
  `tx:sign`, and `keys:manage` for keys that genuinely need them — each can move funds or escalate.
</Note>

## Managing API keys

You can list, create, and revoke API keys programmatically (or from the [Dashboard](https://app.totalis.trade)):

* **List keys** — `GET /v1/api-keys`
* **Create key** — `POST /v1/api-keys` (requires a Privy JWT, or a key with `keys:manage`)
* **Revoke key** — `DELETE /v1/api-keys/{prefix}`

A new key can never grant a scope the creating credential doesn't already hold.

## Key lifecycle

* **Active** — the key is valid and can be used for authentication.
* **Revoked** — the key has been manually revoked and will be rejected.
* **Expired** — the key has passed its expiration date.
