> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs-parschat.parstechai.com/documentation/reference/errors/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs-parschat.parstechai.com/_mcp/server. # Errors > Every status and code we return, and what each one means you should do. > **Warning** > > **Pre-release `v1`, published 2026-09-14.** This page commits to the shape of the API, not to a > date. We will build exactly what is documented here. The shape can still change until > **2026-10-14**; after that, changes follow [Versioning and stability](/documentation/reference/versioning-stability). > > The banner comes off one page at a time as each route goes live. While it is here, build against > the contract and assume the route is not callable yet. ## Shape ```json { "error": { "code": "plan_inactive", "message": "Your plan is not active.", "request_id": "req_8f2Kq9mR" } } ``` **Always log `request_id`.** It is what lets us find your exact request when you contact support. ## Codes | Status | `code` | Meaning | What to do | | ------ | --------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | | `400` | `bad_request` | A parameter is missing, unparseable, or out of range | Fix the query string | | `401` | `invalid_key` | Key missing, wrong, revoked or expired | Check the header; ask sales for a new key | | `403` | `plan_inactive` | Plan lapsed | Not transient. See [When a plan lapses](/documentation/guides/when-a-plan-lapses) | | `403` | `capacity_exhausted` | Robot or channel capacity used up | Delete one, or ask sales to raise it | | `403` | `channel_not_in_plan` | Plan does not include this channel type | Contact sales | | `403` | `attachment_not_in_plan` | Plan does not include this kind of file | Contact sales | | `403` | `forbidden` | The required role is not on your account | Contact your account manager | | `404` | `not_found` | No such resource, **or not yours** | Check the id | | `409` | `conflict` | Duplicate `external_id`, or channel type already present | Use a different value | | `409` | `handshake_pending` | An unexpired Instagram handshake exists | Wait for it to expire, or reuse it | | `410` | `handshake_expired` | The page owner took too long | Start a new one | | `422` | `validation_failed` | Malformed request | Fix the payload | | `422` | `return_url_not_configured` | No return URL configured for you | Contact us before connecting | | `429` | `rate_limited` | Too many requests | Back off, then retry. `details` names your limit. See [Rate limits](/documentation/guides/rate-limits) | | `500` | `internal_error` | Something failed on our side | Retry with backoff; quote `request_id` if it persists | | `503` | `upstream_unavailable` | A channel provider, or our AI service, is down | Retry with backoff | ## `400` and `422` are different failures `400` means the request never got as far as validation: a required parameter is missing, a timestamp will not parse, a `limit` is out of range. `422` means the request was well formed and its contents were rejected, such as a comment rule with no reply and no DM. ```json { "error": { "code": "bad_request", "message": "`from` must be earlier than `to`.", "request_id": "req_8f2Kq9mR", "details": { "from": "2026-09-30T00:00:00Z", "to": "2026-09-01T00:00:00Z" } } } ``` ## One code for every bad key A missing, wrong, revoked or expired key all answer `401 invalid_key`. Telling an expired key from an unknown one would confirm to whoever holds a leaked key that it was once real. Your key's expiry date is on the agreement sales sent you; ask for a new key before it. ## `404`, not `403`, for someone else's resources If you request a resource that exists but belongs to another partner, you receive **`404`, not `403`**. A `403` would confirm the id exists, which is information you should not be able to probe for. ## `details` Some errors carry a `details` object where a number helps you act: ```json { "error": { "code": "capacity_exhausted", "message": "You have reached the maximum number of channels your plan allows.", "request_id": "req_8f2Kq9mR", "details": { "occupied": 10, "requested": 1, "capacity": 10 } } } ``` It is **never** present on `401` or `404`, where extra detail would confirm something you should not learn. ## Which errors are worth retrying | Retry | Do not retry | | --------------------------- | -------------------------------------------------- | | `429` (after backing off) | `400`. The request is malformed | | | `401`. The key will not fix itself | | `500`, `503` (with backoff) | `403`. A plan or role state, not a transient fault | | | `422`. The payload is wrong | | | `409`. The conflict is real | > **Info** > > We never name an internal host or service in an error. If you need to know *why* something > upstream failed, send your `request_id` to your account manager. > Every status and code we return, and what each one means you should do.