Pagination & idempotency
List endpoints (/channel, /playlist, /search) return up to limit videos per page (1–50, default 5) plus a next_cursor. When next_cursor is non-null, pass it back as cursor to fetch the next page; null means the list is exhausted.
Each page is one successful response and costs 1 credit, with one exception: a page that comes back empty is free. Cursors are opaque tokens; do not parse or construct them, and be prepared for a stored cursor to be rejected as malformed or expired. next_cursor: null is the only terminator.
Polling for new uploads with since_video_id
List endpoints accept since_video_id: the newest video id you have already seen, as a bare id or a YouTube URL. The page is trimmed at that watermark, leaving exactly the videos newer than it, and when the marker is found on the page next_cursor is forced to null because everything past it is already seen.
Combined with the empty-page rule this makes new-uploads polling free: ask for a channel's latest page with since_video_id set to the last video you processed, and every poll costs nothing until something new actually appears. When the marker is not on the page (a burst of uploads, or the video was deleted), the page is returned untrimmed rather than risking dropped videos.
Idempotent retries
Because requests are billed, retry safely by sending an Idempotency-Key header (any unique string, up to 255 chars). The first request runs and is charged; retries with the same key replay the stored response, same body, no extra charge, and carry an Idempotent-Replayed: true header. Replays are kept for 24 hours.
Two caveats:
- Only 2xx responses are replayed. A transient failure (a 5xx, or a 402 you fixed by topping up) is not stored, so retrying the same key runs the request again, which is what you want.
- A replayed transcription request returns the stored
202, not the finished transcript. Poll thejob_idfrom the replayed body (or usecallback_url); see the transcription guide.
409 idempotency_conflict. Reusing a key with a different body, or while the first request with that key is still in flight, returns 409 idempotency_conflict.