Skip to content
UDX
On this page

Authentication

Create API credentials, sign REST requests, authenticate WebSocket connections, and see which credential each operation accepts.

The exchange 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 lists the credentials accepted by each operation. WebSocket connections require an API key.

Create an API Key

Create your first key in the UDX UAT app. 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. The exchange stores the PEM-encoded public key. Keep the private key in your environment; the exchange does not receive, store, or return it.

Scopes

Every user holds a set of scopes, and every API key holds a set of scopes. The two use the same vocabulary. A user’s scopes are what that user may do when signed in to the UDX app, and the ceiling for any API key the user owns: a key never holds a scope its user lacks. When a user loses a scope, every API key the user owns loses it at the same moment, and a key left with no scope is revoked.

Scopes are never granted by default. The exchange assigns the first user’s scopes during onboarding; a user holding users:manage assigns everyone else’s. See Participants and Access for the rules.

Scope Allows
read Read markets, portfolio data, and the member’s users.
trade Place and manage orders, quotes, and RFQs.
funds:transfer Transfer funds between eligible accounts. This scope must be selected explicitly.
accounts:manage Create accounts. This scope must be selected explicitly.
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.
users:manage Set the scopes of the member’s other users, within your own. This scope must be selected explicitly.

GET /users/me returns the scopes the calling credential holds. It is the one read that needs no scope.

Limit Key Access

Scopes are selected when the key is created and can be any subset of the scopes the key’s user holds. Requesting a scope the user lacks returns 403 and creates no key. A user holding users:manage can create, list, and revoke keys for the member’s other users; those keys are capped by their owner’s scopes in the same way. 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 widened. Revoke the key and create another one to change its access. A key’s scopes shrink only when its user loses a scope.

A key can revoke itself without keys:manage. For your own keys, listing or creating keys, or revoking another key, requires keys:manage. A users:manage holder manages another user’s keys through the /users/{user_id}/api_keys operations instead; targeting your own user through those paths still requires keys:manage for listing, creation, or revoking another key.

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 for how grants work.

Sign with an API Key

Every signed request or connection sends the same three headers and the same signature algorithm. What differs is the message you sign.

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.

Sign the message with RSA-PSS over SHA-256, using a 32-byte salt, and encode the signature with standard base64. UDX-Access-Timestamp is Unix time in milliseconds and must be within 30 seconds of UDX’s clock, so sign immediately before sending. An invalid signature or stale timestamp returns 401.

Compute a new signature for each authenticated REST request. Build the message with no separators, using the uppercase HTTP method and the path without its query string. The same formula applies to every method:

timestamp + METHOD + path + bodyHash + idempotencyKey
  • bodyHash is the lowercase hexadecimal SHA-256 digest of the exact request body bytes when the body is nonempty. If no body bytes are sent, use an empty string: do not append the SHA-256 digest of an empty body. This includes bodyless POST and DELETE requests.
  • idempotencyKey is the exact value of UDX-Idempotency-Key when supplied, or an empty string when absent. Append a supplied key even when the request has no body.

An empty body and the JSON body {} produce different signing messages: {} contains two bytes and must be hashed. Hash the bytes you actually send, including any whitespace.

For example:

# Bodyless GET without an idempotency key
1752566400000GET/api_keys

# Bodyless DELETE with an idempotency key (replace <order_id> with the actual ID)
1752566400000DELETE/orders/<order_id>6f1c2a40-2b7e-4c1a-9c2e-2d1f8a3e4b5c

# POST with a nonempty body: timestamp + method + path + body hash + idempotency key
1752566400000POST/orders38208c3a7f77df88f932b843cf5be29291ab1e1284f82eef3b6e830e2d24282fb6f1c2a40-2b7e-4c1a-9c2e-2d1f8a3e4b5c

The Quick Start shows the complete signing flow in JavaScript. See Idempotency for retry rules.

Send the three UDX-Access-* headers on the HTTP upgrade request. The upgrade has no body and no idempotency key, so the message is fixed:

timestamp + GET + /ws

The key must have the read scope. A key without it receives 403 and no connection is opened.

The signature authenticates the connection once; individual WebSocket commands are not signed. The upgrade must also select a supported WebSocket version. See Versioning and the 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 on REST requests:

Authorization: Bearer <access-token>

The token must identify an active user with access to UDX. A missing or invalid token returns 401; a user without direct access receives 403. The session holds exactly the user’s scopes, so an operation the user lacks the scope for returns 403 just as it would for an API key.

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 for its accepted credentials.