Skip to content

Quickstart ​

Create a project, mint a publish token, and send your first broadcast through the MoQ CDN.

Set up with the CLI ​

With Node 22 or later, the CLI handles login and setup. Each create uses a key you can reuse after an uncertain outcome:

sh
npx @moq/pro login
npx @moq/pro projects create --idempotency-key quickstart-cli-project-1 --json
# Set PID to the returned id.
npx @moq/pro keys create "$PID" --idempotency-key quickstart-cli-key-1 --json
# Set KID to the returned id, and EXPIRES to an RFC 3339 time one hour ahead.
npx @moq/pro token publish "$PID" "$KID" hello.hang --expires "$EXPIRES" \
  --idempotency-key "quickstart-cli-mint-$EXPIRES" --json

Use the returned URL as PUBLISH_URL in the upstream publisher command below. The CLI prints JSON automatically when redirected; --json makes that explicit. Its command reference is generated from --help.

Create an account token ​

Sign in to MoQ Pro, then open API Tokens. Create a write token with access to all projects. Copy it when it appears: the dashboard only shows the secret once.

An account token manages CDN resources. A signing key mints the separate media token that publishers and viewers use to connect to a relay. Keep both kinds of credential private.

The commands below need a POSIX shell, curl, and jq. Set your account token without putting it in shell history:

sh
read -r MOQ_API_TOKEN
export MOQ_API_TOKEN
API=https://api.moq.pro/v1

Create a project ​

sh
PROJECT=$(curl --fail-with-body --silent --show-error "$API/projects" \
  -H "Authorization: Bearer $MOQ_API_TOKEN" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: "quickstart-project-1"' \
  --data '{}')
PID=$(printf '%s' "$PROJECT" | jq -er '.id')
printf '%s\n' "$PID"

Use the returned immutable id in API paths and relay URLs. You can give a project a vanity name later. Accounts have a cap on owned projects; if you reach it, ask support for more.

For subsequent independent runs, choose new idempotency keys. The API reference describes create replay, errors, and pagination from the same specification used by the API.

Create a signing key ​

sh
KEY=$(curl --fail-with-body --silent --show-error "$API/projects/$PID/keys" \
  -H "Authorization: Bearer $MOQ_API_TOKEN" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: "quickstart-key-1"' \
  --data '{"algorithm":"HS256","label":"Quickstart"}')
KID=$(printf '%s' "$KEY" | jq -er '.id')

The key stays in the API so you can mint media tokens without downloading private signing material.

Mint a publish URL ​

Grant permission to publish the broadcast named hello.hang for one hour. The .hang suffix names the media format, so the dashboard can preview it:

sh
EXPIRES=$(($(date +%s) + 3600))
BODY=$(jq -nc --arg root "$PID" --argjson exp "$EXPIRES" \
  '{root: $root, publish: ["hello.hang"], exp: ($exp | todate)}')
TOKEN=$(curl --fail-with-body --silent --show-error "$API/projects/$PID/keys/$KID/token" \
  -H "Authorization: Bearer $MOQ_API_TOKEN" \
  -H 'Content-Type: application/json' \
  -H "Idempotency-Key: \"quickstart-mint-$EXPIRES\"" \
  --data "$BODY" | jq -er '.token')
PUBLISH_URL="https://cdn.moq.pro/$PID/hello.hang?jwt=$TOKEN"

The account token is used only with the management API. The jwt in the publish URL is the scoped media token; anyone with that URL can publish hello.hang until it expires. The idempotency key follows the expiry, so re-running the block mints a fresh token.

Publish with the upstream CLI ​

Install the upstream moq CLI and FFmpeg. With Rust installed, cargo install moq-cli installs the moq command.

sh
ffmpeg -re -f lavfi -i testsrc=size=1280x720:rate=30 \
  -c:v libx264 -preset veryfast -tune zerolatency -g 60 -pix_fmt yuv420p \
  -f mpegts - | moq --connect "$PUBLISH_URL" import ts

While it runs, open your project in the dashboard. The Broadcasts page shows hello.hang with a live preview and its traffic. Stop FFmpeg with Ctrl-C when finished.

Use the upstream docs for media formats, clients, and protocol details. The management API reference covers CDN resources.