Interactions & Status
read-card and charge-card are queue-based: they return 202 Accepted immediately with an interaction_id, and the outcome is retrieved later.
Retrieving the result
- Polling:
GET /api/terminal/{device_id}/read-card/{interaction_id}orGET /api/terminal/{device_id}/charge-card/{interaction_id} - WebSocket: subscribe to
terminal_job:{interaction_id}for push updates (see Real-time updates).
Interaction status values
After the TTL, the status endpoint returns 404 — the same response as an interaction that never existed or a wrong device_id. Retrieve results promptly and persist anything you need.
Cancelling
DELETE /api/terminal/{device_id}/cancel/{interaction_id} cancels a pending read-card interaction on the terminal. It returns 200 with no body on success, or 422 if the interaction is no longer pending.
Charging is a processing flow whose outcome depends on timing at the terminal and processor. Once a charge-card interaction starts, wait for its final status and check result.
Sessions
ping, read-card, charge-card, and print-receipt auto-connect a terminal session if none is active, so calling connect first is optional. Use connect to pre-warm a terminal or force a reconnect (force: true); use disconnect to release the device.
Real-time updates (WebSocket)
By default, interaction status is retrieved by polling the status endpoint. For applications that want instant updates without polling, the Terminal API also supports an optional WebSocket connection that pushes status changes as they happen. This works for both read-card and charge-card interactions.
Why a separate token?
This flow uses its own token rather than your access token. Browser and native WebSocket clients can only pass credentials via the connection URL (query string), not request headers, and putting a long-lived access token into a URL risks it being captured in server logs, proxy logs, or browser history.
To avoid that risk, the WebSocket flow uses a short-lived, single-use token that is only valid for establishing one socket connection. It expires after 60 seconds or on first use, whichever comes first, and cannot be reused for a second connection or for REST calls.
How it works
Open the WebSocket connection
Connect to wss://javelin.runpayments.io/cable?token={token}. Once used, the token is invalidated; if the connection drops, request a new token before reconnecting.
Start the interaction
POST /api/terminal/{device_id}/read-card or /charge-card. Returns an interaction_id.
Example
Other things to keep in mind
- Tokens are single-use. Request a new token for every new WebSocket connection, including reconnects.
- Tokens expire in 60 seconds. Request the token immediately before connecting, not in advance.
- Channels are per-interaction. You need the
interaction_idbefore subscribing, so queue the interaction first. - WebSocket connections are multi-interaction. Once open, a connection isn’t single-use — you don’t need a new connection or a new token to handle another interaction.
- This does not start an interaction. The WebSocket only delivers updates for an interaction already in progress.
- Status alone doesn’t mean approved. A declined
charge-cardstill arrives assucceeded— see Handling declines.