API Reference
Errors
Every error of the Tentary API has the same format. The message tells you what to do.
On this page
Format
Every error comes as JSON with a matching HTTP status:
{
"error": {
"code": "...",
"message": "...",
"request_id": "..."
}
}
codeis a fixed value from the table below. Your code can react to it.messagesays in words what is wrong and what you can do.request_ididentifies the request. Send it to support if you need help.
Two answers have a shorter body: an unexpected server error answers {"error": "server_error", "request_id": "..."}, and a path outside /v1/ answers {"error": "not_found"}.
Error codes
| HTTP | code | Meaning |
|---|---|---|
| 400 | bad_input | A parameter is missing, unknown or wrong. The message names it. |
| 400 | bad_cursor | The cursor is not valid. Start again without a cursor. |
| 400 | bad_image | The file or the URL is not a PNG, JPG, GIF or WebP image. |
| 400 | fetch_failed | Tentary could not copy the file from the URL, for example because the file is too large or the URL does not answer with HTTP 200. The message says why. |
| 400, 404 | legacy_course | The product has an old course. Open it once in the Tentary app first. The message has the link. |
| 400 | not_possible | The action is not possible for this object, for example a refund of an old order. |
| 400, 403 | setup_missing | The account setup is not finished, for example there is no payment provider. See GET /v1/setup. |
| 401 | unauthorized, invalid_token | No key, a wrong key or a revoked key. The answer has the header WWW-Authenticate: Bearer. |
| 403 | scope_missing | The key does not have the permission. Create a key with the permission. |
| 403 | owner_only, blocked, plan_limit, not_possible | Not allowed for this account, or not possible through the API. The message says why. |
| 404 | not_found | No such object in this account, or no such path. |
| 405 | method_not_allowed | Wrong HTTP method. The Allow header names the right one. |
| 409 | busy | The same write is still running, or Tentary still copies this product. Wait a minute, check, then retry. |
| 409 | not_uploaded | The file is not in the storage yet. Send the bytes with PUT to the upload_url first, then finish the upload again. See File uploads. |
| 429 | rate_limited | Too many calls. The Retry-After header gives the seconds to wait. See Rate limits. |
| 429 | busy | Too many calls of this account run at the same time, or Tentary copies another file or image of this account at the moment. See Rate limits. Wait the Retry-After seconds, then retry. |
| 500 | server_error | An error on the Tentary side. Send the request_id to support. |
| 503 | timeout | The call took too long for this account. Ask for a shorter period, one product (product_id) or fewer items per page. |
| 503 | unavailable | The help center search is not available now. Try again later. |
Retry safely
- After a 429, wait the
Retry-Afterseconds. Do not retry at once in a loop: a call refused by the per-minute or per-day limit still costs 1 point. - After a timeout or a 500 on a write, first read the object or the list to see if the write happened. Only then retry.
- Create calls (and
POST /v1/files) have a short protection: the same create with the same values within 60 seconds returns the first result and does not create a second object. This is not a general guarantee. Updates and calls after 60 seconds run again.
Last updated: October 28, 2026