Status. This page is TEST only. See the “Tested in TEST” section below.This guide is written in simple English.
Before you start
- API in TEST:
https://test-api.segmnt.cloud - Playback uses
POST /v1/projects/{projectId}/videos/{videoId}/playback-tokens. - A held video is refused with
409code: video_not_ready. ThedetailisThe video is held for review.for a free hold, andThe video is not ready to play yet.for a flagged or team-held video. - Times are UTC.
1. What the check does
- The encoder writes 1 review frame every 10 seconds to our storage.
- A moderation job reads up to 20 frames and asks the AI provider.
- The job runs on our 15-minute cron. Our team can also run it on demand.
- A flagged video is held. A clean check on a video that waits for a check releases it.
- Every decision is audited: what decided (the check or a person), the decision, the reason and the time.
2. Moderation states
Each video has one moderation state:
Notes:
- The state is for our team. Your API sees the effect: the video
statusbecomesheld, and a playback token is refused (section 3). - A free account’s first videos are
pendingwhile the videostatusmay still beready. Sostatus: readyalone does not mean the video plays. Ask for a playback token to be sure, or wait forvideo.ready.
3. What your app sees when a video is held
-
POST /v1/projects/{projectId}/videos/{videoId}/playback-tokensanswers409and issues no token. Thecodeis alwaysvideo_not_ready; thedetaildepends on the state:Example (a free hold): -
A flagged video, and a video our team holds, gets
status: held, and we send thevideo.heldwebhook (if your endpoint subscribed to it). -
A playback link that was issued before the hold stops working within about
a minute. The CDN answers
403with the headerX-Segmnt-Error: video_unavailable. -
GET /v1/projects/{projectId}/videos/{videoId}still returns the video. Itsstatusisheldfor a check or a team hold; it can bereadyfor a free account’s first videos that still wait for a check.
4. Free accounts: the first videos
- A free account’s first videos are held until checked. The default is 3, and our config allows 0 to 5.
- A paid account’s first video is not held.
- Phone verification is available but not required in this version, so it does not hold or block the first upload. See Phone verification.
- Until the AI check runs, these videos wait for a person in our review queue.
none (playable when
ready).
5. How a held video is released
Our team reviews held videos on an internal page at/admin on the dashboard
host, in the Moderation tab:
- Every Approve and Hold is audited as a human decision, with the reason.
- Our team’s release sends the
video.readywebhook; our team’s hold sendsvideo.held. A clean check that clears a free hold makes the video playable and sends no webhook. - You cannot release a video yourself.
/v1/admin/**is for our team only. If you think a hold is wrong, contact us.
6. The AI provider (our side)
The AI provider costs money, so choosing or using one needs board approval first. Today only the no-coststub provider can be enabled
(MODERATION_PROVIDER=stub). Any other value is ignored, so nothing paid can be
switched on by config alone.
Until a paid provider is approved, the pipeline still works: a free account’s
first videos are held and wait for a person in the review queue, exactly as
“held until checked” requires.
Config (our side):
The state lives in migration
0013_moderation.sql.
Admin API (our team only, under the Admin tag in the API reference):
The admin page
/admin has a Moderation tab that lists this queue and can
Approve or Hold a video. These routes sit behind Cloudflare Access and are not
for customers.
7. Errors
Errors useapplication/problem+json. Use the code field in your code, not
the text.
Tested in TEST
It is TEST only; no paid provider is called. TEST deploys frommain.
The behaviour is proved by our API test suite:
api/src/moderation.test.ts— onlynoneandclearedplay; the free hold counts the account’s videos and is clamped to 0-5; the check flags and holds a video and audits it; a clean check releases a free hold; a second run is skipped; a failed check is retried; onlystubcan be enabled; the scan is a no-op with no provider.api/src/uploads.test.ts— a free account’s first 3 videos arepending(and each hold is audited); the 4th isnone; a paid account’s first video isnone.api/src/playback-tokens.test.ts—409forpendingand forflagged,201forcleared. (The test asserts the status only; thedetaildifference in section 3 comes from the guard order inplayback-tokens.ts.)api/src/admin.test.ts— the review queue listspending/held videos, a release clears the hold and writes the audit row, and the scan route answers.
https://test-api.segmnt.cloud needs a held video and a
verified domain. The API tests above cover the behaviour; we re-run them after
every change.