---
title: "Start a background job that fetches every transcript of a channel, playlist or video URL"
method: POST
path: "/api/v1/bulk"
---

# Start a background job that fetches every transcript of a channel, playlist or video URL

`POST /api/v1/bulk`

## Request

- Base URL: `https://bulktranscripts.co`
- URL: `https://bulktranscripts.co/api/v1/bulk`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

Returns 202 with a run_id immediately. Listing is free; each transcript newly added to the caller's library costs 1 credit, cache hits and repeats are free, failures are never charged. Up to 1,000 videos per job and 2 jobs per account at a time.

## Request body

- object
  - `url` string, required: Channel (@handle or URL), playlist URL or id, or a single video URL.
  - `max_videos` integer
  - `start_at` integer: 1-based position to start from, newest first.
  - `content` 'videos' | 'shorts' | 'live': Channels only: which tab to read.
  - `language` string

## Response `202`

Job accepted

- BulkJob
  - `run_id` string
  - `status` 'running' | 'completed' | 'stopped' | 'failed'
  - `phase` 'discovering' | 'extracting' | 'finished'
  - `source` object
    - `url` string
    - `type` string, nullable
    - `title` string, nullable
  - `videos_found` integer, nullable: null until the listing has finished.
  - `total` integer
  - `completed` integer
  - `cached` integer
  - `failed` integer
  - `skipped` integer: Videos without captions.
  - `quota` integer: Not attempted for lack of credits.
  - `interrupted` integer
  - `remaining` integer
  - `error` object, nullable
    - `code` string
    - `message` string
  - `check_again_in_seconds` integer: Minimum wait before the next poll; 0 when finished.
  - `billing` Billing: Present on every credited response. When billing is disabled on a self-hosted install only enabled/unlimited are set.
    - `enabled` boolean
    - `unlimited` boolean
    - `kind` 'anon' | 'license' | 'admin'
    - `remaining` integer
    - `used` integer
    - `granted` integer
    - `freeLimit` integer
    - `creditsCharged` integer

## Other responses

- `400`: Bad request (invalid_input, resolution_failed, or empty_source)
- `401`: Unauthorized (missing_api_key, invalid_api_key, or invalid_token)
- `429`: Rate limited (rate_limited; honour the Retry-After header (seconds))
- `503`: Restarting (restarting): the server is deploying, start again in a minute

---

[API](https://skmtc.dev/bulktranscripts/apis/bulktranscripts-api.md) · [All operations](https://skmtc.dev/bulktranscripts/apis/bulktranscripts-api/llms.txt) · [OpenAPI document](https://skmtc.dev/bulktranscripts/apis/bulktranscripts-api/revisions/4949830b74d7?raw)
