Developer docs

REST API

Plain JSON over HTTPS for everything the MCP server can do. Every route below is also an MCP tool of the same name: one implementation, one scope map, one rate limit, reachable from curl, a cron job or an automation platform.

Conventions

ItemRule
Base URLhttps://app.streamagent.io/api/v1
AuthenticationAuthorization: Bearer sa_live_… with an API key, or a sat_ assistant token. See Authentication.
ContentJSON in, JSON out. Send Content-Type: application/json on writes.
IdsUUID strings, exactly as the list routes return them. Never construct one.
VersioningThe version is in the path. This version only gains fields and routes; a breaking change would be a new path.
Rate limitsThe same per-credential ceilings as the MCP server, with Retry-After on 429.
Lead privacyLead fields are masked exactly as on the MCP server when the workspace keeps masking on.
curl "https://app.streamagent.io/api/v1/leads?status=new&limit=20" \
  -H "Authorization: Bearer sa_live_…"
The newest twenty leads still marked new.
curl -X POST https://app.streamagent.io/api/v1/routes \
  -H "Authorization: Bearer sa_live_…" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: onboarding-route-2026-09" \
  -d '{"entry_video":"Welcome tour","name":"Onboarding"}'
Create a route from a video title, safely retryable.

Pagination

List routes take limit (default 50, at most 100) and cursor. The response carries a pagination block with total, limit, has_more and next_cursor; pass next_cursor back as cursor until it is null. Cursors are opaque and only valid for the same route and filters.

{
  "leads": [ … ],
  "pagination": { "total": 143, "limit": 50, "has_more": true, "next_cursor": "eyJvIjo1MH0" },
  "pii_redacted": true
}
A first page of leads.

Idempotent writes

Send an Idempotency-Key header (any string up to 255 characters, unique per operation) on a write and the first response is stored for 24 hours. A retry with the same key and the same request gets that response back with Idempotency-Replayed: true; the same key with a different request is a 409 conflict. Keys are private to the credential that sent them.

Errors

Every non-success response is { "error": { "code", "message", "details"? } }. The message is written to be shown to a developer and lists every problem it found, so one fix reaches a correct call.

CodeHTTPMeaning
unauthorized401No credential, or one that is malformed, revoked or expired. The response carries a WWW-Authenticate header.
forbidden403The credential is valid but lacks the scope the route needs; details.required_scope names it.
plan_limit403The workspace plan does not include this capability; details.entitlement names it.
not_found404No route at that path, or the object id is not in this workspace.
method_not_allowed405The path exists but not for that verb. The Allow header lists the verbs that work.
conflict409An Idempotency-Key was reused with a different request, or the first request with it is still running.
invalid_request400A parameter or body field is missing, unknown or the wrong shape; the message lists every problem at once.
rate_limited429Over the per-credential ceiling. Retry after the number of seconds in Retry-After.
internal500Something failed on our side. The details are logged; retry once, then contact support.
  • Retry 429 after the header value and 500 once; never retry 400, 401, 403 or 409 unchanged.
  • A 404 on an id means the object is not in this workspace, which is also what a wrong workspace key looks like.

Machine-readable contract

The full OpenAPI document, generated from the same source as this page, is at /api/v1/openapi.json. Point a client generator or an assistant at it.

Routes

Grouped as on the MCP server page. Required parameters are marked with *. Path segments in braces are ids from the list routes; GET routes take parameters in the query string, other verbs in a JSON body.

Outcomes in one call

Method and pathWhat it doesScopeQuery or body fields
GET /leads/call-listYour hottest open leads, why each one matters now, and the next step for each.leads:readlimit
GET /resultsPlays to leads to calls to revenue for a window, against the one before.outcomes:readwindow
POST /videos/{video_id}/route-planPlan a lead-capturing StreamRoute from one video, saved as a suggestion to approve.routes:write—
POST /rotations/planDescribe who goes where in one sentence; get the lanes, saved as a suggestion to approve.routes:writebrief*

Suggestions

Method and pathWhat it doesScopeBody fields
POST /proposalsSave a change as a suggestion card you approve in the app; nothing changes until you click Apply.workspace:readaction*, params*, rationale
POST /proposals/plansSave two to eight related changes as one card; Apply runs them in order and Undo reverses all.workspace:readtitle*, steps*, rationale
GET /proposals/actionsThe changes a suggestion can carry, with their params.workspace:read—

Videos

Method and pathWhat it doesScopeQuery or body fields
GET /videosBrowse your library with status and view counts.videos:readstatus, folder_id, tags, search, sort, limit, cursor
GET /videos/{video_id}Full detail and stats for one video.videos:read—
GET /embedThe code or site-builder prompt that puts a video, route or rotation on a website.videos:readvideo_id, route_id, rotation_id
POST /videos/compareRank videos on real performance, not raw views.videos:readvideo_ids*
GET /videos/{video_id}/key-momentsThe notable moments detected in a video.videos:read—
PATCH /videos/{video_id}Rename, describe, or retag a video (write); archiving needs approval unless granted.videos:writetitle, description, tags, archived
POST /videosPull a video file in from a public link; it processes in the background (write).videos:writesource_url*, title, folder_id, tags
POST /videos/uploadsCreate the video and get a one-time URL to send the file to (write).videos:writefile_name*, file_size*, title, folder_id, tags
POST /videos/generateRender a clip with a connected AI video tool and add it to the library (write).videos:writeprovider*, prompt, script, model, avatar_id, voice_id, aspect_ratio, image_url, duration, folder_id
GET /videos/generations/{generation_id}Where a generation is: rendering, added to the library, or why it stopped.videos:read—
GET /videos/generation-optionsWhich AI video tools are connected and the models, avatars and voices they offer.videos:readprovider
POST /studio/projects/{project_id}/editClean up, cut, arrange clips, set sound, music, text and captions (write); needs approval unless granted.videos:writedoc_version*, ops*, rationale
GET /commentsRecent comments on your videos, and which ones are hidden.videos:readvideo_id, limit
GET /videos/{video_id}/questionsWhat viewers asked a video, answered or not.videos:readonly_unanswered
GET /shortsSuggested and made Shorts, with this month’s allowance.videos:readvideo_id
GET /foldersYour video and route folders.videos:readkind
GET /studio/projectsYour StreamAgent Studio projects and their takes.videos:read—
GET /studio/projects/{project_id}One project’s timeline, sound, music, scenes, cameras and what Clean up would cut.videos:read—

Analytics

Method and pathWhat it doesScopeQuery parameters
GET /videos/{video_id}/analyticsViews, engagement, and conversion for a video.analytics:readfrom_date, to_date
GET /videos/{video_id}/retentionWhere viewers stay and where they drop off.analytics:read—
GET /changesWhat changed across your workspace lately.analytics:readdays
GET /analytics/summaryThe workspace numbers for a range, each with its prior-period change.analytics:readrange
GET /analytics/dailyA per-day series between two dates.analytics:readfrom, to
GET /routes/{route_id}/performanceHow many reach each step of a route, where it loses people, and its leads.analytics:read—
GET /goalsThis month’s targets for leads, views and depth, with the pace.analytics:read—
GET /meta/adsSpend, leads and cost per lead for ads launched from StreamAgent.analytics:readdays
GET /pixelsConversions sent to each ad pixel, and any that failed.analytics:readdays
GET /trafficWhere viewers come from: sources, devices and countries.analytics:readdays
GET /ai-searchWhether AI assistants cite your videos, by question and engine.analytics:readdays

Outcomes

Method and pathWhat it doesScopeQuery parameters
GET /outcomesThe revenue ledger: purchases, booked calls and refunds with value.outcomes:readfrom_date, to_date, kind, status, lead_id, video_id, limit, cursor
GET /outcomes/sourcesWhich revenue sources are connected and when each last reported.outcomes:read—

Provisioning

Method and pathWhat it doesScopeQuery or body fields
GET /webhook-endpointsEvery endpoint with its events and whether it is active.workspace:manage—
POST /webhook-endpointsRegister a URL and get its signing secret once (write).workspace:managename*, url*, events, include_clients
PATCH /webhook-endpoints/{endpoint_id}Rename, re-point, change events, pause or rotate the secret (write).workspace:managename, url, events, active, include_clients, rotate_secret
DELETE /webhook-endpoints/{endpoint_id}Remove an endpoint and its history (write).workspace:manage—
POST /webhook-endpoints/{endpoint_id}/testDeliver the synthetic test event and report the result (write).workspace:manage—
GET /webhook-endpoints/{endpoint_id}/deliveriesWhat was sent to an endpoint and how it went.workspace:managestatus, limit, cursor
GET /api-keysActive keys by name, prefix and tier.workspace:manage—
POST /api-keysMint a key of equal or lower access and receive it once (write).workspace:managename*, scope, agency_wide
DELETE /api-keys/{key_id}Stop a key immediately (write).workspace:manage—

Leads

Method and pathWhat it doesScopeQuery or body fields
GET /leadsYour captured leads, most engaged first.leads:readvideo_id, status, source, from_date, to_date, search, sort, limit, cursor
GET /leads/{lead_id}One lead with full activity history.leads:read—
GET /leads/{lead_id}/journeyA lead’s complete timeline across your videos.leads:read—
PATCH /leads/{lead_id}Set status, tags, or append a note (write).leads:writestatus, tags, notes, email, name, phone
PUT /leadsAdd a lead by email, or enrich the one that already exists (write).leads:writeemail*, first_name, last_name, name, phone, status, tags, notes, custom_fields, source
GET /leads/exportA private, hour-long link to the Leads page CSV, when lead details are not masked.leads:readstatus, video_id, search, heat, date_from, date_to, booked, rewatcher

Transcripts

Method and pathWhat it doesScopeQuery parameters
GET /transcripts/searchFind where a topic is spoken across your library.transcripts:readq*, video_id, limit
GET /videos/{video_id}/transcriptThe full transcript for a video.transcripts:readoffset, max_chars

Routes

Method and pathWhat it doesScopeQuery or body fields
GET /routesYour interactive routes.routes:readvideo_id, status, limit, cursor
GET /routes/{route_id}The structure of one route.routes:read—
PATCH /routes/{route_id}Rename a route (write); pausing or archiving needs approval unless granted.routes:writename, status, available_from, available_until, description
POST /routesStart a new interactive route (write).routes:writeentry_video*, name
POST /routes/{route_id}/stepsAdd a video step to a route (write).routes:writevideo*
POST /routes/{route_id}/branchesWire the choices between steps (write).routes:writequestion, branches*
GET /landing-pagesYour landing pages with status, views and leads.routes:read—
GET /landing-pages/{landing_page_id}Everything on one landing page, section by section.routes:read—
GET /rotationsEach rotation with its lanes, live tests and how they are doing.routes:readinclude_archived

Scheduling

Method and pathWhat it doesScopeQuery or body fields
GET /bookingsUpcoming and past calls booked through your videos.leads:readscope, limit, cursor
GET /scheduling/overviewYour calendar shape at a glance.workspace:read—
GET /scheduling/availabilityWhy a slot is (or isn’t) offered.workspace:readevent_type
POST /bookingsBook a call and capture the lead (write); needs approval unless granted.leads:writeevent_type_id*, start*, invitee_email*, invitee_name, invitee_phone, invitee_timezone
GET /scheduling/slotsThe times an event type actually offers next.workspace:readevent_type, days

Main page & collections

Method and pathWhat it doesScopeBody fields
GET /channelWhat your main page shows, and every collection.workspace:read—
GET /collections/{collection_id}One collection and what’s in it.workspace:read—
POST /collectionsA new public page of chosen videos (write); needs approval unless granted.channel:writetitle*, dek, slug, fill_rule, rule_folder_id, rule_tag, listed_on_home, items, video_id, route_id
PATCH /collections/{collection_id}Title, intro, address and how it fills (write); needs approval unless granted.channel:writetitle, dek, slug, fill_rule, rule_folder_id, rule_tag, listed_on_home
DELETE /collections/{collection_id}Take a collection’s page down (write); needs approval unless granted.channel:write—
POST /collections/{collection_id}/itemsPut videos and routes in a collection, or take them out (write); needs approval unless granted.channel:writeitems*, in*
PUT /collections/{collection_id}/featuredChoose what leads a collection’s page (write); needs approval unless granted.channel:writevideo_id, route_id
PATCH /channelWhat your main page shows and how it reads (write); needs approval unless granted.channel:writecollection_id, headline, dek, tagline, cta_route_id, cta_label, website_url, enabled

Workspace

Method and pathWhat it doesScopeQuery or body fields
GET /workspacePlan, usage, and the guidance you wrote for assistants.workspace:read—
GET /workspacesThe workspaces this credential can act on; an agency-wide key lists every client.workspace:read—
GET /tagsThe tags in use across your content.workspace:read—
POST /tags/renameRename or merge a tag everywhere it’s used (write); needs approval unless granted.videos:writetag*, new_tag*, applies_to
GET /searchOne search across videos, transcripts, routes, and leads.workspace:readq*
GET /teamWho is on the team, their roles, and seats left.workspace:read—
GET /domainsEach connected domain and whether it is live.workspace:read—
GET /workspace/settingsName, caption language, discoverability, AI access and brand voice.workspace:read—
GET /integrationsWhich apps are connected and whether each is healthy.workspace:readprovider
GET /metaWhether Meta is connected, the ad account and pixel, and audience sync.workspace:read—
GET /leads/routingThe rules that hand new leads to teammates, in the order they run, with the fields a rule can use.leads:read—
GET /playbooksAn agency’s saved playbooks and the client workspaces they can be deployed into.workspace:read—
GET /routes/{route_id}/partnersA route’s partners with their links and ledger: leads, sales, revenue and owed.routes:readdays
GET /meta/promote/optionsWhat a Meta ad can use: Pages, audiences, currency and budget bounds, and the ads already running for a video or route.workspace:readsource_type, source_id
GET /agent/usageThis month’s agent messages: used, left, and when they reset.workspace:read—
GET /agency/overviewEvery client workspace with its numbers, health flags and waiting suggestions.analytics:readwindow
POST /domains/{domain_id}/checkCheck a custom domain’s DNS now; it goes live when the record is right.workspace:read—

Not in this version

Deleting a video or a lead stays a signed-in action; archive is the reversible path and is on PATCH /videos/{video_id}.