# Credits, Rate Limits & Errors



The platform meters credits per successful billed response. Failed calls are free. Credits never expire. Most endpoints cost 1 credit; video `mode=full` costs 2. See [Pricing](/pricing) for packs.

Rate limits [#rate-limits]

| Account                | Rate limit         |
| :--------------------- | :----------------- |
| Free                   | 30 RPM (0.5 req/s) |
| Paid (any credit pack) | 300 RPM (5 req/s)  |
| Reserved               | Contact us         |

Customer `Cache-Control: no-cache` is ignored. Cache policy is server-side.

Credit Schedule [#credit-schedule]

| API Feature                  | Endpoint                                                    | Cost                                 |
| :--------------------------- | :---------------------------------------------------------- | :----------------------------------- |
| Standard Transcript          | [`POST /v1/transcripts`](/transcripts/extract)              | <CreditBadge credits={1} />          |
| AI-Native Markdown           | [`POST /v1/transcripts`](/transcripts/extract)              | <CreditBadge credits={1} />          |
| Video metadata (`mode=fast`) | [`GET /v1/videos/{id}`](/videos/get)                        | <CreditBadge credits={1} />          |
| Video metadata (`mode=full`) | [`GET /v1/videos/{id}?mode=full`](/videos/get#returns-full) | <CreditBadge credits={2} />          |
| Playlist Details             | [`GET /v1/playlists/{id}`](/playlists/get)                  | <CreditBadge credits={1} />          |
| Playlist Videos              | [`GET /v1/playlists/{id}/videos`](/playlists/videos)        | <CreditBadge credits={1} />          |
| Channel Profile              | [`GET /v1/channels/{id}`](/channels/get)                    | <CreditBadge credits={1} />          |
| Channel Streams              | [`GET /v1/channels/{id}/streams`](/channels/streams)        | <CreditBadge credits={1} />          |
| Channel Playlists            | [`GET /v1/channels/{id}/playlists`](/channels/playlists)    | <CreditBadge credits={1} />          |
| Search                       | [`GET /v1/search`](/search/query)                           | <CreditBadge credits={1} />          |
| Search Autocomplete          | [`GET /v1/search/suggestions`](/search/suggestions)         | <CreditBadge credits={0} />          |
| Batch Processing             | [`POST /v1/batch`](/batch/run)                              | <CreditBadge credits={1} /> per task |

***

Error Response Format [#error-response-format]

All errors return a standard JSON envelope:

```json
{
  "error": "Transcripts are disabled or unavailable for this video",
  "status": 404
}
```

***

HTTP Status Codes [#http-status-codes]

<Callout type="error" title="400 — Bad Request">
  Missing required parameters (e.g. invalid video ID or empty search query). Check your request payload.
</Callout>

<Callout type="error" title="401 — Unauthorized">
  Missing or invalid API key in `Authorization: Bearer <key>`. Verify your key in the [Dashboard](https://ytapi.dev/app/api-keys).
</Callout>

<Callout type="warn" title="402 — Payment Required">
  Credit balance depleted. Buy a pack in the [billing dashboard](https://ytapi.dev/app/billing). Failed requests are still free.
</Callout>

<Callout type="info" title="404 — Not Found">
  Video does not exist, is private, or captions are unavailable for the requested language.
</Callout>

<Callout type="warn" title="429 — Too Many Requests">
  Rate limit exceeded. Check the `Retry-After` header for seconds until reset. See [Authentication](/authentication) for tier limits.
</Callout>

<Callout type="error" title="500 — Internal Error">
  Upstream extraction error. Credits are **automatically refunded** for failed requests.
</Callout>
