Issue a one-time WebSocket handshake token
Owner-only: the caller must be the purchase's `purchaser_id` (anything else is 404 — no existence leak). Issues a fresh one-time token for the raw `WS /ws?token=...` socket: a 32-byte random value stored as its SHA-256 hash, valid 10 minutes, consumed by the first handshake. The token is a handshake-auth shim — it proves prior REST auth for this purchase and nothing more (no refresh dance, no scopes). Reconnect = fresh token: the front re-requests before the 10-minute expiry and re-opens the socket.
/ws/tokenOwner-only: the caller must be the purchase's purchaser_id
(anything else is 404 — no existence leak). Issues a fresh one-time
token for the raw WS /ws?token=... socket: a 32-byte random value
stored as its SHA-256 hash, valid 10 minutes, consumed by the first
handshake. The token is a handshake-auth shim — it proves prior REST
auth for this purchase and nothing more (no refresh dance, no
scopes). Reconnect = fresh token: the front re-requests before the
10-minute expiry and re-opens the socket.
Authorization
bearerAuth JWT issued by IdentityX, signed with Ed25519
In: header
Query Parameters
Purchase to bind the token to.
Response Body
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/ws/token?purchase_id=497f6eca-6276-4993-bfeb-53cbbbba6f08"{
"code": 0,
"message": "string",
"error": {
"code": "BAD_REQUEST",
"message": "string",
"fields": [
{
"field": "string",
"message": "string"
}
],
"meta": {},
"debug": {
"raw_error": "string",
"stack_trace": "string"
}
},
"pagination": {
"page": 1,
"limit": 1,
"total": 0,
"has_next": true,
"has_prev": true,
"next_page": 0,
"prev_page": 0
},
"timestamp": "2019-08-24T14:15:22Z",
"module": "string",
"data": {
"token": "string",
"expires_at": "2019-08-24T14:15:22Z"
}
}{
"code": 0,
"message": "string",
"error": {
"code": "BAD_REQUEST",
"message": "string",
"fields": [
{
"field": "string",
"message": "string"
}
],
"meta": {},
"debug": {
"raw_error": "string",
"stack_trace": "string"
}
},
"timestamp": "2019-08-24T14:15:22Z",
"module": "string"
}{
"code": 0,
"message": "string",
"error": {
"code": "BAD_REQUEST",
"message": "string",
"fields": [
{
"field": "string",
"message": "string"
}
],
"meta": {},
"debug": {
"raw_error": "string",
"stack_trace": "string"
}
},
"timestamp": "2019-08-24T14:15:22Z",
"module": "string"
}{
"code": 0,
"message": "string",
"error": {
"code": "BAD_REQUEST",
"message": "string",
"fields": [
{
"field": "string",
"message": "string"
}
],
"meta": {},
"debug": {
"raw_error": "string",
"stack_trace": "string"
}
},
"timestamp": "2019-08-24T14:15:22Z",
"module": "string"
}List my purchases GET
Lists the authenticated user's purchases with their items, newest first. The purchases table is the record of truth (issue #61); items come from `purchase_items` — the availability ledger (D4). Read-only; no state transitions.
Backend
The Univents Go service — events, ticketing, the store. Where it lives, structure, run it.