NetworkRealtimeTicketResult network.realtime-ticket-result@1

Generated at from openvibe-contracts v0.76.0 and openvibe-sdk v0.20.1.

Version
1.0.0
Owner
network
Visibility
first-party
Status
active
Compatibility
backward
Decision
ADR-005
Schema
https://openvibe.network/contracts/network/realtime-ticket-result.v1.json

What POST /api/v1/realtime/ticket answers (OpenVibe.Network; ADR-005 amendment 2): a realtime ticket (identity.realtime-ticket-claims@1) for the signed-in person, and where to use it. The caller is the person's own session (Bearer Network JWT, or the ov_token cookie on openvibe.network); guests are refused (403 realtime.guest), and 503 realtime.disabled means the operator turned browser realtime off (REALTIME_TICKETS=off): the client stays on polling. The client opens `${stream_url}?topics=${topics}&ticket=${ticket}` (plus last_event_id when it resumes) at once, and asks for a fresh ticket for every reconnect: a ticket opens one stream.

Fields

FieldTypeRequiredDescriptionConstraints
ticketstringyesThe signed ticket (a compact JWS). Never logged, never stored.
  • pattern ^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$
  • maxLength 4096
expires_atstringyes
  • format date-time
expires_inintegeryesSeconds until the ticket expires (120).
  • minimum 1
  • maximum 300
stream_urlstringyesEvents' realtime stream (https://events.openvibe.network/realtime/stream).
  • pattern ^https?://[^?#]+/realtime/stream$
  • format uri
topicsarray of stringyesThe topic patterns the notification badge subscribes to: ["network.notification.*"].
  • minItems 1
  • maxItems 20
  • items: pattern ^(\*|[a-z0-9_]+)(\.(\*|[a-z0-9_]+))*$
subjectstringyesWhose ticket it is; a client ignores any event whose subject is someone else.
  • pattern ^usr_[0-9A-HJKMNP-TV-Z]{26}$

Examples

From the contract's own test fixtures: valid ones validate, rejected ones must fail.

Valid: badge
{
  "ticket": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXAiOiJyZWFsdGltZSJ9.c2lnbmF0dXJl",
  "expires_at": "2026-09-26T18:05:08.000Z",
  "expires_in": 120,
  "stream_url": "https://events.openvibe.network/realtime/stream",
  "topics": [
    "network.notification.*"
  ],
  "subject": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
}
Rejected: long-lived
{
  "ticket": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXAiOiJyZWFsdGltZSJ9.c2lnbmF0dXJl",
  "expires_at": "2026-09-27T18:03:08.000Z",
  "expires_in": 86400,
  "stream_url": "https://events.openvibe.network/realtime/stream",
  "topics": [
    "network.notification.*"
  ],
  "subject": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
}
Rejected: not-a-jws
{
  "ticket": "not a token",
  "expires_at": "2026-09-26T18:05:08.000Z",
  "expires_in": 120,
  "stream_url": "https://events.openvibe.network/realtime/stream",
  "topics": [
    "network.notification.*"
  ],
  "subject": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
}
Rejected: stream-url-with-query
{
  "ticket": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXAiOiJyZWFsdGltZSJ9.c2lnbmF0dXJl",
  "expires_at": "2026-09-26T18:05:08.000Z",
  "expires_in": 120,
  "stream_url": "https://events.openvibe.network/realtime/stream?ticket=x",
  "topics": [
    "network.notification.*"
  ],
  "subject": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
}
Rejected: user-colon-topic
{
  "ticket": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXAiOiJyZWFsdGltZSJ9.c2lnbmF0dXJl",
  "expires_at": "2026-09-26T18:05:08.000Z",
  "expires_in": 120,
  "stream_url": "https://events.openvibe.network/realtime/stream",
  "topics": [
    "user:usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  ],
  "subject": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
}

Validate

const contracts = require('openvibe-contracts');
contracts.validate('network.realtime-ticket-result@1', value);   // { valid, errors: [{ path, message }] }