Soapbox

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.

FIELDTYPENOTES
Base URLstringhttps://soapbox-server.fly.dev
AuthheaderAuthorization: Bearer sk_test_... or sk_live_...
Content typeheaderapplication/json on requests with a body

Quickstart

Three calls, start to finish. Swap in your own key and identity.

CURL
# 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

Sign in and a test key is waiting on your account page. No card, no expiry.

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.

HEADER
Authorization: Bearer sk_live_...

The key is a server credential

Never put it in a page, a bundle, an app binary or a client side environment variable. A live key arriving from a browser origin is rejected as compromised, because by then it is. Mint tokens on your server and send the token to the client.

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.

FIELDTYPENOTES
hostroleSpeaks, moderates, ends the cast.
cohostroleEverything except promoting another host.
featured_guestroleSpeaks for the rest of the cast.
listenerroleAudience. Chat, react and vote, no microphone.

Limits

FIELDTYPENOTES
Live casts10Per account, at once. Yours alone.
People per cast50Hosts, guests and audience together.
Duration4hHard stop, with warnings at 30, 10, 5 and 1 minute.
Tags5Trimmed and de-duplicated on the way in.
Message life180sThen 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

If a feature you are planning needs an archive, it cannot be built on Soapbox. Better to find that out now than three days in.

API REFERENCE

Create a cast

POST/v1/casts
FIELDTYPENOTES
titlestringRequired. Up to 90 characters.
tagsstring[]Optional, up to 5. Leagues, teams as "LEAGUE:Team", or your own strings.
REQUEST
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"]}'
201
{
  "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

GET/v1/casts
200
{ "casts": [ { "id": "c_9f2a...", "title": "...", "shareCode": "...", "maxParticipants": 50, "endsAt": "..." } ] }

Retrieve a cast

GET/v1/casts/{id}
200
{
  "id": "c_9f2a...",
  "title": "Week 1 overreactions",
  "shareCode": "npya5h3xwq",
  "participantCount": 32,
  "maxParticipants": 50,
  "endsAt": "2026-08-23T12:41:17.888Z"
}

End a cast

DELETE/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.

200
{ "ended": true }

Mint a token

POST/v1/casts/{id}/tokens
FIELDTYPENOTES
identitystringRequired. Your id for your user. Opaque to us.
displayNamestringRequired. What the stage shows.
rolestringOptional, defaults to listener.
200
{
  "token": "eyJhbGciOi...",
  "url": "wss://soapbox.livekit.cloud",
  "role": "listener",
  "canPublish": false,
  "expiresAt": "2026-08-23T12:41:17.888Z"
}

Usage

GET/v1/usage

Minutes 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.

200
{
  "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.

402
{
  "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."
  }
}
FIELDTYPENOTES
INSUFFICIENT_MINUTES402Live key, zero balance.
CAST_FULL409Your pool of casts is fully in use.
CAST_NOT_FOUND404Wrong id, or the cast already ended.
UNAUTHENTICATED401Missing or invalid key.
RATE_LIMITED429Back 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.

MCP CONFIG
{
  "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.

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