Changelog
Notable changes to the Zentag Partner API.
All notable changes to the Zentag Partner API are documented here. The API is
versioned in the URL path (/api/v1/partner). Backwards-incompatible changes
ship under a new major version; additive changes may ship within v1.
v1.2.1 - 2026-09-01
Added
GET /matches— search fixtures for your organization. Returns
{ object: "match", match_id, name, team1_id, team2_id }. Passcompetition_id
(fromGET /competitions) to search that competition's season schedule; optional
search/qfilters by name or id; optionalmatch_idfetches one fixture
exactly. Useteam1_id/team2_idandmatch_idonPOST /streams.match_idon streams — accepted onPOST /streamsandPATCH /streams/{id},
and returned on stream reads. Same fixture id Studio uses when creating a video
feed from a schedule match.
v1.2.0 - 2026-08-24
Stream ingest and templates, expanded media and highlight filtering, webhook
correlation, and a closed allowlist for identifiers.
⚠️ Breaking
- External storage push records are now snake_case.
GET /clips/{id}/external-storage-status
and thepushobject insidePOST /clips/{id}/push-external-storageand the
bulk variant previously returned camelCase keys (bucketId,videoObjectKey,
pushedAt, …), inconsistent with the rest of the API. They now return
bucket_id,video_object_key,pushed_atand so on, plusreplaced_at. - Player tag
metadatais a closed allowlist. It now contains only
player_name,short_name,position,jersey_number,nationalityand
roster_memberships(themselves reduced tojersey_numberandposition).
Upstream sports-data-provider identifiers that previously leaked through this
field are removed and will not return. The same applies to the JSON sidecar
written when a clip is pushed to external storage. /media/statsand/media/filters/countsreturn a fixed, documented shape.
Both previously forwarded the internal Studio response wholesale. Buckets are
now explicitly named and snake_case, and facet buckets appear only when
computed. Inmatch_index, the provider match id is replaced by an opaque,
non-reversiblematch_ref.
Added
POST /streamscan run the processing pipeline. Supplying the new optional
video_template_idmakes Zentag provision ingest and analyse the feed, along
withvideo_type,match_date,scheduled_start_at,scheduled_end_at,
scheduled_duration_hoursandtimezone. Omitting it keeps the existing
metadata-only behaviour, so no existing integration changes.GET /stream-templateslists the templates your organization can pass as
video_template_id, with input type, resolution, frame rate, audio tracks and
whether AI analysis runs.GET /streams/{id}/ingestreturns push ingest coordinates forRTMP_PUSHand
SRT_PUSHstreams. Scopedstreams:writerather thanstreams:read, because
the response includes a stream key.Streamgainsstatus,video_type,aspect_ratio,match_date,
clips_count,highlights_count,tags,scheduled_start_at,
scheduled_end_at,timezoneandupdated_at. Preferstatusoveris_live
when tracking progress:is_liveisfalsefor pending, completed, failed,
cancelled, delayed and scheduled alike.GET /streamsgainsstatus,is_live,video_type,competition_id,
search,created_after,created_before,match_date_after,
match_date_beforeandsort_by.- Webhook event
stream.created, emitted for streams created through the API and
in Zentag Studio, so an integration can pick up streams it did not create. - New guide: Streams.
GET /clips/{id}/jobsandGET /jobs/{id}to reconcile async job state after
a missed webhook delivery, without re-running the render.- Webhook payloads carry
job_idandidempotency_key, correlating a delivery
with the request that started the work. Both arenullfor events originating
in the Studio UI. Clip.variants[](aspect ratio, video url, thumbnail, status) so a
clip.readyevent shows what was produced.Highlightgainscategory,clip_ids,rating,tags,preview_url,
thumbnail_url,updated_atandcompleted_at.GET /highlightsgainscategory,rating,is_ai_created,duration
buckets,start_date,end_dateandsort_by.GET /mediagains the full filter vocabulary of the Zentag Studio library:
hierarchy filters and the facet controlscounts_bundle,
include_match_index,facet_page_size,facet_pageandfacet_load_more.MediaItemgainsdownload_status,platform,players,actions,
venue,season,match_day,duration_label,score_label,progress
andvariants.- New guide: Media library filters. Webhooks expands into a per-event
reference with explicit ordering and deduplication guarantees.
Fixed
GET /mediapagination was stuck:next_cursordid not advance, so every
page returned the first page.GET /media?stream_id=filtered against the stream title facet instead of
scoping to the stream. It now scopes correctly.- Clip lifecycle events were missing in several paths: AI scene creation,
saveClipAsNew, editor render completion, and the AI trim webhook's
completion and failure branches. All now emit. stream.startedwas emitted byPOST /streams, which only registers
metadata. It now fires when the stream actually goes live.highlight.readywas emitted when an AI job was accepted, not when the reel
finished. The premature event is gone; the real one fires on completion.clip.readyfor crop jobs fired on acceptance rather than on completion.stream.endedcould be emitted twice for an already-ended stream.- Webhook retry backoff only covered 5 of the 6 attempts; the last retry reused
the previous delay. - Webhook fan-out is now scoped by partner app, so an app only receives events
for endpoints it registered. - Deleted streams were still reachable.
GET /streams,GET /streams/{id},
the nested clip and highlight lists,PATCH /streams/{id}and
POST /streams/{id}/enddid not exclude deleted streams, and a deleted stream
could still be named as the target of a new clip or highlight. All now treat a
deleted stream as absent. team1_id,team2_idandcompetition_idwere accepted on write but not
returned on read. They now round-trip.
Documentation
- Spec bumped to
1.2.0. All 13 untyped2xxresponses now have concrete
schemas, the two generic placeholder schemas are gone,401/403/429are
attached to every operation and409to every idempotentPOST, and all 55
operations that lacked a description have one. Idempotent-Replayedis documented as a response header on idempotent POSTs./menow correctly advertisesenvironmentasliveortest.- Sidebar navigation is fixed: every guide now resolves to a real category
instead of rendering a placeholder.
v1.1.0 - 2026-07-17
Clips, highlights, media, streams and catalog write access.
Added
- Clips:
PATCH/DELETE, richer list filters, asyncautoflip/reframe/crop(202). - Highlights: create / update / delete, real
POST /highlights/generate(manual|ai|ai_global), progress GET. - Media: library filters,
/media/stats,/media/filters/counts,GET /media/{id}. - Streams:
streams:read/streams:write, create / update / end (reads still acceptcatalog:read). - Catalog write: competitions, teams, players, tags (
catalog:write). - Storage: bulk push + external-storage status.
- Webhooks:
PATCH /webhook-endpoints/{id}.
Changed
POST /highlights/generateno longer returns501; it queues a real job.
v1.0.1 - 2026-07-17
Audit hardening pass.
Fixed
POST /clips/generatenow creates an HLS clip job with a trackableclip_id.POST /publishwithclip_idhydrates media from the clip (optionalsocial_profile_id).GET /media/{id}/signed-urlsreportssigned+expires_at(signed when GCS key available).clip.createdwebhook is emitted when clips are created.- Key scopes are intersected with parent app scopes; partner webhooks are app-scoped; deleting an app removes its webhooks.
Added
- Nested
GET /streams/{id}/clipsandGET /streams/{id}/highlights. - Catalog get-by-id: competitions, teams, players, tags.
- Partner webhook
POST .../testandPOST .../deliveries/{id}/replay. - Error code
not_implemented(501).
Changed
POST /highlights/generatereturns501 not_implemented. It queues real work as of v1.1.0.
v1.0.0 - 2026-07-01
Initial public release of the Zentag Partner API.
Added
- Authentication: API key pairs (
zt_live_pk/sk_...) with scopes,
hashed-at-rest secrets, rotation with grace window, and revocation. - Clips:
GET /clips,GET /clips/{id},GET /clips/{id}/export-json,
POST /clips/generate. - Highlights:
GET /highlights,GET /highlights/{id},
POST /highlights/generate. - Media:
GET /media,GET /media/{id}/signed-urls. - Publishing:
POST /publish,GET /publish/history,GET /publish/{id}. - Storage:
POST /clips/{id}/push-external-storage,GET /storage/buckets. - Catalog: competitions, teams, players, tags, streams.
- Webhooks: endpoint management, signed deliveries (
clip.ready,
highlight.ready,publish.*,stream.*), delivery log, replay, and test events. - Platform: cursor pagination, per-key rate limiting with
X-RateLimit-*
headers,Idempotency-Keysupport, and a typed error envelope.
Updated about 2 months ago
Did this page help you?
