The WebSocket API gives your app a live channel from Orenda. Instead of polling REST endpoints, you hold one connection open and events arrive as they happen. Today it carries 3DS challenges, so a card payment that needs approval reaches the customer’s device instantly (see 3DS events), and BATCH_PAYMENT_VERIFICATION_COMPLETED, which says a batch verification has finished.

Connecting

Pass the user’s access_token (the same token you send as the bearer on REST calls) as the token query parameter. It’s checked once, during the handshake. A valid token opens the connection; an invalid or expired one rejects the handshake. The connection is scoped to the authenticated user, so you only receive their events.
The access token lasts about 5 minutes, so by the time you reconnect it has almost certainly expired. The open connection isn’t affected (auth happens only at the handshake), but refresh before every reconnect and use the fresh token. Once the refresh token itself expires (about an hour), the user signs in again before the WebSocket can reconnect.

Keeping the connection alive

Two server-side limits shape your client:
A client that never pings will be disconnected after 10 idle minutes and silently miss events until it reconnects. Build the ping loop and the reconnect handler first. They aren’t optional hardening.

Missed events

A 3DS challenge pushed while the customer is offline is re-delivered on reconnect: any still-pending challenge from the last 10 minutes that wasn’t delivered is pushed again as soon as the connection opens. Anything older has expired anyway. Other event types aren’t replayed. Treat the connection as a live feed, with REST as the source of truth.

Receiving events

Every message is JSON with a code that says what it is:
Route on code and ignore codes you don’t recognise. New event types get added without notice.