Connect with a short-lived capability
Provision from a trusted Node 22 backend, mint one subject-bound capability in your BFF, then connect the browser directly to the Lot session.
Sandbox endpoints
- Control Plane:
https://control.sandbox.headless.bid - Data Plane:
wss://data.sandbox.headless.bid - Session path:
/v1/lots/{lotId}/session. The opaquelotIdreturned by provisioning is also the route name.
Minimal WebSocket transport
Install the exact private release-candidate version authorized for your pilot. Pass both values returned by sessionSubprotocols unchanged; the server negotiates only ledgero.v2 and never reflects the proof-bearing capability protocol.
import {
SessionClient,
sessionSubprotocols,
type ClientFrame,
type ServerFrame,
type SessionTransport,
} from '@headless-bid/client'
const lotId = provisioned.lotId
const sessionUrl =
`wss://data.sandbox.headless.bid/v1/lots/${encodeURIComponent(lotId)}/session`
class BrowserWebSocketTransport implements SessionTransport {
#socket: WebSocket | null = null
open({ capability, onFrame, onClose }: Parameters<SessionTransport['open']>[0]) {
const socket = new WebSocket(sessionUrl, [...sessionSubprotocols(capability)])
this.#socket = socket
socket.addEventListener('message', (event) => {
onFrame(JSON.parse(String(event.data)) as ServerFrame)
})
socket.addEventListener('close', (event) => {
onClose(event.wasClean ? 'normal' : 'abnormal')
})
return new Promise<void>((resolve, reject) => {
socket.addEventListener('open', () => resolve(), { once: true })
socket.addEventListener('error', () => reject(new Error('session upgrade failed')), { once: true })
})
}
send(frame: ClientFrame) {
if (this.#socket?.readyState !== WebSocket.OPEN) throw new Error('session is not open')
this.#socket.send(JSON.stringify(frame))
}
close() {
this.#socket?.close(1000, 'client disconnect')
this.#socket = null
}
}
const client = new SessionClient({
transport: new BrowserWebSocketTransport(),
capability: async () => {
const response = await fetch('/api/lots/SKU-4471/capability', {
method: 'POST',
headers: { 'content-type': 'application/json' },
})
if (!response.ok) throw new Error('capability unavailable')
return (await response.json()).capability as string
},
})
await client.connect()Recovery discipline
- 1
Let the SDK acknowledge heartbeats
SessionClientanswerssession.heartbeatframes. A missed deadline closes the connection; application activity is not a heartbeat substitute. - 2
Reconnect with fresh authority
After an abnormal close, obtain a new capability, reconnect, and issue one explicit
session.resync. - 3
Reconcile before deciding
Read
yourParticipation.commandOutcomesfrom the snapshot. Never automatically replay a bid or proxy command whose outcome is unknown. - 4
Respect congestion
Surface
overloadedandrate_limitedwith their optionalretryAfterMs. Retrying an economic command remains an explicit user decision with a new request identifier.
Service credential delivery
During the private Sandbox pilot, headless.bid installs the credential directly into the tenant's approved deployment secret store. It is not emailed, returned to browser JavaScript, committed to a repository, printed in CI, or exposed by Platform OAuth. Rotate immediately after suspected disclosure.