# Livepush Developers API

Official REST API reference for Livepush.

The Livepush API allows developers to programmatically manage
live streams, multistreaming destinations, video libraries,
recordings, scheduling, and media ingestion workflows.

This specification defines the base structure for all Livepush
API resources. Some endpoints may be introduced incrementally
as additional APIs become available.


Version: 1.0.0

## Base URLs

- `https://tokens.livepush.io` — Authentication & OAuth 2.0
- `https://octopus.livepush.io` — Core Streams & Media APIs
- `https://squid.livepush.io` — Accounts & Billing APIs
- `https://vod-web-import-api.livepush.io` — Livepush VOD Import API
- `https://usages.livepush.io` — Usage & Bandwidth API

## Authentication

All endpoints use bearer authentication: `Authorization: Bearer <token>`.

## Authentication

Access tokens and the OAuth 2.0 authorization-code flow

Every Livepush endpoint expects a JWT in the `Authorization` header. Tokens are issued by
the auth service at `https://tokens.livepush.io` through the OAuth 2.0 authorization-code
flow, and the three endpoints below are the whole of it.

**The flow, step by step**

1. **Register your app** at [the developer console](/console/apps/).
   You get a `client_id`, a `client_secret`, and a list of redirect URIs. A redirect URI
   sent later must match one of these exactly — there is no prefix matching.
2. **Ask for consent.** Call `GET /oauth2/authorize` with your `client_id`,
   `redirect_uri`, `response_type=code`, the `scope` list you need, and a random `state`.
   It returns JSON describing the consent screen rather than rendering one, so you build
   the UI. The `sessionID` it returns lives for 5 minutes.
3. **Send the decision back.** `POST /oauth2/authorize` with `session_id` and
   `is_rejected`. The response is a `301` to your redirect URI carrying either `code` and
   `state`, or `error` and `error_description`. Check `state` matches what you sent.
4. **Exchange the code.** Call `GET /oauth2/access_token` with `grant_type=authorization_code`,
   the `code`, your `client_id`, `client_secret` and the same `redirect_uri`. You get an
   `access_token` valid for 14 days and a `refresh_token`. The code is single-use and
   expires after 10 minutes.
5. **Call the API.** Send `Authorization: Bearer <access_token>` on every request, whatever
   `token_type` says.
6. **Refresh before day 14.** Same endpoint with `grant_type=refresh_token`, passing the
   refresh token in the `code` parameter. Refresh tokens are single-use, so store the new
   one from every response.

The [Authentication guide](/guides/authentication/) covers scopes, error codes and a
shortcut for getting a token while you are just experimenting.

- [GET /oauth2/authorize](https://developers.livepush.io/authentication/get-the-consent-screen/): Starts the authorization-code flow and returns the data needed to render a consent screen. Unlike most OAuth servers this returns JSON rather than an HTML page — you build the consent UI and post the user's decision back. The user must already have a Livepush session; the request is authenticated by the srid cookie, not by a bearer token. The sessionID in the response is valid for 5 minutes.
- [POST /oauth2/authorize](https://developers.livepush.io/authentication/submit-the-consent-decision/): Records the user's decision and redirects back to your app. On approval the redirect carries code (valid for 10 minutes, single use) and your state. On refusal or any validation failure it carries error and errordescription instead, and no code.
- [GET /oauth2/access_token](https://developers.livepush.io/authentication/exchange-a-code-or-refresh-token/): Exchanges an authorization code for an access and refresh token pair, or rotates an existing refresh token. Access tokens are valid for 14 days. Refresh tokens are single use — the supplied one is disabled as soon as a new pair is issued, so store the new refreshtoken from every response. Call this server-side only. It is a GET and takes clientsecret as a query parameter, so the secret lands in proxy logs, browser history and access logs if it is ever called from a client. Make sure your own logging redacts it.

## Accounts

Account-level resources and metadata

- [GET /account/this](https://developers.livepush.io/accounts/get-user-details/): Retrieves details of the currently authenticated user account. The response includes profile information, preferences, and basic billing metadata.
- [GET /account/subscriptions](https://developers.livepush.io/accounts/get-user-subscriptions/): Returns a list of active and historical subscriptions associated with the authenticated user account.

## Streams

Live stream creation and lifecycle management

- [GET /streams/mine](https://developers.livepush.io/streams/get-user-streams/): Returns the list of live streams owned by the authenticated user. Each stream includes its configuration, assigned zone, metadata, and connected streaming destinations.
- [POST /streams](https://developers.livepush.io/streams/create-a-new-stream/): Creates a new live stream for the authenticated user. The stream is initialized with the provided category and name and is assigned to a default processing zone.
- [GET /streams/{stream_id}](https://developers.livepush.io/streams/get-stream-by-id/): Retrieves details of a specific live stream owned by the authenticated user. The response includes stream metadata, configuration, zone assignment, and destinations.
- [DELETE /streams/{stream_id}](https://developers.livepush.io/streams/delete-live-stream/): Permanently deletes a live stream owned by the authenticated user. Once deleted, the live stream configuration, associated destinations, and related metadata will be removed and cannot be recovered.

## Destinations

Streaming destinations (YouTube, Facebook, RTMP, etc.)

- [GET /streams/me/destinations](https://developers.livepush.io/destinations/list-saved-destinations/): Returns the list of saved streaming destinations owned by the authenticated user. Saved destinations can be used for multistreaming and may include platforms such as YouTube, Facebook, or custom RTMP endpoints.
- [POST /streams/{stream_id}/destinations](https://developers.livepush.io/destinations/create-new-stream-destination/): Creates and attaches a new streaming destination to the specified live stream. This endpoint is used to add platforms such as YouTube, Facebook, or custom RTMP destinations to an existing live stream.
- [PUT /streams/{stream_id}/destinations/{destination_id}/enable](https://developers.livepush.io/destinations/enable-stream-destination/): Enables a previously added destination for the specified live stream. Once enabled, the destination will start receiving the live stream when the stream is online.
- [PUT /streams/{stream_id}/destinations/{destination_id}/disable](https://developers.livepush.io/destinations/disable-stream-destination/): Disables an active destination for the specified live stream. When disabled, the destination will no longer receive the live stream until it is re-enabled.
- [DELETE /streams/{stream_id}/destinations/{destination_id}](https://developers.livepush.io/destinations/delete-stream-destination/): Permanently deletes a destination from the specified live stream. Once deleted, the destination will be removed entirely and can no longer be enabled or reused.

## Videos

Video library and VOD assets

- [GET /streams/me/videos](https://developers.livepush.io/videos/get-user-videos/): Returns every video in the authenticated account's library, across all streams. Requires a token with the streams.videos.read scope.
- [GET /streams/me/videos/storage_specs](https://developers.livepush.io/videos/get-video-storage-specs/): Returns the storage zones available to the account and the switches that govern how an upload must be performed. Call this before every upload session. It tells you which zone to write to (defaultStorageZone), whether the user may choose another (canSelectStorage), and whether the multipart flow is available at all (isMultipartUploadDisabled). When multipart is disabled, every file must go through the single-request upload URL no matter its size. Requires a token with the streams.videos.read scope.
- [GET /streams/{stream_id}/videos](https://developers.livepush.io/videos/list-videos-on-a-stream/): Returns the videos attached to one stream, in playlist order. Requires a token with the streams.videos.read scope.
- [POST /streams/{stream_id}/videos](https://developers.livepush.io/videos/register-an-uploaded-video/): Registers an object already written to storage as a video in the library. This is the final step of an upload: request a URL, PUT the bytes, then call this. Requires a token with the streams.videos.write scope.
- [PUT /streams/{stream_id}/videos/arrange](https://developers.livepush.io/videos/reorder-stream-videos/): Sets the playback order of the videos attached to a stream. Not called by the dashboard. Requires a token with the streams.videos.write scope.
- [GET /streams/{stream_id}/videos/{video_id}](https://developers.livepush.io/videos/get-video-by-id/): Returns one video. Snapshot URLs are rewritten from raw bucket hosts to the Livepush CDN before being returned. Requires a token with the streams.videos.write scope.
- [PUT /streams/{stream_id}/videos/{video_id}](https://developers.livepush.io/videos/update-video-metadata/): Updates the editable metadata on a video — label, description, tags and thumbnail. Requires a token with the streams.videos.write scope.
- [DELETE /streams/{stream_id}/videos/{video_id}](https://developers.livepush.io/videos/delete-a-video/): Permanently deletes a video and its stored object. Requires a token with the streams.videos.write scope.
- [GET /streams/{stream_id}/videos/{video_id}/codecinfo](https://developers.livepush.io/videos/get-video-codec-info/): Returns container and per-track codec details for a video: duration, resolution, frame rate and the audio and video codecs in use. When the stored media info already lists codecs it is returned as-is; otherwise the API probes the file, caches the result on the video, and returns the fresh reading. Requires a token with the streams.videos.write scope.
- [POST /streams/{stream_id}/videos/{video_id}/retranscode](https://developers.livepush.io/videos/re-transcode-a-video/): Queues the video for transcoding again, optionally against a different encoding preset. Increments the video's retranscodeCount. Requires a token with the streams.videos.write scope.
- [GET /streams/{stream_id}/videos/{video_id}/download_url/signed](https://developers.livepush.io/videos/get-a-signed-download-url/): Returns a time-limited URL for downloading the source file. Not called by the dashboard. Requires a token with the streams.videos.read scope.
- [GET /streams/{stream_id}/videos/{video_id}/thumb_url/signed](https://developers.livepush.io/videos/get-a-signed-thumbnail-url/): Returns a time-limited URL for the video thumbnail. Responds 404 when the video has no snapshot yet. Not called by the dashboard. Requires a token with the streams.videos.read scope.
- [PUT /streams/{stream_id}/videos/{video_id}/set_group/{group_id}](https://developers.livepush.io/videos/move-a-video-into-a-folder/): Files the video under a video folder. A video belongs to at most one folder, so this moves it rather than adding a second membership. Video folders appear as resourcegroup in the URL and as resourceGroup on the video object — the original internal name, kept for compatibility. Requires a token with the streams.videos.write scope.
- [PUT /streams/{stream_id}/videos/{video_id}/unset_group](https://developers.livepush.io/videos/remove-a-video-from-its-folder/): Takes the video out of its folder and returns it to the top level of the library. The video itself is untouched. Video folders appear as resourcegroup in the URL and as resourceGroup on the video object — the original internal name, kept for compatibility. Requires a token with the streams.videos.write scope.
- [GET /streams/{stream_id}/videos/resource_groups](https://developers.livepush.io/videos/list-video-folders/): Returns the video folders defined for the account. Video folders appear as resourcegroup in the URL and as resourceGroup on the video object — the original internal name, kept for compatibility. Requires a token with the streams.videos.write scope.
- [POST /streams/{stream_id}/videos/resource_group](https://developers.livepush.io/videos/create-a-video-folder/): Creates a video folder. Passing the id of an existing folder renames that folder instead of creating a new one. Video folders appear as resourcegroup in the URL and as resourceGroup on the video object — the original internal name, kept for compatibility. Requires a token with the streams.videos.write scope.
- [DELETE /streams/{stream_id}/videos/resource_group/{group_id}](https://developers.livepush.io/videos/delete-a-video-folder/): Deletes a video folder. The videos inside it are not deleted — they return to the top level of the library. Video folders appear as resourcegroup in the URL and as resourceGroup on the video object — the original internal name, kept for compatibility. Requires a token with the streams.videos.write scope.
- [POST /streams/{stream_id}/videos/uploadurl](https://developers.livepush.io/videos/create-a-video-upload-url/): Returns a URL to upload a video file to. Use this for a single-request upload; for large files use the multipart flow instead. The response tells you how to upload via uploadType: direct is a plain PUT to uploadUrl, formdata posts the file with the fields in uploadCredentials. Keep id and Key — registering the video afterwards needs them. Requires a token with the streams.videos.write scope.
- [POST /streams/{stream_id}/videos/uploadurl/signed](https://developers.livepush.io/videos/create-a-signed-video-upload-url/): Returns a pre-signed upload URL, for clients that cannot use the plain upload URL. The response shape matches the plain variant. Requires a token with the streams.videos.write scope.
- [POST /streams/{stream_id}/videos/uploadurl/multipart](https://developers.livepush.io/videos/start-a-multipart-upload/): Opens a multipart upload session for a large video and returns the uploadId and object Key used by the remaining multipart calls. Check isMultipartUploadDisabled on the storage specs first — when it is true this endpoint is closed to the account. Requires a token with the streams.videos.write scope.
- [POST /streams/{stream_id}/videos/uploadurl/multipart/part/signed](https://developers.livepush.io/videos/sign-a-multipart-upload-part/): Returns a pre-signed URL for one part. Call once per part, then keep each response ETag for the finish call. Requires a token with the streams.videos.write scope.
- [POST /streams/{stream_id}/videos/uploadurl/multipart/finish](https://developers.livepush.io/videos/finish-a-multipart-upload/): Completes the multipart upload by listing every uploaded part with its ETag. The object only becomes readable once this succeeds. The body is the storage provider's completion record, passed through unchanged. Requires a token with the streams.videos.write scope.
- [POST /streams/{stream_id}/videos/uploadurl/multipart/abort](https://developers.livepush.io/videos/abort-a-multipart-upload/): Abandons the session and releases the parts already written. Call this on client-side upload failure so storage is not left holding orphaned parts. The body is whatever the storage provider returns for an abort, which is often empty. A failed abort is not reported as an error status. Requires a token with the streams.videos.write scope.

## Players

Standalone multi-source players

- [POST /players](https://developers.livepush.io/players/create-a-player/): Creates a standalone player. Unlike a stream embed, a player can carry several sources (streams, videos or URLs) behind one embed. Requires a token with CanCreatePlayers.
- [GET /players/mine](https://developers.livepush.io/players/list-your-players/): Returns every standalone player owned by the authenticated user. Requires a token with CanReadPlayers.
- [GET /players/suggestions](https://developers.livepush.io/players/get-player-creation-suggestions/): Returns suggested sources for a new player, based on the account's existing streams and videos. Not used by the dashboard. Requires a token with CanReadPlayers.
- [GET /players/{player_id}](https://developers.livepush.io/players/get-player-by-id/): Returns a single player with its configuration and sources. Requires a token with CanReadPlayers.
- [DELETE /players/{player_id}](https://developers.livepush.io/players/delete-a-player/): Permanently deletes a player. The player is force-disabled before removal, so any live embed stops immediately. Requires a token with CanDeletePlayers.
- [PUT /players/{player_id}/enable](https://developers.livepush.io/players/enable-a-player/): Re-enables a disabled player. Not used by the dashboard. Requires a token with CanWritePlayers.
- [PUT /players/{player_id}/disable](https://developers.livepush.io/players/disable-a-player/): Disables a player without deleting it. Not used by the dashboard. Requires a token with CanWritePlayers.
- [PUT /players/{player_id}/name](https://developers.livepush.io/players/rename-a-player/): Updates the player's display name. Not used by the dashboard. Requires a token with CanWritePlayers.
- [PUT /players/{player_id}/config](https://developers.livepush.io/players/replace-player-configuration/): Sets the player's embed configuration — the player equivalent of the /streams/{streamid}/embed/ endpoints, as a single call. This replaces the entire config object rather than merging into it. Fields you omit are cleared, so always send the complete configuration. Unknown fields are stripped rather than rejected. Not used by the dashboard. Requires a token with CanWritePlayers.

## Stream Embed

Embedded player configuration for a live stream

- [PUT /streams/{stream_id}/embed/title](https://developers.livepush.io/stream-embed/set-embed-title/): Sets the title shown in the embedded player. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/color](https://developers.livepush.io/stream-embed/set-embed-colour-scheme/): Sets the accent colour of the embedded player. Returns 400 when no colour is supplied. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/channel_logo](https://developers.livepush.io/stream-embed/save-embed-channel-logo-settings/): Configures the channel logo overlay: image, size, position, layout and click-through URL. Requires a token with write access to the stream (CanWriteStreams).
- [GET /streams/{stream_id}/embed/assets/cover_img](https://developers.livepush.io/stream-embed/get-embed-cover-image/): Returns the cover image currently attached to the stream embed. Read-only: this is the one embed route guarded by CanReadStreams rather than CanWriteStreams. The dashboard does not call it. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/assets/cover_img](https://developers.livepush.io/stream-embed/set-embed-cover-image/): Attaches an already-uploaded image as the player cover, shown before playback starts. Upload the file first with POST /streams/{streamid}/embed/assets/uploadurl. Requires a token with write access to the stream (CanWriteStreams).
- [DELETE /streams/{stream_id}/embed/assets/cover_img](https://developers.livepush.io/stream-embed/remove-embed-cover-image/): Detaches the cover image. The underlying asset is not deleted. Requires a token with write access to the stream (CanWriteStreams).
- [POST /streams/{stream_id}/embed/assets/upload_url](https://developers.livepush.io/stream-embed/create-embed-asset-upload-url/): Returns a signed URL for uploading an embed asset — a cover image, brand icon or caption image. Upload the bytes to the returned URL, then attach the asset with the matching setting endpoint. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/offline_text](https://developers.livepush.io/stream-embed/set-embed-offline-text/): Sets the message shown in the player while the stream is offline. Pass alternateText=1 to set the secondary offline message instead of the primary one. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/offline_text_mode](https://developers.livepush.io/stream-embed/toggle-offline-text-mode/): Switches between the primary and alternate offline messages. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/autoplay](https://developers.livepush.io/stream-embed/toggle-embed-autoplay/): Controls whether the embedded player starts playing automatically. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/abr](https://developers.livepush.io/stream-embed/toggle-adaptive-bitrate/): Enables or disables adaptive bitrate streaming in the embedded player. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/live_rewind](https://developers.livepush.io/stream-embed/toggle-live-rewind/): Enables or disables rewinding within a live stream. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/set_uninterrupted_mode](https://developers.livepush.io/stream-embed/toggle-uninterrupted-mode/): When enabled, the player keeps the session going across short source interruptions instead of dropping to the offline state. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/premier](https://developers.livepush.io/stream-embed/toggle-premiere-mode/): Enables premiere mode, which holds viewers on a countdown until the scheduled start. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/premier/text](https://developers.livepush.io/stream-embed/set-premiere-text/): Sets the message shown during the premiere countdown. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/set_viewers_counter](https://developers.livepush.io/stream-embed/toggle-the-viewer-counter/): Controls visibility of the live viewer count in the player. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/set_pause_control](https://developers.livepush.io/stream-embed/toggle-the-pause-control/): Controls whether viewers can pause playback. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/toggle_live_badge](https://developers.livepush.io/stream-embed/toggle-the-live-badge/): Controls visibility of the LIVE badge in the player. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/plugins](https://developers.livepush.io/stream-embed/set-embed-analytics-plugins/): Configures third-party analytics integrations for the embedded player. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/chat_config](https://developers.livepush.io/stream-embed/set-embed-chat-configuration/): Configures the chat panel shown alongside the embedded player. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/password](https://developers.livepush.io/stream-embed/set-embed-password/): Password-protects the embed. Send an empty string to remove the password. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/domains](https://developers.livepush.io/stream-embed/set-allowed-embed-domains/): Restricts playback to the listed domains. An empty array allows every domain. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/geo](https://developers.livepush.io/stream-embed/set-embed-geo-restrictions/): Restricts playback to the listed country codes. An empty array allows every country. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/iframe_restriction](https://developers.livepush.io/stream-embed/set-iframe-hosting-rule/): Controls whether the embed may be hosted inside an iframe. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/mode/cdn](https://developers.livepush.io/stream-embed/toggle-cdn-embed-mode/): Switches the embed to CDN delivery. Enabling this checks the account subscription before applying. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/mode/external](https://developers.livepush.io/stream-embed/toggle-external-embed-mode/): Switches the embed to an external delivery source. Toggling this resets the cdnReady flag on the stream. Requires a token with write access to the stream (CanWriteStreams).
- [PUT /streams/{stream_id}/embed/preferred_destination](https://developers.livepush.io/stream-embed/set-preferred-embed-destination/): Chooses which connected destination the embed plays back from. Requires a token with write access to the stream (CanWriteStreams).
- [POST /streams/{stream_id}/embed/produce_direct_links](https://developers.livepush.io/stream-embed/produce-direct-playback-links/): Generates direct output links for the stream, for use outside the Livepush player. Requires a token with write access to the stream (CanWriteStreams).
- [POST /streams/{stream_id}/embed/use_direct_links_for_embed](https://developers.livepush.io/stream-embed/toggle-direct-links-for-the-embed/): Switches the embed to play from the direct output URL rather than the managed player source. Requires a token with write access to the stream (CanWriteStreams).

## Video Imports

Import videos from direct URLs (S3, HTTPS)

- [POST /inspector/get_metadata](https://developers.livepush.io/video-imports/inspect-remote-video-metadata/): Inspects a video hosted at a direct URL (e.g. Amazon S3, HTTPS) and returns metadata required before starting a video import. This step is mandatory before creating a transfer.
- [POST /transfers/new](https://developers.livepush.io/video-imports/start-a-new-video-import/): Starts an asynchronous video import using the metadata ID returned by the inspector endpoint.
- [GET /transfers/queued](https://developers.livepush.io/video-imports/list-queued-video-imports/): Returns video imports that are currently queued or processing. If a previously created video ID is no longer present, the import is considered complete and the video will appear in the VOD library.

## Stream Recordings

Recordings generated from live streams

- [GET /streams/me/recordings](https://developers.livepush.io/stream-recordings/list-user-stream-recordings/): Returns the list of stream recordings owned by the authenticated user. These recordings are generated from live streams and may include completed, queued, or errored recording entries.
- [GET /streams/{stream_id}/recordings](https://developers.livepush.io/stream-recordings/list-stream-recordings-by-stream/): Returns the list of recordings generated for a specific live stream. This endpoint is useful for retrieving all historical recordings associated with a single stream.

## Stream Zones

Processing and storage regions

- [GET /zones/simulcast](https://developers.livepush.io/stream-zones/list-available-rtmp-ingestion-zones/): Returns the list of available stream zones that can be used for simulcast and stream deployment. Zones represent geographic regions and infrastructure locations available for publishing and routing live streams.

## Stream Scheduler

Scheduled and automated streaming

- [PUT /streams/{stream_id}/config/scheduler/playlist](https://developers.livepush.io/stream-scheduler/attach-videos-to-the-pre-recorded-stream-playlist/): Attaches one or more existing videos to the scheduler playlist of a pre-recorded live stream. The playlist defines the playback order for scheduled or looping pre-recorded live streams.
- [PUT /streams/{stream_id}/config/scheduler/loop](https://developers.livepush.io/stream-scheduler/toggle-scheduler-looping/): Enables or disables looping for the scheduler playlist. When enabled, the playlist will repeat indefinitely, allowing continuous 24/7 pre-recorded live streaming.
- [POST /streams/{stream_id}/config/scheduler/events](https://developers.livepush.io/stream-scheduler/schedule-a-pre-recorded-live-stream/): Schedules a pre-recorded live stream to start at a specific date and time using the configured playlist. This endpoint is used for both one-time scheduled events and looping (24/7) streams.
- [DELETE /streams/{stream_id}/config/scheduler/events/{event_id}](https://developers.livepush.io/stream-scheduler/delete-scheduled-stream-event/): Deletes a scheduled pre-recorded live stream event before it starts. This operation does not affect the stream configuration or playlist.
- [PUT /streams/{stream_id}/config/scheduler/events/{event_id}/end](https://developers.livepush.io/stream-scheduler/end-active-scheduled-stream/): Stops a currently running pre-recorded live stream event. Ending a stream is not instantaneous and may take a few seconds to fully stop playback and disconnect destinations.

## Usage

CDN bandwidth delivered, per hostname and per stream

Livepush records delivered bytes against the hostname they were served on,
not against the stream directly. A stream therefore has a bandwidth figure
of its own only when it has a hostname of its own. Streams without one
deliver on the account's primary hostname, where their traffic is pooled
with every other such stream and with anyone still using an older link.

Both endpoints report the same `assignment` on every row, and it is the
field to read first:

| `assignment` | What the bytes mean |
| --- | --- |
| `dedicated` | One stream on the hostname, so the figure is that stream's |
| `shared` | Several streams on the hostname; the figure covers all of them |
| `pooled` | The account's primary hostname; traffic cannot be split per stream |
| `other` | Hostnames no longer configured, kept so the rows still sum to the account total |

**These are delivery figures for reporting, not billing.** Allowance, quota
and overage come from the account's subscription and are not returned here.
Values are billable bytes as integers; the dashboard's GB is bytes divided
by 1e9. Every date is a UTC day, ranges are inclusive at both ends and span
at most 400 days, and a collector writes the rows periodically, so the
current day is always partial and `lastUpdated` tells you how stale a figure
is.

- [GET /usage/cdn/hostnames](https://developers.livepush.io/usage/get-bandwidth-by-hostname/): Returns every delivery hostname on the account with its billable bytes for the range, which is how you split CDN bandwidth per channel. Picking a range. Send nothing and you get the current billing term, from the day it started through today, with range.isCurrentTerm set to true. Send from, till, or both to ask for specific UTC days instead. from on its own runs to today; till on its own starts at the current term. The maximum span is 400 days. Reading the rows. The account's primary hostname comes first, then the rest by descending bytes, then a synthetic other row holding traffic recorded against hostnames that are no longer configured. other is always present, even at zero, so the rows always sum to accountBytes. Only a hostname with assignment: dedicated belongs to a single stream. A pooled or shared row covers more than one stream and cannot be split further, so do not divide it. These are delivery figures, not an invoice. Quota, allowance and overage are not reported here; they come from the account's subscription. Figures are written by a collector that runs periodically, so the current day is always partial and lastUpdated says how fresh the numbers are. Add daily=true for a per-day series on every row.
- [GET /usage/cdn/streams/{stream_id}](https://developers.livepush.io/usage/get-bandwidth-for-a-stream/): Returns the bandwidth recorded for one stream, resolved through the hostname it delivers on. Ranges work exactly as they do on GET /usage/cdn/hostnames. Check assignment before you trust bytes. Only dedicated means the figure belongs to this stream alone. shared means the hostname carries the streams named in sharedWith as well, so the figure covers all of them. pooled means the stream delivers on the account's primary hostname, where traffic cannot be attributed per stream: bytes is null and reason explains why. A stream with no per-stream tracking is not an error. It returns 200 with assignment: pooled and a reason, because whether a stream has its own hostname is account configuration rather than a bad request. The only 404 is a stream that does not exist or is not yours. Add daily=true for the per-day series. Days with no traffic are omitted, so do not assume one entry per day in the range.
