# StellarFirm API errors

> The one error shape every StellarFirm API route uses, the HTTP statuses it comes with, and every error code with what to do about it.

Every failure from a public StellarFirm API route is JSON with the same shape. Branch on `error.code`: it is stable. The `message` and `hint` are for people and may be reworded.

```json
{
  "error": {
    "code": "not_found",
    "message": "There is no API route at /api/nothing-here.",
    "hint": "Read the route list at /openapi.json, or start at /docs/api.",
    "docs": "https://stellarfirm.ai/docs/api/errors"
  }
}
```

| Field | Meaning |
| --- | --- |
| `code` | A stable, machine-readable code. |
| `message` | What went wrong, in one plain sentence. |
| `hint` | What to do next. |
| `docs` | This page. |

Failures are never cached. A `405` also carries an `Allow` header that lists the methods the route accepts.

## Error codes

| Code | Status | What to do |
| --- | --- | --- |
| `not_found` | 404 | The address is not a route. Check the [OpenAPI file](https://stellarfirm.ai/openapi.json). |
| `method_not_allowed` | 405 | Use a method from the `Allow` header. |
| `signed_out` | 401 | Send the account's session token. See [Authentication](/docs/api/authentication). |
| `forbidden` | 403 | The account may not use the route. |
| `rate_limited` | 429 | Wait for the `Retry-After` seconds before trying again. See [Versioning and limits](/docs/api/policy). |
| `invalid_request` | 400 | The request is not valid. Check it against the OpenAPI file. |
| `invalid_token` | 400 | The link or token is not valid. Use the link exactly as sent. |
| `not_configured` | 503 | Sign-in is not set up on this deployment. Try again later. |
| `balance_unavailable` | 503 | The balance could not be read. Try again in a few seconds. |
| `unavailable` | 503 | StellarFirm could not answer. Try again in a few seconds. |
| `upstream_failed` | 502 | A service StellarFirm relies on did not answer. Try again. |
| `too_large` | 413 | The request is too large. Send a smaller one. |
| `try_used_up` | 429 | The visitor used every free prompt of the free trial. The error carries `promptsLeft`. |
| `try_ended` | 503 | The free trial is used up for this month. The error carries `reopensOn`, the day it opens again (UTC). |
| `try_busy` | 429 | A prompt is already running, or too many run at once. Wait for the answer, then try again. A `Retry-After` header says how long when it is the second case. |
| `try_refused` | 403, 503 | The request did not pass the check that a person sent it, or the check could not run. Open the page in a browser. |
| `try_failed` | 502 | The free trial could not answer the prompt. The error says how many prompts are left. |
| `internal_error` | 500 | Something went wrong on our side. Try again. |

Routes that belong to the signed-in app can answer other codes. They keep the same shape. The free trial's errors add fields inside `error` where they help (`reopensOn`, `promptsLeft`).

## Still stuck?

Write to hey@stellarfirm.ai with the `error.code` and the time of the request.

## Related

- [Endpoints](/docs/api/endpoints)
- [Authentication](/docs/api/authentication)

---

Source: https://stellarfirm.ai/docs/api/errors
