Guides / Get started / Errors and retries
Errors and retries
Every error has a stable code and costs nothing. Retry 429s and 5xx with backoff; fix the rest.
Error format
Errors return JSON with a code you can switch on, a message and the request ID to quote to support.
Error body
{
"error": {
"code": "rate_limited",
"message": "Over 75 requests per second on this account.",
"retry_after": 1.4,
"request_id": "req_8fK2xQ7mN4"
}
}Error codes
| Status | Code | Meaning | Retry? |
|---|---|---|---|
| 400 | invalid_request | A parameter is missing or malformed. | No. Fix the request. |
| 401 | unauthorized | The key is missing, wrong or revoked. | No. |
| 402 | out_of_credits | Your balance can’t cover this call. | After a top-up. |
| 403 | forbidden | Your plan doesn’t include this endpoint (Growth+ or Enterprise). | No. |
| 404 | not_found | The video, profile or sound doesn’t exist or isn’t visible. | No. |
| 409 | session_expired | A connected session needs to sign in again. | After re-importing. |
| 429 | rate_limited | Over your plan’s requests per second. | Yes, after retry-after. |
| 502 | upstream_error | TikTok returned an error after our retries. | Yes, with backoff. |
| 504 | upstream_timeout | TikTok didn’t answer in time. | Yes, with backoff. |
Retrying safely
Wait for retry-after when it’s present; otherwise back off exponentially with a little jitter.
Pythonretry.py
1import time, random, requests
2
3def call(url, params, key, tries=4):
4 for attempt in range(tries):
5 r = requests.get(url, params=params, headers={"x-api-key": key})
6 if r.status_code not in (429, 502, 504):
7 return r
8 wait = float(r.headers.get("retry-after", 2 ** attempt))
9 time.sleep(wait + random.random()) # failed tries cost nothing
10 return r
Don’t retry 4xx other than 429. They mean the request itself needs to change.