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

# Authentication

> API keys, scopes, status, rotation, revocation and key security.

Every `/mm/v1` request is authenticated with an API key sent as a Bearer token.

```bash theme={null}
curl "$D1_API_URL/mm/v1/status" \
  -H "Authorization: Bearer $D1_MM_API_KEY"
```

The header must be exactly `Bearer <key>`: one scheme, one space, one key. Send the key only in the `Authorization` header, never in a query string or request body.

> [!NOTE]
>
> **Need a key?** Market Maker API access is permissioned. See [Getting API access](https://docs.d1.exchange/market-makers/introduction.md#getting-api-access) for how to request one.

## API keys

* Access uses Market Maker API keys issued by D1 during onboarding. There is no self-service key creation. See [Getting API access](https://docs.d1.exchange/market-makers/introduction.md#getting-api-access).
* A key is valid only for the documented `/mm/v1` endpoints. It does not give access to any other D1 interface.
* **The key identifies your account.** Every request acts on the market maker account the key belongs to. Do not send an account ID: no endpoint takes one, and a request body that contains one is refused with `400 MALFORMED_REQUEST`.
* **The full key is shown once.** D1 cannot show it again or recover it. If you lose it, ask D1 to revoke it and issue a new one.
* Your account can have **up to two active keys** at a time, so you can rotate without downtime. Both keys act on the same account and see the same orders, fills and execution stream.

## Scopes

| Scope | Grants |
| - | - |
| `mm:read` | Every `GET` endpoint: status, markets, order books, balances, positions, orders, fills and executions. |
| `mm:trade` | `POST /mm/v1/orders`, `POST /mm/v1/orders/{orderId}/cancel` and `POST /mm/v1/orders/cancel-all`. |

D1 issues read keys with `mm:read` only, and trading keys with both `mm:read` and `mm:trade`, so a trading key can also read its own orders and executions. A read key never gains `mm:trade`: trading access comes with a new key, issued after D1 enables trading for your account. A key without the scope a route needs gets `403 INSUFFICIENT_SCOPE`.

> [!NOTE]
>
> **`mm:trade` alone does not mean you can place orders right now.** New orders also need your account to be enabled for trading by D1. Check `trading.available` in `GET /mm/v1/status`. See [Trading availability](https://docs.d1.exchange/market-makers/trading-rules.md#trading-availability).

## `GET /mm/v1/status`

Shows the identity and permissions of the key you sent, and whether you can place new orders right now. It takes no query parameters and needs `mm:read`.

```json theme={null}
{
  "apiVersion": "mm/v1",
  "dealer": { "id": "…", "status": "ACTIVE", "displayName": "Alpha Markets" },
  "credential": { "keyId": "…", "scopes": ["mm:read", "mm:trade"] },
  "capabilities": { "read": true, "trade": true, "writeOptions": false },
  "trading": { "available": true, "reason": null, "sellPolicy": "CLOSE_ONLY" },
  "limits": {
    "maxOpenExposure": { "units": "…", "decimals": 6 },
    "maxRestingOrders": 128,
    "maxRestingOrdersPerInstrument": 8
  }
}
```

**apiVersion** `string`

Always `mm/v1`.

**dealer** `object`

Your market maker account.

**fields**

**id** `string`

Your account's stable identifier.

**status** `string`

Always `ACTIVE` in a `200`. A suspended account cannot read, so it gets `403 DEALER_SUSPENDED` instead.

**displayName** `string`

Your account's display name.

**credential** `object`

The key you sent: `keyId` (its public identifier, safe to log) and `scopes`.

**capabilities** `object`

`read` is `true` when the key has `mm:read`. `trade` is `true` exactly when a new order from this key would pass D1's trading checks now. `writeOptions` is always `false`: V1 does not support option writing.

**trading** `object`

`available` has the same value as `capabilities.trade`. `reason` is `null` when trading is available and `TRADING_DISABLED` when it is not. `sellPolicy` is always `CLOSE_ONLY`; see [Sell-to-close](https://docs.d1.exchange/market-makers/trading-rules.md#sell-to-close).

**limits** `object`

The order limits that apply to your account. These are configuration, not your current usage. See [Order limits](https://docs.d1.exchange/market-makers/trading-rules.md#order-limits).

`trading.available` reflects the moment of the request. It can change at any time, so a placement can still be refused with `403 TRADING_DISABLED` even after a status that said `true`.

## Rotation

**1. Request a new key**

Ask D1 through your [onboarding contact](https://docs.d1.exchange/market-makers/introduction.md#getting-api-access). D1 issues a second key. Your old key keeps working.

**2. Switch over**

Deploy the new key and check it with `GET /mm/v1/status`.

**3. Revoke the old key**

Ask D1 to revoke the old key by its `keyId`.

Both keys share your account's [rate limits](https://docs.d1.exchange/market-makers/rate-limits.md), orders, `clientOrderId` values and execution stream. A new key does not reset any budget.

## Revocation and suspension

| Event | Reads | New orders | Cancel and cancel-all |
| - | - | - | - |
| Key revoked | `401 API_KEY_REVOKED` | `401 API_KEY_REVOKED` | `401 API_KEY_REVOKED` |
| Account suspended | `403 DEALER_SUSPENDED` | `403 DEALER_SUSPENDED` | **Still allowed** with an active `mm:trade` key |
| Trading not enabled for the account | Allowed | `403 TRADING_DISABLED` | Allowed |
| Account reactivated | Allowed again for keys that were not revoked | `403 TRADING_DISABLED` until D1 enables trading again | Allowed |

When D1 suspends an account, it also turns trading off for it and cancels its resting orders, with `cancelReason: ADMIN_PULL`. Reactivating the account does not turn trading back on: D1 has to enable trading again after the trading checks pass.

Revocation is permanent. You only see `API_KEY_REVOKED` or `DEALER_SUSPENDED` if your request included the correct secret. Any other bad credential returns `401 INVALID_API_KEY`.

## Keeping your key safe

Treat a key with `mm:trade` like access to a trading account: anyone who holds it can place and cancel orders on your account.

* **Keep keys server-side.** Run your bot on infrastructure you control. Never ship a key in a browser app, a mobile app or any software installed on end-user devices.
* **Never commit keys.** Load them from a secrets manager or a secret environment variable, not from source control or a config file in your repository.
* **Never log keys.** Keep them out of logs, URLs, tickets, chat messages and error reports. To refer to a key, use its `keyId`.
* **Separate integrations.** Give each production system its own key, so you can revoke one without stopping the other.
* **Rotate and revoke.** Rotate keys periodically. If you think a key has leaked, ask D1 to revoke it right away, then switch to your other key.
* **Contain damage.** Keep a tested path to `POST /mm/v1/orders/cancel-all` so you can pull your quotes quickly in an incident.


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