Docs
Authentication
The PodRead API is authenticated with personal API tokens. Tokens are self-serve and carry the full permissions of your user account. If you'd rather pay per call without creating an account, see Machine Payments instead.
Quick start
- Sign in at podread.app/login.
- Open Settings → API tokens.
- Click New token. Copy the token - it is shown once and never again.
- Send it as
Authorization: Bearer <token>.
curl https://podread.app/api/v1/episodes \
-H "Authorization: Bearer sk_live_Nk2o8F7XqV9pR3cL-JmQwTdY5bH7aKfNxZgBvEhWnMsPoIuCrA"
Content-Type: application/json is only required for requests with a JSON body (POST, PATCH); GET and DELETE do not need it.
Permissions
A personal API token acts as the user it was created by. Every token can do anything that user can do through the API - create, list, fetch, and delete episodes on their own podcast feeds. Read-only tokens, per-resource scopes (episode:write), and per-token quotas are not supported.
Tokens are also not user-nameable today - the only identifier shown in Settings → API tokens is the 4-character display prefix. If you run more than one integration, create multiple tokens and track which is which on your side.
Token format
Tokens look like:
sk_live_Nk2o8F7XqV9pR3cL-JmQwTdY5bH7aKfNxZgBvEhWnMsPoIuCrA
sk_live_- fixed prefix so tokens are easy to recognize in logs and secret scanners.- The remaining 43 characters are 256 bits of url-safe base64 randomness (no padding,
-/_alphabet). - The plain token is shown once at creation and cannot be recovered.
Using a token
Send the token in the Authorization header of every request to /api/v1/*:
curl -X POST https://podread.app/api/v1/episodes \
-H "Authorization: Bearer sk_live_…" \
-H "Content-Type: application/json" \
-d '{"source_type":"url","url":"https://www.worksinprogress.news/p/the-secret-behind-japans-railways"}'
See Episodes for every endpoint's request and response shape.
Secret hygiene
Treat personal API tokens like passwords. Load them from environment variables or a secret manager. Never commit them to source control, never paste them in client-side JavaScript, never ship them in a browser extension you don't control end-to-end.
Rotation and revocation
Tokens do not expire automatically. Revoke a token any time at Settings → API tokens - revocation is immediate; the next request using that token gets a 401 Unauthorized. Rotating a token is three steps: create a new token, swap it into your client, revoke the old one.
Rate limits
The only per-user limit today is on episode creation: 20 episodes per rolling hour. Reads (GET) are not rate-limited. Per-token quotas are not supported.
Over-limit responses return 429 Too Many Requests with a JSON error body. Retry-After and X-RateLimit-* headers are not emitted yet - back off for ~60 seconds and retry.
Error responses
Every error response is JSON with one error object. It holds a type that follows the status, a stable code to match on, a message for a person, and a param when one request field caused the error. Some errors add fields inside the object (402 on POST /api/v1/episodes adds upgrade_url and credits_remaining); each endpoint's page lists them.
{
"error": {
"type": "invalid_request_error",
"code": "invalid_voice",
"message": "voice must be an id from GET /api/v1/voices.",
"param": "voice"
}
}
-
400 / 422
Malformed request or invalid parameters
{"error":{"type":"invalid_request_error","code":"…","message":"…","param":"…"}} -
401
Missing, malformed, or revoked token
{"error":{"type":"authentication_error","code":"invalid_token","message":"Unauthorized"}} -
402
Authenticated but out of episode credits (POST only). Pointer to a human billing page.
{"error":{"type":"payment_error","code":"insufficient_credits","message":"Payment required","upgrade_url":"…"}} -
404
Resource does not exist, or exists but is owned by another user (existence is not leaked)
{"error":{"type":"invalid_request_error","code":"resource_missing","message":"…","param":"id"}} -
429
Over the 20/hour episode creation limit
{"error":{"type":"rate_limit_error","code":"rate_limited","message":"You've reached your hourly episode limit"}} -
5xx
Server error; retry with exponential backoff
{"error":{"type":"api_error","code":"…","message":"…"}}
The 402 here is not an MPP challenge - it's a pointer to the /billing upgrade page meant for humans. If you want to pay per request with no account, use the Machine Payments endpoints instead.