# Authentication

**Use the Deriv API documented here.** The auth model is OAuth2 for REST, plus an OTP-URL flow for WebSocket trading. There is no auth handshake on the WebSocket itself.

| Surface | Gateway | Auth |
|---------|---------|------|
| Public market data | `wss://api.derivws.com/trading/v1/options/ws/public` | None — connect directly |
| Authenticated trading | OTP-issued `wss://api.derivws.com/trading/v1/options/ws/real` or `/ws/demo` | OTP URL from `POST /trading/v1/options/accounts/{accountId}/otp` |

## OAuth 2.0 (Authorization Code + PKCE)

Obtain an OAuth2 access token via the Authorization Code flow with PKCE.

- Authorization endpoint: `https://auth.deriv.com/oauth2/auth`
- Token endpoint: `https://auth.deriv.com/oauth2/token`

The access token is sent as `Authorization: Bearer <token>` on REST calls.

Login, signup, and troubleshooting: [oauth](https://developers.deriv.com/llms/oauth.md).

## REST request headers (required on every authenticated REST call)

```
Deriv-App-ID: <your app id>
Authorization: Bearer <oauth access token>
Content-Type: application/json
```

## WebSocket authentication — the OTP-URL flow

Authentication happens before connect:

1. Call `POST /trading/v1/options/accounts/{accountId}/otp` with the OAuth Bearer token (and `Deriv-App-ID`).
2. The response returns a `data.url` — a WebSocket URL with an embedded one-time password.
3. Connect to that URL directly. Do not send any auth message after connect.

```
POST https://api.derivws.com/trading/v1/options/accounts/{accountId}/otp
Headers: Deriv-App-ID, Authorization: Bearer <token>
Response: { "data": { "url": "wss://api.derivws.com/trading/v1/options/ws/real?otp=..." } }
```

Then: `new WebSocket(otpUrl)` — no further auth step.

## Public market data (no authentication)

Connect directly to `wss://api.derivws.com/trading/v1/options/ws/public` — no OTP, no token, no request body. Use this for `ticks`, `active_symbols`, `proposal` (pricing), `time`, `trading_times`.

## Bulk-purchase authentication (different)

`POST /trading/v1/options/contracts/bulk-purchase/{real,demo}` uses the `Deriv-App-ID` header plus per-account Personal Access Tokens (PATs) in the request body. **Never** send an OAuth Bearer token to bulk-purchase.

_Source: [authentication](https://developers.deriv.com/llms/authentication.md)._
