Story0.API
API v2026-11-01 · TypeScript and Python SDKs

The video API
that shows its work.

Segment, screen and triage footage against your own categories. Every answer comes back as typed JSON with timecodes and evidence, in seconds, from two cents a minute.

GENERATED DEMO CLIP · 0:00.0no_dog_visible

evidence · seen · 0.25–0.50 s

Empty park with trees and benches.

0:00.0 / 0:24.0
dog_visibleno_dog_visibleuncertainperson jogging
partition
extract
screenanimals matchpeople matchbreaking_news no_match
{
  "id": "seg_01m5kst36ks6apse20eyzyatps",
  "object": "segmentation",
  "mode": "partition",
  "duration_seconds": 24,
  "segments": [
    {
      "id": "interval_1",
      "end": 4,
      "label": "no_dog_visible",
      "start": 0,
      "review": {
        "reasons": [],
        "required": false
      },
      "evidence": [
        {
          "id": "ev_1",
          "end": 0.5,
          "kind": "seen",
          "start": 0.25,
          "description": "Empty park with trees and benches."
        },
        {
          "id": "ev_2",
          "end": 2,
          "kind": "seen",
          "start": 1.75,
          "description": "Pathway and trees, no dog."
        }
      ]
    },
    {
      "id": "interval_2",
      "end": 15,
      "label": "dog_visible",
      "start": 4,
      "review": {
        "reasons": [],
        "required": false
      },
      "evidence": [
        {
          "id": "ev_3",
          "end": 4.5,
          "kind": "seen",
          "start": 4.25,
          "description": "Golden retriever walking on the park path."
        },
        {
          "id": "ev_4",
          "end": 8.5,
          "kind": "seen",
          "start": 8.25,
          "description": "Golden retriever walking down a path."
        }
      ]
    },
    {
      "id": "interval_3",
      "end": 24,
      "label": "no_dog_visible",
      "start": 15,
      "review": {
        "reasons": [],
        "required": false
      },
      "evidence": [
        {
          "id": "ev_5",
          "end": 15.5,
          "kind": "seen",
          "start": 15.25,
          "description": "Person walking away on path, no dog."
        },
        {
          "id": "ev_6",
          "end": 18,
          "kind": "seen",
          "start": 17.75,
          "description": "Park path with trees, no dog."
        }
      ]
    }
  ],
  "coverage": {
    "timeline": "complete",
    "modalities": [
      "visual"
    ],
    "sampled_frames": 48,
    "uncertain_seconds": 0,
    "frame_interval_seconds": 0.5
  },
  "boundary_resolution_seconds": 0.5,
  "receipt": {
    "items": [
      {
        "item": "analysis",
        "amount": "0.04",
        "unit_price_per_minute": "0.08"
      },
      {
        "item": "segment",
        "amount": "0.01",
        "unit_price_per_minute": "0.02"
      }
    ],
    "total": "0.05",
    "currency": "USD",
    "price_version": "2026-11-01",
    "billable_seconds": 30
  }
}
REAL API OUTPUT, REPLAYED3.6 s end to end$0.05Run it live →

3.6 s

to segment the 24 s demo clip, end to end

$0.02

per minute to screen

$0.10

per minute to segment

0.5 s

timeline resolution on short clips

The 90-second tour

How a video becomes a decision.

Frames go to a vision model in parallel, every label comes back with evidence, and the answers snap into a timeline you can trust. Animated with the real results from the demo clip above.

How it works

Four steps from file to decision.

One asynchronous contract for every operation: create a job, get a typed result. No pipelines to assemble, no prompts to tune.

1.0

Send video

Upload a file in resumable chunks, or pass a direct link. Up to 20 minutes and 2 GB.

2.0

Ask in your words

Your labels, your categories, your instruction. No fixed taxonomy to learn.

3.0

Get typed results

Intervals and outcomes with timecodes, evidence and review flags, as JSON.

4.0

Wire it in

Long-poll, or a signed job.succeeded webhook. Results draw straight onto a timeline.

For developers

Ten lines from a file to a timeline.

The SDKs upload in resumable chunks, wait with long-polling, retry safely and raise typed errors that say how to recover. Drawing the result is arithmetic: every interval has a start and an end in seconds.

  • Partition covers the whole range: no gaps, no overlaps
  • Each result carries its receipt and retention dates
  • Same request and key? Same job, one charge
import Story0 from "@story0/sdk";

const story0 = new Story0(); // reads STORY0_API_KEY
const asset = await story0.assets.uploadAndWait({ file: "./park-dog-demo.mp4" });

const result = await story0.segments.createAndWait({
  input: {
    asset_id: asset.id
  },
  mode: "partition",
  instruction: "Partition the whole video by whether a dog can be seen.",
  labels: [
    {
      key: "dog_visible",
      description: "At least one dog is visible."
    },
    {
      key: "no_dog_visible",
      description: "No dog is visible."
    }
  ]
});

for (const s of result.segments) console.log(s.start, s.end, s.label);

Built to be trusted

Answers you can check, costs you can predict.

The contract was shaped by media teams who have to stand behind every clip they publish.

Partition and extract

Label every moment with one of your states, or return only the moments you ask for. Brief appearances are kept, never smoothed away.

Uncertainty is an answer

When frames don't show enough, you get uncertain intervals flagged for review, not a confident guess.

Evidence on every label

Each definite interval cites what was seen and when, so a producer can check it in seconds.

Spend you can cap

Quote before you run. Set max_charge per request; work stops before exceeding it. Failed jobs are free.

Safe to retry

Idempotency keys return the original job, never a second charge. The SDKs set them for you.

Test mode

s0_test_ keys return labelled fixtures with the real response shapes and are never billed.

Who it's for

Made for teams that live in footage.

Newsrooms, aggregators, archives and rights teams use the same three operations differently.

Find the usable moments in raw footage before the edit starts.

Producers describe what they need in plain words. Extract returns the matching moments with timecodes and a sentence of evidence each, so an editor jumps straight to them instead of scrubbing an hour of rushes.

segments.createAndWait({
  input: { url: "https://media.example.com/rushes/cam-b.mp4" },
  mode: "extract",
  instruction: "Wide shots of the flooded high street with no people in frame",
  constraints: { min_seconds: 2, max_segments: 20 },
})

Illustrative output

  • 00:41.5 – 00:47.0match

    Wide view of a flooded street, no people visible

  • 03:12.0 – 03:19.5match

    Water covers the road between shopfronts

  • 07:58.5 – 08:02.0match · review

    Partly obscured by a passing van

Examples show the shape of real results; the footage and figures here are illustrative.

Pricing

Pay for minutes, not seats.

Two prices, both per minute of video. Every video bills at least 30 seconds. Credits never expire. Full pricing →

1,000 min
101001k10k100k
30%

Screen everything cheaply, then segment the clips worth a closer look.

Estimated monthly cost

$50.00

Screening · 1,000 min × $0.02
$20.00
Segmentation · 300 min × $0.10
$30.00

Pay as you go from prepaid credits. Your first $10 is free. Volume pricing for more than 50,000 minutes a month: talk to us.

Your first hundred minutes are on us.

Sign up, verify your email and get $10 of credit: enough to segment 100 minutes of video. No card required.