# Errors

Canonical: https://monsterapi.co/docs/errors

A refusal comes with a JSON body of one shape, whether the gateway or the platform refused:

```json
{ "status": "error", "code": "not_found", "message": "not found" }
```

`status` is always `error`. `code` names the refusal, and `message` is fixed for each `code`; neither ever carries diagnostic text.
Branch on `code`, and read the body as JSON rather than as text: the order of its fields can differ.
The gateway sends this body even when the platform doesn’t answer at all.

## Refusals at the gateway

The gateway checks every request before the platform sees it. A request the gateway refuses never reaches the platform and isn’t billed.

| Status and code            | Meaning                                                                                                                                                                                                                                                      |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `400` `bad_request`        | The request target, path and query string together, is longer than 8,192 bytes, or the request carries more than 64 headers or more than 16 KiB of them, the target included. Shorten the request.                                                           |
| `401` `unauthorized`       | The key is missing or malformed. Send it exactly as issued.                                                                                                                                                                                                  |
| `402` `payment_required`   | The account’s credits don’t cover the price of the operation. Top the account up.                                                                                                                                                                            |
| `403` `forbidden`          | The key is unknown or revoked. Check whether the key is revoked. Create another key in the customer account.                                                                                                                                                 |
| `404` `not_found`          | No operation has this path. The message is `no such endpoint`, where a platform’s `404` says `not found`. A normalized path that ends with `/` or still holds a percent-encoded character matches no operation. Check the path in the [API reference](https://monsterapi.co/docs/api). |
| `405` `method_not_allowed` | The path doesn’t take this method, and `HEAD` isn’t taken where only `GET` is. `Allow` names the methods it takes. Send the request with one of them. A `405` to `HEAD` has no body.                                                                         |
| `409` `conflict`           | A repeat of a request the gateway already checked differs from the original. Send it again as a new request.                                                                                                                                                 |
| `429` `too_many_requests`  | The account sends faster than its rate limit allows. Try again after `Retry-After`: the whole seconds until the request fits the limit, never less than one. Facebook also returns `429`, with the code `rate_limited`. Tell the two apart by `code`.        |
| `503` `unavailable`        | The gateway couldn’t complete its check, the account is suspended, or the platform didn’t answer. Retry later, after `Retry-After` when it’s sent; if it persists, contact support through the customer account.                                             |

A `400` from the gateway carries the same body as a platform’s `400`. If the request fits the limits above and its path has no `%00`, the platform sent it.

The gateway normalizes the path before its check, and the platform gets the same normalized path. It decodes a percent-encoded letter, digit, `-`, `.`, `_` or `~`, so `/topic/%73occer` reaches the platform, and is billed, as `/topic/soccer`. It resolves `.` and `..` segments and merges `//` into one `/`. Any other percent-encoded character stays encoded, so a path with `%3A` or `%40` gets `404`.

An encoded slash, `%2F`, gets a `307` with no body, and its `Location` is the path with the slash decoded. The `307` isn’t billed; following it sends a new request to that path. An encoded null, `%00`, gets a `400` with an HTML page instead of the JSON body, and isn’t billed either.

One `503` `unavailable` comes after the check rather than from it: the gateway let the request through, and the platform didn’t answer. It carries `Retry-After: 5` and isn’t billed either. Repeat the request after five seconds.

## Refusals of the platform

A platform refuses when the site didn’t give what the operation asks for, or when a value of the request is outside the accepted set.
Where a pause helps, the refusal carries `Retry-After`, in seconds.

| Status and code                                    | Meaning                                                                                                                                                                                                                                                                          |
| -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400` `bad_request`                                | A value on the request line is outside the accepted set.                                                                                                                                                                                                                         |
| `403` `private`                                    | The site shows the object only to visitors with an account.                                                                                                                                                                                                                      |
| `404` `not_found`                                  | The site states that the object is absent or closed to a guest.                                                                                                                                                                                                                  |
| `500` `upstream_shape`                             | The site answered, and the answer couldn’t be read. Waiting doesn’t cure it, so there’s no `Retry-After`.                                                                                                                                                                        |
| `501` `requires_auth`                              | The site shut its door on a guest, or this endpoint isn’t available yet.                                                                                                                                                                                                         |
| `503` `upstream_error`                             | No answer came from the site, or the site answered with a server error. Try again after `Retry-After`, five seconds. If LinkedIn answers with a server error, the request returns `500` `upstream_shape` instead.                                                                |
| `429` or `503` `rate_limited`                      | The site limited how often it may be called, or asked a guest to sign in for a while. Either way, the limit lifts by itself. Try again after `Retry-After`: the wait the site named, or 60 seconds when it named none. Facebook returns `429`, and other platforms return `503`. |
| `503` `no_proxies`, `overloaded`, `upstream_stale` | No address, too many concurrent requests, or stale protocol material. Each may pass later.                                                                                                                                                                                       |

The exact set per operation, the gateway’s refusals included, is in the [API reference](https://monsterapi.co/docs/api).
A platform’s `4xx` is billed, `400` and Facebook’s `429` `rate_limited` included. Its `5xx` isn’t: the operation didn’t deliver. A `405` always comes from the gateway and isn’t billed. See [Pricing](https://monsterapi.co/docs/pricing).
