Errors
A Jaah API call that fails answers with an HTTP status code of 400 or above and a JSON body. Read the status code first: it says what kind of failure it was. The body says why.
The error body
Almost every error body has one field, detail, a sentence written for the person using the console:
{"detail": "This user has already activated their account."}
Show detail to your user as it is. Do not parse it: its wording can change.
When the request itself does not match what the endpoint declares — a missing field, a wrong type, a
value out of range — the status is 422 and detail is a list, one entry per problem. Each entry names
where the problem is (loc, for example ["body", "name"] or ["query", "limit"]), says what is wrong
(msg) and gives a machine-readable kind (type); an entry may carry more fields:
{
"detail": [
{"loc": ["query", "limit"], "msg": "Input should be less than or equal to 200", "type": "less_than_equal"}
]
}
Some endpoints check a value themselves and answer 422 with a plain sentence instead. So a 422
detail is either a list or a string: handle both.
The access-request hint
When you are refused a project or an agent account of your own organization, the refusal can say how
to get access. The body then carries a request field beside detail:
{
"detail": "You can see this project but not change it — ask for access to it.",
"request": {
"scope": {"type": "project", "id": "7f3c…"},
"role": "project_developer"
}
}
scope.typeisprojectoraccount, andscope.idis that project's or agent account's id.roleis the least role that would allow the call:project_viewer,project_developerorproject_maintainer.
Pass both to Create request to ask for that role. The hint comes with
a 403, when you can see the item but not change it, or with a 404, when you cannot see it at all.
A refusal that offers no request — anything outside your own organization, or something no request can
grant — has no request field.
Status codes
| Status | What it means | What to do |
|---|---|---|
400 Bad Request | The request is well formed but cannot be done as asked, for example a pagination cursor the listing did not issue. | Fix the request; detail says what is wrong. |
403 Forbidden | You may not do this. You may still be able to see the item. | Ask for access; see the hint above. |
404 Not Found | The item does not exist, or you cannot see it. The two are deliberately not told apart. | Check the id; ask for access if the hint is there. |
409 Conflict | The item is not in a state that allows this, for example inviting a user who has already joined, or billing that is not connected yet. | Read detail, change the state, then retry. |
413 Content Too Large | An uploaded file is bigger than the endpoint accepts. | Send a smaller file. |
422 Unprocessable Content | The request does not match what the endpoint declares, or a value is invalid. | Fix the fields named in detail. |
429 Too Many Requests | You reached an endpoint's limit: too many calls, or too much already open. | See Rate limits for what clears it. |
502 Bad Gateway | A service Jaah relies on for this call, such as Jira, answered with an error. | Retry later. |
503 Service Unavailable | A service Jaah relies on for this call is unavailable. | Retry later. Billing endpoints, and Jira endpoints while Jira is limiting Jaah, send a Retry-After header with the seconds to wait. |
Two 503 bodies are common. Billing endpoints answer {"detail": "Billing is temporarily unavailable. Try again in a minute."} with Retry-After: 60 while the payment provider cannot be reached. An
endpoint that opens a stored credential answers {"detail": "the secret-wrapping key is unavailable; try again shortly"} while its encryption key cannot be reached.
An endpoint page lists the status codes that endpoint declares. The codes above can come from any endpoint, so not every page lists them all.