Skip to main content
Live streams are real-time broadcasts that show up in your feed exactly like any other content item. Once a stream ends, the recording stays in the feed as on-demand video, and you can carve clips out of it for separate distribution. This guide walks through the full lifecycle: creating a stream, broadcasting to it, displaying it in the SDK, and turning the recording into clips.

How a live stream flows through ShortKit

  1. Create the stream with POST /v1/live-streams. Choose a protocol — hls for standard latency or webrtc for sub-second delivery. You receive a playbackId (for viewers) and broadcast credentials (rtmpUrl + streamKey) for your encoder.
  2. Forward the credentials to your broadcaster. They paste them into their encoder of choice. The broadcast workflow is the same regardless of protocol.
  3. The broadcaster goes live. As soon as ShortKit receives video, the stream’s status flips from idle to active. The stream appears in your feed automatically — no separate publish step.
  4. Viewers watch from your app. The SDK plays the live stream the same way it plays any video. A live badge and viewer count are available to overlay on top.
  5. The stream ends. Either the broadcaster disconnects (and stays disconnected longer than reconnectWindow on HLS streams), or you call POST /v1/live-streams/{id}/end. The status moves to ended and the recording stays in the feed as a regular video.
  6. Optionally, create clips from the recording with POST /v1/live-streams/{id}/clips. Each clip becomes its own content item.

Choosing a protocol

ShortKit supports two ingest and delivery protocols: Specify protocol when you create the stream:
The broadcast workflow is identical for both protocols. Your encoder always connects to the rtmpUrl from the create response — there is no separate setup required for WebRTC. The protocol choice only affects how the stream is delivered to viewers; the ShortKit SDK handles playback automatically. The protocol cannot be changed after creation. latencyMode and reconnectWindow apply only to hls streams and are ignored for webrtc streams.

Creating a stream

You create a stream from your backend using your secret key:
The response includes the broadcaster credentials:
rtmpUrl and streamKey are credentials. Anyone with them can broadcast under your stream. Forward them only to the broadcaster who will publish the stream. Do not log them, expose them in your client app, or commit them to source control.
The credentials are returned only on this response. If you lose them, delete the stream and create a new one.

Broadcasting to a stream

Once you have the rtmpUrl and streamKey from the create response, point your encoder at them to start pushing video. rtmpUrl already embeds the stream key, so for tools that take a single URL (such as ffmpeg), pass it directly:
For broadcast software (OBS, Wirecast, and similar) that has separate Server and Stream Key fields, split the URL at the key boundary: For example, with a WebRTC stream whose rtmpUrl is rtmps://ingest.shortkit.dev/x/AbCdEfGhIjKl:
  • Server: rtmps://ingest.shortkit.dev/x/
  • Stream Key: AbCdEfGhIjKl
The broadcast workflow is the same regardless of whether you created an hls or webrtc stream — the difference is entirely on the viewer delivery side.

Displaying live streams in the feed

Live streams render in the feed with no extra setup. The SDK’s ContentItem exposes the following live-specific fields you can read in your custom overlay:
  • isLive — true while the broadcast is in progress, false after it ends
  • liveStreamStatus — "idle", "active", or "ended" (more on lifecycle)
  • liveStreamId — the underlying live stream’s UUID (use this from your backend to address the stream itself, e.g. for creating clips)
  • currentViewers — concurrent viewer count for the stream (0 for non-live items)
  • startedAt — ISO 8601 timestamp the broadcaster connected (useful for an elapsed-time display)
The SDK automatically reports viewer presence on your behalf — every active viewer counts toward currentViewers for as long as they’re watching. The mechanism is a live.viewer.heartbeat event the SDK fires every 30 seconds while a live item is the active playing item. You don’t need to call any tracking API or write your own heartbeat code; just render the field. For a known set of streams (for example, those currently visible to a viewer in your UI), you can also poll Get Live Stream Status directly with your publishable key to react to status changes (active → ended) more promptly than the next feed refresh would surface them.

Surfacing a specific live stream in a custom feed

If you’re using custom feed mode and want to surface a known stream at a specific position, pass its playbackId as a video input — the SDK plays it like any other:
The SDK detects whether the playback ID is live or on-demand at play time and configures the player accordingly.

Turning a stream into clips

You can carve short clips out of a stream while it’s still active (real-time clipping during the broadcast) or after it has ended. Specify start and end offsets in seconds from the beginning of the stream:
Each clip becomes its own content item with a fresh contentId and playbackId. The clip is processing for a few seconds to a few minutes, then becomes ready and shows up in the feed like any other video. If you provide a callbackUrl, ShortKit will POST to it once each clip is ready — handy if you want to re-share clips into your app immediately without polling. See the Create Clips reference for the full request and response shape.

Letting end users create clips

If you want to expose a “clip this moment” affordance directly in your client app, don’t ship your secret key with the app — secret keys grant full server-side access to your organization and are extractable from any shipped binary. Instead, expose your own backend endpoint (using whatever user-auth your app already does) that takes a clip request from your client and forwards it to ShortKit’s clip API with your secret key. That gives you a place to enforce per-user rate limits, attribution, and abuse controls before a clip is created. The client app already has everything it needs to construct the request: read liveStreamId and the marked time offsets from the live ContentItem, send them to your backend, and your backend handles the rest.

Ending a stream

End any stream — regardless of protocol — by calling:
HLS streams also end automatically if the broadcaster disconnects and stays disconnected past the reconnectWindow you configured at creation time (default: 60 seconds). Use the explicit end call above when you want to close the stream immediately rather than waiting for the timeout. Once ended, a stream cannot be restarted. Create a new live stream for the next broadcast. For the full object shape, field descriptions, and all available endpoints, see the Live Stream API reference.