Skip to content

Live Events API ​

Managed live streaming and event broadcasting.

Events are created and run from the dashboard: stream keys, access tokens, the rehearsal → live → stop lifecycle, recordings, stats and health. The API below is the public viewer side, which resolves watch state for watch pages and embeds.

RTMP ingest: rtmp://ingest.wayscloud.services/live with the stream key from the dashboard.


Viewer endpoints (public, no authentication) ​

Resolve event watch state for watch pages, embeds, and custom players. Verify viewer access for password- or token-protected events.

The resolve endpoint returns two state fields:

  • watch_state — canonical viewer-facing UI state (not_started, access_required, live, replay_available, etc.)
  • status — internal lifecycle state for diagnostics

Access control modes:

ModeBehavior
publicAnyone with the URL can watch. Playback URLs returned directly.
passwordViewer submits password → receives access grant + playback.
tokenViewer submits pre-shared token → receives access grant. Token consumed on playback start, not on verify.
tenant_onlyViewer must be authenticated as a member of the same customer account.

Watch pages: https://live.wayscloud.services/watch/{slug}Embed: https://live.wayscloud.services/embed/{slug}


Manage events in dashboard: my.wayscloud.services/live-events

Endpoints ​

MethodPathDescription
GET/v1/live-events/watch/{slug}Resolve watch state
POST/v1/live-events/watch/{slug}/verify-passwordVerify event password
POST/v1/live-events/watch/{slug}/verify-tokenVerify watch token
POST/v1/live-events/watch/{slug}/consume-grantConsume access grant on playback start
GET/v1/live-events/watch/by-id/{public_id}Resolve watch state
POST/v1/live-events/watch/by-id/{public_id}/verify-passwordVerify event password
POST/v1/live-events/watch/by-id/{public_id}/verify-tokenVerify watch token
POST/v1/live-events/watch/by-id/{public_id}/consume-grantConsume access grant on playback start

GET /v1/live-events/watch/ ​

Resolve watch state

Returns the current watch state for an event. The watch page polls this every 10 seconds to detect state changes (e.g. event goes live, replay becomes available).

Returns watch_state (viewer-facing UI state) and status (internal lifecycle). Playback objects are only included for public events — auth-required events must call verify-password or verify-token first.

Draft events are not publicly resolvable and return 404.

Response:

FieldTypeDescription
event_idstringUnique event identifier
public_idstringGlobal event identity used by Meil Live and branded audience URLs
slugstringURL-safe event identifier used in watch and embed URLs
namestringEvent display name
descriptionstringOptional event description
statusstringInternal lifecycle state. For UI logic, use watch_state instead. Values: scheduled, ready, rehearsal, live, ending, ended, processing, failed, cancelled
watch_statestringCanonical viewer-facing UI state. The watch page should render based on this field. Values: not_started, access_required, live, rehearsal_hidden, processing_replay, replay_available, ended_no_replay, cancelled
visibility_modestringAccess control model for this event Values: public, token, password, tenant_only
requires_authbooleanWhether the viewer must verify access (password, token, or login) before playback URLs are returned
auth_typestringWhich auth method is required, if any. Null for public events. Values: password, token, tenant_only
scheduled_start_atstringPlanned start time (ISO 8601)
scheduled_end_atstringPlanned end time (ISO 8601)
timezonestringIANA timezone for display purposes
countdown_enabledbooleanWhether to show a countdown timer before the event starts
playback_modestringWhich playback path is currently active Values: live, replay, none
live_playbackobjectLive stream playback info. Present only when the event is live and the viewer has access.
replay_playbackobjectReplay playback info. Present only when the event has ended with a published replay and the viewer has access.
embed_enabledbooleanWhether iframe embedding is permitted for this event
banner_urlstringOptional banner image URL for the watch page
logo_urlstringOptional logo image URL for the watch page

Example:

bash
curl https://api.wayscloud.services/v1/live-events/watch/{slug} \
  -H "X-API-Key: wayscloud_live_abc12_YOUR_SECRET"

Response:

json
{
  "event_id": "9a72d400-36a0-4fa5-bf7e-6883f262850a",
  "public_id": "4ee07f75-9be5-4ed6-a43f-4ad9319c6436",
  "slug": "product-demo",
  "name": "Product Demo",
  "description": "Live demo of new release features",
  "status": "live",
  "watch_state": "live",
  "visibility_mode": "public",
  "requires_auth": false,
  "auth_type": null,
  "scheduled_start_at": "2026-04-10T12:00:00+00:00",
  "scheduled_end_at": "2026-04-10T13:30:00+00:00",
  "actual_start_at": "2026-04-10T12:01:10+00:00",
  "actual_end_at": null,
  "timezone": "Europe/Oslo",
  "countdown_enabled": false,
  "playback_mode": "live",
  "live_playback": {
    "hls_url": "https://live.wayscloud.services/hls/live/qz0bKkTt6Vjvpb7/index.m3u8",
    "protocol": "hls"
  },
  "replay_playback": null,
  "embed_enabled": true,
  "banner_url": null,
  "logo_url": null,
  "replay_published_at": null
}

POST /v1/live-events/watch/{slug}/verify-password ​

Verify event password

Verifies the password for a password-protected event. On success, issues a short-lived access grant and returns the current playback information.

Failed attempts are logged for abuse detection.

Request Body:

FieldTypeDescription
passwordstringRequired. Event password set by the event organizer

Response:

FieldTypeDescription
verifiedbooleanWhether verification succeeded
event_idstringInternal event identifier
public_idstringGlobal event identity used by Meil Live and branded audience URLs
access_grantstringShort-lived access grant. Pass this to consume-grant when playback starts.
access_grant_expires_atstringWhen the access grant expires. Viewer must re-verify after expiry.
watch_statestringCurrent watch state at time of verification Values: not_started, access_required, live, rehearsal_hidden, processing_replay, replay_available, ended_no_replay, cancelled
playback_modestringWhich playback path is active Values: live, replay, none
live_playbackobjectLive stream info, if event is live
replay_playbackobjectReplay info, if replay is available

Example:

bash
curl -X POST https://api.wayscloud.services/v1/live-events/watch/{slug}/verify-password \
  -H "X-API-Key: wayscloud_live_abc12_YOUR_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
  "password": "MyEventPass2026"
}'

Response:

json
{
  "verified": true,
  "event_id": "9a72d400-36a0-4fa5-bf7e-6883f262850a",
  "public_id": "4ee07f75-9be5-4ed6-a43f-4ad9319c6436",
  "access_grant": "ag_SqW1a2RzM1PB-bNUcXyZk0pQ7wE9vF3hJ6mT8nL",
  "access_grant_expires_at": "2026-04-10T15:00:00+00:00",
  "watch_state": "live",
  "playback_mode": "live",
  "live_playback": {
    "hls_url": "https://live.wayscloud.services/hls/live/qz0bKkTt6Vjvpb7/index.m3u8",
    "protocol": "hls"
  },
  "replay_playback": null
}

POST /v1/live-events/watch/{slug}/verify-token ​

Verify watch token

Validates an access token for a token-gated event. On success, issues a short-lived access grant and returns playback information.

The token use_count is not incremented here — it is consumed when playback actually starts via the consume-grant endpoint. This means opening the watch page and entering a token does not use up a token slot.

The token can also be supplied as a URL parameter on the watch page (?token=...) for auto-verification.

Request Body:

FieldTypeDescription
tokenstringRequired. Full watch token value as received when the token was created

Response:

FieldTypeDescription
verifiedbooleanWhether verification succeeded
event_idstringInternal event identifier
public_idstringGlobal event identity used by Meil Live and branded audience URLs
access_grantstringShort-lived access grant. Pass this to consume-grant when playback starts.
access_grant_expires_atstringWhen the access grant expires. Viewer must re-verify after expiry.
watch_statestringCurrent watch state at time of verification Values: not_started, access_required, live, rehearsal_hidden, processing_replay, replay_available, ended_no_replay, cancelled
playback_modestringWhich playback path is active Values: live, replay, none
live_playbackobjectLive stream info, if event is live
replay_playbackobjectReplay info, if replay is available

Example:

bash
curl -X POST https://api.wayscloud.services/v1/live-events/watch/{slug}/verify-token \
  -H "X-API-Key: wayscloud_live_abc12_YOUR_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
  "token": "wayscloud_le_k5q2ubCC8QAx1L2RNNMn8dLQ7bEeVNTm"
}'

Response:

json
{
  "verified": true,
  "event_id": "9a72d400-36a0-4fa5-bf7e-6883f262850a",
  "public_id": "4ee07f75-9be5-4ed6-a43f-4ad9319c6436",
  "access_grant": "ag_SqW1a2RzM1PB-bNUcXyZk0pQ7wE9vF3hJ6mT8nL",
  "access_grant_expires_at": "2026-04-10T15:00:00+00:00",
  "watch_state": "live",
  "playback_mode": "live",
  "live_playback": {
    "hls_url": "https://live.wayscloud.services/hls/live/qz0bKkTt6Vjvpb7/index.m3u8",
    "protocol": "hls"
  },
  "replay_playback": null
}

POST /v1/live-events/watch/{slug}/consume-grant ​

Consume access grant on playback start

Called by the watch page when video playback actually starts. Marks the access grant as consumed and increments the token use_count.

This is the point where a token use is actually spent. Idempotent — calling twice with the same grant returns already_consumed: true without incrementing again.

If the grant has expired, returns 403.

Request Body:

FieldTypeDescription
access_grantstringRequired. Access grant string (prefixed with ag_) received from verify-password or verify-token

Response:

FieldTypeDescription
consumedbooleanWhether the grant was consumed
already_consumedbooleanTrue if this grant was already consumed in a previous call. Token use_count is not incremented again.

Example:

bash
curl -X POST https://api.wayscloud.services/v1/live-events/watch/{slug}/consume-grant \
  -H "X-API-Key: wayscloud_live_abc12_YOUR_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
  "access_grant": "ag_SqW1a2RzM1PB-bNUcXyZk0pQ7wE9vF3hJ6mT8nL"
}'

Response:

json
{
  "consumed": true,
  "already_consumed": false
}

GET /v1/live-events/watch/by-id/ ​

Resolve watch state

Returns the current watch state for an event. The watch page polls this every 10 seconds to detect state changes (e.g. event goes live, replay becomes available).

Returns watch_state (viewer-facing UI state) and status (internal lifecycle). Playback objects are only included for public events — auth-required events must call verify-password or verify-token first.

Draft events are not publicly resolvable and return 404.

This tenant-independent variant is for Meil Live and verified customer audience domains. Do not use a customer-local slug for new integrations.

Response:

FieldTypeDescription
event_idstringUnique event identifier
public_idstringGlobal event identity used by Meil Live and branded audience URLs
slugstringURL-safe event identifier used in watch and embed URLs
namestringEvent display name
descriptionstringOptional event description
statusstringInternal lifecycle state. For UI logic, use watch_state instead. Values: scheduled, ready, rehearsal, live, ending, ended, processing, failed, cancelled
watch_statestringCanonical viewer-facing UI state. The watch page should render based on this field. Values: not_started, access_required, live, rehearsal_hidden, processing_replay, replay_available, ended_no_replay, cancelled
visibility_modestringAccess control model for this event Values: public, token, password, tenant_only
requires_authbooleanWhether the viewer must verify access (password, token, or login) before playback URLs are returned
auth_typestringWhich auth method is required, if any. Null for public events. Values: password, token, tenant_only
scheduled_start_atstringPlanned start time (ISO 8601)
scheduled_end_atstringPlanned end time (ISO 8601)
timezonestringIANA timezone for display purposes
countdown_enabledbooleanWhether to show a countdown timer before the event starts
playback_modestringWhich playback path is currently active Values: live, replay, none
live_playbackobjectLive stream playback info. Present only when the event is live and the viewer has access.
replay_playbackobjectReplay playback info. Present only when the event has ended with a published replay and the viewer has access.
embed_enabledbooleanWhether iframe embedding is permitted for this event
banner_urlstringOptional banner image URL for the watch page
logo_urlstringOptional logo image URL for the watch page

Example:

bash
curl https://api.wayscloud.services/v1/live-events/watch/by-id/{public_id} \
  -H "X-API-Key: wayscloud_live_abc12_YOUR_SECRET"

Response:

json
{
  "event_id": "9a72d400-36a0-4fa5-bf7e-6883f262850a",
  "public_id": "4ee07f75-9be5-4ed6-a43f-4ad9319c6436",
  "slug": "product-demo",
  "name": "Product Demo",
  "description": "Live demo of new release features",
  "status": "live",
  "watch_state": "live",
  "visibility_mode": "public",
  "requires_auth": false,
  "auth_type": null,
  "scheduled_start_at": "2026-04-10T12:00:00+00:00",
  "scheduled_end_at": "2026-04-10T13:30:00+00:00",
  "actual_start_at": "2026-04-10T12:01:10+00:00",
  "actual_end_at": null,
  "timezone": "Europe/Oslo",
  "countdown_enabled": false,
  "playback_mode": "live",
  "live_playback": {
    "hls_url": "https://live.wayscloud.services/hls/live/qz0bKkTt6Vjvpb7/index.m3u8",
    "protocol": "hls"
  },
  "replay_playback": null,
  "embed_enabled": true,
  "banner_url": null,
  "logo_url": null,
  "replay_published_at": null
}

POST /v1/live-events/watch/by-id/{public_id}/verify-password ​

Verify event password

Verifies the password for a password-protected event. On success, issues a short-lived access grant and returns the current playback information.

Failed attempts are logged for abuse detection.

This tenant-independent variant is for Meil Live and verified customer audience domains. Do not use a customer-local slug for new integrations.

Request Body:

FieldTypeDescription
passwordstringRequired. Event password set by the event organizer

Response:

FieldTypeDescription
verifiedbooleanWhether verification succeeded
event_idstringInternal event identifier
public_idstringGlobal event identity used by Meil Live and branded audience URLs
access_grantstringShort-lived access grant. Pass this to consume-grant when playback starts.
access_grant_expires_atstringWhen the access grant expires. Viewer must re-verify after expiry.
watch_statestringCurrent watch state at time of verification Values: not_started, access_required, live, rehearsal_hidden, processing_replay, replay_available, ended_no_replay, cancelled
playback_modestringWhich playback path is active Values: live, replay, none
live_playbackobjectLive stream info, if event is live
replay_playbackobjectReplay info, if replay is available

Example:

bash
curl -X POST https://api.wayscloud.services/v1/live-events/watch/by-id/{public_id}/verify-password \
  -H "X-API-Key: wayscloud_live_abc12_YOUR_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
  "password": "MyEventPass2026"
}'

Response:

json
{
  "verified": true,
  "event_id": "9a72d400-36a0-4fa5-bf7e-6883f262850a",
  "public_id": "4ee07f75-9be5-4ed6-a43f-4ad9319c6436",
  "access_grant": "ag_SqW1a2RzM1PB-bNUcXyZk0pQ7wE9vF3hJ6mT8nL",
  "access_grant_expires_at": "2026-04-10T15:00:00+00:00",
  "watch_state": "live",
  "playback_mode": "live",
  "live_playback": {
    "hls_url": "https://live.wayscloud.services/hls/live/qz0bKkTt6Vjvpb7/index.m3u8",
    "protocol": "hls"
  },
  "replay_playback": null
}

POST /v1/live-events/watch/by-id/{public_id}/verify-token ​

Verify watch token

Validates an access token for a token-gated event. On success, issues a short-lived access grant and returns playback information.

The token use_count is not incremented here — it is consumed when playback actually starts via the consume-grant endpoint. This means opening the watch page and entering a token does not use up a token slot.

The token can also be supplied as a URL parameter on the watch page (?token=...) for auto-verification.

This tenant-independent variant is for Meil Live and verified customer audience domains. Do not use a customer-local slug for new integrations.

Request Body:

FieldTypeDescription
tokenstringRequired. Full watch token value as received when the token was created

Response:

FieldTypeDescription
verifiedbooleanWhether verification succeeded
event_idstringInternal event identifier
public_idstringGlobal event identity used by Meil Live and branded audience URLs
access_grantstringShort-lived access grant. Pass this to consume-grant when playback starts.
access_grant_expires_atstringWhen the access grant expires. Viewer must re-verify after expiry.
watch_statestringCurrent watch state at time of verification Values: not_started, access_required, live, rehearsal_hidden, processing_replay, replay_available, ended_no_replay, cancelled
playback_modestringWhich playback path is active Values: live, replay, none
live_playbackobjectLive stream info, if event is live
replay_playbackobjectReplay info, if replay is available

Example:

bash
curl -X POST https://api.wayscloud.services/v1/live-events/watch/by-id/{public_id}/verify-token \
  -H "X-API-Key: wayscloud_live_abc12_YOUR_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
  "token": "wayscloud_le_k5q2ubCC8QAx1L2RNNMn8dLQ7bEeVNTm"
}'

Response:

json
{
  "verified": true,
  "event_id": "9a72d400-36a0-4fa5-bf7e-6883f262850a",
  "public_id": "4ee07f75-9be5-4ed6-a43f-4ad9319c6436",
  "access_grant": "ag_SqW1a2RzM1PB-bNUcXyZk0pQ7wE9vF3hJ6mT8nL",
  "access_grant_expires_at": "2026-04-10T15:00:00+00:00",
  "watch_state": "live",
  "playback_mode": "live",
  "live_playback": {
    "hls_url": "https://live.wayscloud.services/hls/live/qz0bKkTt6Vjvpb7/index.m3u8",
    "protocol": "hls"
  },
  "replay_playback": null
}

POST /v1/live-events/watch/by-id/{public_id}/consume-grant ​

Consume access grant on playback start

Called by the watch page when video playback actually starts. Marks the access grant as consumed and increments the token use_count.

This is the point where a token use is actually spent. Idempotent — calling twice with the same grant returns already_consumed: true without incrementing again.

If the grant has expired, returns 403.

This tenant-independent variant is for Meil Live and verified customer audience domains. Do not use a customer-local slug for new integrations.

Request Body:

FieldTypeDescription
access_grantstringRequired. Access grant string (prefixed with ag_) received from verify-password or verify-token

Response:

FieldTypeDescription
consumedbooleanWhether the grant was consumed
already_consumedbooleanTrue if this grant was already consumed in a previous call. Token use_count is not incremented again.

Example:

bash
curl -X POST https://api.wayscloud.services/v1/live-events/watch/by-id/{public_id}/consume-grant \
  -H "X-API-Key: wayscloud_live_abc12_YOUR_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
  "access_grant": "ag_SqW1a2RzM1PB-bNUcXyZk0pQ7wE9vF3hJ6mT8nL"
}'

Response:

json
{
  "consumed": true,
  "already_consumed": false
}