---
title: Authentication
description: Create API credentials, sign REST requests, authenticate WebSocket connections, and see which credential each operation accepts.
sidebar:
  order: 3
---

UDX accepts two credentials, both acting for one active user:

- an **API key signature** for programmatic REST and WebSocket access; and
- an **interactive access token** for a signed-in UDX session.

Most REST operations accept either credential. The [REST API](/api-reference) lists the credentials accepted by each operation.

## Create an API Key

Create your first key in the [UDX UAT app](https://app.uat.udx.underdogsports.com/). A user can have multiple keys, so give each integration its own key and access boundary.

An API key uses an RSA keypair with a modulus from 2048 to 4096 bits. UDX stores the PEM-encoded public key. Keep the private key in your environment; UDX does not receive, store, or return it.

## Limit Key Access

Scopes are selected when the key is created:

| Scope | Allows |
| --- | --- |
| `read` | Read markets, portfolio data, and the member's users. |
| `trade` | Place and manage orders. |
| `transfer` | Transfer funds between eligible accounts. |
| `keys:manage` | List, create, and revoke API keys. This scope must be selected explicitly. |
| `grants:manage` | View and change which of the member's users can reach each account. This scope must be selected explicitly. |

A key can also be restricted to one account. An unrestricted key can access only accounts available to its user.

A key's name, scopes, and account restriction cannot be changed. Revoke the key and create another one to change its access.

A key can revoke itself without `keys:manage`. Listing keys, creating a key, or revoking another key requires `keys:manage`.

Using `grants:manage` on an account also requires that the key's own user holds a grant on that account, and an account-restricted key cannot manage grants. See [Participants and Access](/concepts/participants-and-access) for how grants work.

## Sign REST Requests

Compute a new signature for each authenticated REST request and send these headers:

| Header | Value |
| --- | --- |
| `UDX-Access-Key` | Your API key ID. |
| `UDX-Access-Timestamp` | The current Unix time in milliseconds, as a string. |
| `UDX-Access-Signature` | The base64-encoded request signature. |

Build the message with no separators. Use the uppercase HTTP method and exclude the query string from the path.

For `GET` and `HEAD` requests:

```text
timestamp + METHOD + path
```

For `POST`, `PUT`, `PATCH`, and `DELETE` requests:

```text
timestamp + METHOD + path + hex(SHA256(body)) [+ idempotencyKey when supplied]
```

Use the lowercase hexadecimal SHA-256 digest of the exact request body bytes. If the request includes `UDX-Idempotency-Key`, append its exact value too. Then sign the message with RSA-PSS over SHA-256, using a 32-byte salt, and encode the signature with standard base64.

For example:

```text
# GET request
1752566400000GET/api_keys

# POST request: timestamp + method + path + body hash + idempotency key
1752566400000POST/orders38208c3a7f77df88f932b843cf5be29291ab1e1284f82eef3b6e830e2d24282fb6f1c2a4-2b7e-4c1a-9c2e-2d1f8a3e4b5c
```

The timestamp must be within 30 seconds of UDX's clock. Sign immediately before sending the request. An invalid signature or stale timestamp returns `401`.

The [Quick Start](/quick-start#place-an-order) shows the complete signing flow in JavaScript. See [Idempotency](/idempotency) for retry rules.

## Authenticate a WebSocket Connection

Authenticate the WebSocket upgrade with the three `UDX-Access-*` headers. Sign this message:

```text
timestamp + GET + /ws
```

The upgrade must also select a supported WebSocket version. See [Versioning](/versioning#websocket-versioning) and the [WebSocket API](/websocket-api) for the complete connection contract.

## Use an Interactive Access Token

A signed-in UDX session sends its access token as a bearer token:

```http
Authorization: Bearer <access-token>
```

The token must identify an active user with direct UDX access. A missing or invalid token returns `401`; a user without direct access receives `403`.

Use the UDX app to create your first API key. If you are building an interactive UDX integration, check each operation in the [REST API](/api-reference) for its accepted credentials. WebSocket connections require an API key.
