API REFERENCE
Live voice, three calls in.
Create a cast, mint a token for one of your users, and hand that token to a client. Your users never need a Soapbox account and your key never leaves your server.
Overview
A cast is a live audio room with a clock on it. You get 10 live at once, 50 people in each, and 4 hours at the outside. Nothing is recorded.
Everything below works against a test key, which creates real casts and is never billed. New accounts also get 5 free participant-minutes for live keys.
| FIELD | TYPE | NOTES |
|---|---|---|
Base URL | string | https://soapbox-server.fly.dev |
Auth | header | Authorization: Bearer sk_test_... or sk_live_... |
Content type | header | application/json on requests with a body |
Quickstart
Three calls, start to finish. Swap in your own key and identity.
# 1. create a cast
curl -X POST https://soapbox-server.fly.dev/v1/casts \
-H "authorization: Bearer $SOAPBOX_KEY" \
-H "content-type: application/json" \
-d '{"title":"Week 1 overreactions","tags":["NFL"]}'
# 2. mint a token for one of your users
curl -X POST https://soapbox-server.fly.dev/v1/casts/$CAST_ID/tokens \
-H "authorization: Bearer $SOAPBOX_KEY" \
-H "content-type: application/json" \
-d '{"identity":"user_8891","displayName":"Dana"}'
# 3. join with it, in the browser
# npm i @soapbox/embed
import { join } from '@soapbox/embed';
await join({ token, container: document.querySelector('#cast') });Get a key first
Authentication
Every request carries your secret key as a bearer token. Keys come in two modes, live and test, and they are shown in full exactly once when created.
Authorization: Bearer sk_live_...
The key is a server credential
Test keys
An sk_test_ key creates real casts, with real audio, and is never billed. Run the same call twenty times while you get it right. Test usage is recorded so you can see it, and never charged.
This is the intended way to build. The free live allowance is 5 participant-minutes, which a single test session can spend, so it is not meant to carry your integration work.
Casts
A cast holds 2 hosts, 8 guest seats pulled up from the crowd, and an audience, to a total of 50. It ends on its own at 4 hours and the row is deleted rather than archived.
Casts you create belong to your account. They never appear in the Soapbox consumer feed and they do not compete for its slots: you get your own pool of 10.
Tokens and roles
A token is minted for an identity you choose, which is your id for your user. It never becomes a Soapbox account and never counts against any Soapbox cap.
| FIELD | TYPE | NOTES |
|---|---|---|
host | role | Speaks, moderates, ends the cast. |
cohost | role | Everything except promoting another host. |
featured_guest | role | Speaks for the rest of the cast. |
listener | role | Audience. Chat, react and vote, no microphone. |
Limits
| FIELD | TYPE | NOTES |
|---|---|---|
Live casts | 10 | Per account, at once. Yours alone. |
People per cast | 50 | Hosts, guests and audience together. |
Duration | 4h | Hard stop, with warnings at 30, 10, 5 and 1 minute. |
Tags | 5 | Trimmed and de-duplicated on the way in. |
Message life | 180s | Then it is gone for everyone. |
What it refuses to do
No recordings, no transcripts, no chat history, no replay, no video and no screen share. A finished cast is deleted rather than archived, and listening without an account is capped at 5 minutes.
Check this before you build
API REFERENCE
Create a cast
/v1/casts| FIELD | TYPE | NOTES |
|---|---|---|
title | string | Required. Up to 90 characters. |
tags | string[] | Optional, up to 5. Leagues, teams as "LEAGUE:Team", or your own strings. |
curl -X POST https://soapbox-server.fly.dev/v1/casts \
-H "authorization: Bearer $SOAPBOX_KEY" \
-H "content-type: application/json" \
-d '{"title":"Week 1 overreactions","tags":["NFL"]}'{
"id": "c_9f2a...",
"title": "Week 1 overreactions",
"shareCode": "npya5h3xwq",
"maxParticipants": 50,
"startedAt": "2026-08-23T08:41:17.888Z",
"endsAt": "2026-08-23T12:41:17.888Z",
"url": "https://soapbox.3sb.io/s/npya5h3xwq"
}Returns 402 INSUFFICIENT_MINUTES on a live key with no balance, and 409 CAST_FULL when all 10 of your casts are already live.
List casts
/v1/casts{ "casts": [ { "id": "c_9f2a...", "title": "...", "shareCode": "...", "maxParticipants": 50, "endsAt": "..." } ] }Retrieve a cast
/v1/casts/{id}{
"id": "c_9f2a...",
"title": "Week 1 overreactions",
"shareCode": "npya5h3xwq",
"participantCount": 32,
"maxParticipants": 50,
"endsAt": "2026-08-23T12:41:17.888Z"
}End a cast
/v1/casts/{id}Ends the cast and deletes it. Not reversible, and there is nothing to restore afterwards, which is the point rather than a limitation.
{ "ended": true }Mint a token
/v1/casts/{id}/tokens| FIELD | TYPE | NOTES |
|---|---|---|
identity | string | Required. Your id for your user. Opaque to us. |
displayName | string | Required. What the stage shows. |
role | string | Optional, defaults to listener. |
{
"token": "eyJhbGciOi...",
"url": "wss://soapbox.livekit.cloud",
"role": "listener",
"canPublish": false,
"expiresAt": "2026-08-23T12:41:17.888Z"
}Usage
/v1/usageMinutes consumed this period, and what is left. A participant-minute is one person in a cast for one minute, which is how our own provider bills us.
{
"mode": "live",
"billable": true,
"balance": { "freeMinutesRemaining": 0, "purchasedMinutesRemaining": 840, "totalRemaining": 840 },
"last30Days": { "participantMinutes": 1160, "sessions": 48 }
}Errors
Every error carries a stable machine code, a human message, a docs_url, and where there is one, a fix naming the next action.
{
"error": {
"code": "INSUFFICIENT_MINUTES",
"message": "This account has no minutes left this period.",
"fix": "Buy a pack from the account page, or use a test key while you build."
}
}| FIELD | TYPE | NOTES |
|---|---|---|
INSUFFICIENT_MINUTES | 402 | Live key, zero balance. |
CAST_FULL | 409 | Your pool of casts is fully in use. |
CAST_NOT_FOUND | 404 | Wrong id, or the cast already ended. |
UNAUTHENTICATED | 401 | Missing or invalid key. |
RATE_LIMITED | 429 | Back off and retry. |
BUILDING WITH AGENTS
Integration prompts
Each block is self-contained: the contract, the versions, the security invariants and a step that proves the integration works. Paste one into a coding agent.
MCP server
So an agent can create a cast, mint a token and read usage as tool calls while it builds, instead of writing throwaway scripts.
{
"mcpServers": {
"soapbox": {
"command": "npx",
"args": ["-y", "@soapbox/mcp"],
"env": { "SOAPBOX_API_KEY": "sk_test_..." }
}
}
}Machine readable
The whole surface, in one fetch, for an agent that would rather read than crawl.
- /llms.txt, the short version
- /llms-full.txt, every endpoint and error in one file
- /openapi.yaml, the contract the SDK and MCP server are built from
BILLING
Pricing
5 free participant-minutes to start, once. After that, $10 buys 1,000 participant-minutes, billed monthly, and your balance refills to the full amount at the start of every period. A heavy month never leaves you short the next one, and the bill is the same number every time.
Test keys are outside all of this. They create real casts and are never billed, however many times you call them.
Buying minutes
Buy packs from your account page. Each pack is 1,000 minutes a month, and the number of packs is the quantity on one subscription, so changing it changes the monthly total rather than stacking one-off charges.
GO TO YOUR ACCOUNT