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

# Authentication

> How to send your API key, what a key looks like, which environment it works in, and why a call is refused with 401.

Every call authenticates with one API key, sent in the `X-API-Key` header. There is no login, token exchange or session: the key is checked on every request.

```bash curl theme={null}
curl -s https://api.bullionwale.com/api/trading/test/v1/me \
  -H "X-API-Key: $BULLIONWALE_API_KEY"
```

```python Python theme={null}
import os
import requests

BASE = "https://api.bullionwale.com/api/trading/test/v1"
HEADERS = {"X-API-Key": os.environ["BULLIONWALE_API_KEY"]}

r = requests.get(f"{BASE}/me", headers=HEADERS, timeout=10)
print(r.status_code, r.json()["key_id"])
```

Your web or mobile login is never accepted by this API, and an API key is never accepted by the web or mobile app. A key sent as `Authorization: Bearer …` is not read; send it in `X-API-Key`.

## Key format

A key is one string with four parts separated by dots:

```text theme={null}
bwk_test.<broker>.<key id>.<secret>
bwk_live.<broker>.<key id>.<secret>
```

| Part | What it is |
| - | - |
| `bwk_test` or `bwk_live` | The environment the key works in: test or production. |
| `<broker>` | The Bullionwale platform that issued the key. |
| `<key id>` | The key's public id: 20 hexadecimal characters. `GET /me` returns it as `key_id`. It is safe to log and to quote to Bullionwale. |
| `<secret>` | 43 URL-safe characters (letters, digits, `-` and `_`). Never share it, including with Bullionwale staff. |

Treat the whole string as opaque: store it and send it exactly as you received it. Bullionwale stores only a hash of the secret, so it cannot show you a key again, only replace it (see [Credentials](/credentials)).

## Environments

A key works in one environment only:

| Key | Works on | Elsewhere |
| - | - | - |
| `bwk_test.…` | `/api/trading/test/v1` | `401 wrong_environment` |
| `bwk_live.…` | `/api/trading/v1` | `401 wrong_environment` |

So a test key can never place a real order, and pointing a program at the wrong base path fails at once instead of half-working. See [Test and production](/environments).

## How many keys

Each account can hold up to 5 active keys per environment by default (Bullionwale's limit may differ). Use a separate key for each system that calls the API, so that one can be rotated or revoked without touching the others. A read-only key (without `orders:write`) is a good choice for dashboards and reconciliation jobs.

## When authentication fails

A refused key answers `401` with a code that says why:

| Code | Status | Meaning |
| - | - | - |
| `missing_credential` | 401 | No `X-API-Key` header. |
| `malformed_credential` | 401 | The value is not shaped like a key: check that the whole key was copied, with no spaces or quotes. |
| `wrong_tenant` | 401 | The key was issued by a different Bullionwale platform. |
| `wrong_environment` | 401 | A test key on a production path, or a live key on a test path. |
| `invalid_credential` | 401 | Unknown key id or wrong secret. |
| `credential_revoked` | 401 | The key was revoked. |
| `credential_rotated` | 401 | The key was replaced and its overlap has ended. |
| `credential_expired` | 401 | The key reached its expiry date. |

```json 401 Unauthorized theme={null}
{
  "detail": {
    "code": "missing_credential",
    "message": "Send your API key in the X-API-Key header."
  }
}
```

A key that authenticates can still be refused with `403`: `api_access_disabled` (API access is off for the account), `account_inactive`, or `insufficient_scope` (see the [Scope reference](/scopes)).

> [!WARNING]
>
> **Repeated failures lock out your address.** Too many `401` answers from one source address in a minute and every call from that address is refused with `429 auth_throttled`, **even with a good key**, until it cools down. Fix a misconfigured key before it blocks your other systems. See [Rate limits](/rate-limits).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.