Getting started

Go from zero to your first authenticated Zentag Partner API request in minutes.

The Zentag Partner API gives you programmatic access to clips, highlights, media,
publishing, and signed webhooks. This guide gets you from zero to your first
authenticated request in a few minutes.

Base URL: https://studio.zentag.ai/api/v1/partner

1. Create a partner app and API key

In Zentag Studio, go to Settings → Partner integrations → Apps & keys:

  1. Click New app and select the scopes you need (e.g. clips:read,
    publish:write).
  2. Open the app and click Generate key.
  3. Copy the secret key (zt_live_sk_...). It is shown once - store it in
    a secrets manager.

2. Make your first request

Authenticate with the Authorization: Bearer header:

curl https://studio.zentag.ai/api/v1/partner/me \
  -H "Authorization: Bearer zt_live_sk_..."

You'll get back your key's scopes:

{
  "object": "api_key_context",
  "environment": "live",
  "scopes": ["clips:read", "publish:write"],
  "publishable_key": "zt_live_pk_..."
}

3. List some clips

curl "https://studio.zentag.ai/api/v1/partner/clips?limit=10" \
  -H "Authorization: Bearer zt_live_sk_..."

4. Generate a clip (HLS export)

curl -X POST "https://studio.zentag.ai/api/v1/partner/clips/generate" \
  -H "Authorization: Bearer zt_live_sk_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"stream_id":"YOUR_STREAM_ID","start_offset_seconds":10,"end_offset_seconds":25,"source":"replay"}'

Subscribe to clip.created / clip.ready / clip.failed webhooks for the outcome.

5. Async clip AI jobs

curl -X POST "https://studio.zentag.ai/api/v1/partner/clips/CLIP_ID/autoflip" \
  -H "Authorization: Bearer zt_live_sk_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"aspect_ratio":"9:16"}'

Keep the returned job id: the resulting clip.ready webhook carries it in
job_id, and GET /jobs/{id} lets you check state if a delivery is missed. The
new rendition lands in the clip's variants, leaving the original untouched.

See Clips AI jobs. Highlight generate (mode: ai |
manual | ai_global) works the same way, with highlight.ready /
highlight.failed.

6. Browse the media library

GET /media exposes clips, highlights and streams under one shape, with the
same filters as the Studio library:

curl "https://studio.zentag.ai/api/v1/partner/media?rating=4,5&media_types=clip&limit=25" \
  -H "Authorization: Bearer zt_live_sk_..."

Pair it with /media/filters/counts to build a filter UI and /media/stats for
totals. See Media library filters.

7. Local smoke check

From zentag-backend_:

PARTNER_KEY=zt_live_sk_... npm run script:partner-smoke

Conventions worth knowing up front

  • Send Idempotency-Key on every POST. Retries then can't duplicate work.
  • Branch on error.code, not the status or message. See
    Error codes.
  • Treat cursors as opaque. Pass next_cursor back verbatim.
  • Prefer webhooks to polling. Polling loops are the usual cause of 429s.
  • Every id here is a Zentag id. Third-party sports-data provider identifiers
    are deliberately not exposed, so don't plan to join against them.

Next steps


Did this page help you?