← Back to the blog

Create an app and mint an API token

Your first two API calls: register an app and issue a scoped token. A tour of the REST API envelope and the auth header every request needs.

2 min read
Leer en español

Everything is an API call

The StreamHub dashboard is just a client of the same REST API you can use directly. Every endpoint lives under /api/v1, takes an Authorization: Bearer <token> header, and returns a consistent envelope:

{ "data": <payload>, "error": null }

Errors return the proper HTTP status plus a NestJS error body. Full interactive docs are at /api/v1/docs (Swagger) and /api/v1/openapi.json.

Step 1 — set up your shell

The installer seeded a global sk_ token. Grab it and point at your server:

export BASE="https://media.example.com/api/v1"
export TOKEN="sk_...."     # the seeded global token

Step 2 — create an app

curl -s -X POST $BASE/apps -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"name":"live","displayName":"Live Channel"}'

That registers the app, creates its per-app database, and sets up its room prefix. The app is now the scope for streams, recordings, plugins and its own tokens.

Step 3 — mint a scoped token

A global token can do anything; for day-to-day integration you want a token scoped to one app, so a leak is contained:

curl -s -X POST $BASE/tokens -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"name":"live-ci","app":"live"}'

The response contains the new sk_ value once — store it in your secret manager immediately. You can list and revoke tokens later via GET /tokens and DELETE /tokens/{id}.

Step 4 — confirm it works

curl -s $BASE/apps/live -H "Authorization: Bearer $LIVE_TOKEN"

You should get the app's config back in the data envelope.

Understanding permissions

Behind the scenes, every route declares a Casbin permission like app:create or ingress:create. A global token or superadmin bypasses tenant scoping; an app-scoped token is confined to that app. If a call returns 403, the token is authenticated but lacks the permission — check the endpoint's required resource:action in the API reference.

With an app and a token in hand, you are ready to ingest your first stream.