Errors
The RFC 7807 problem+json error format, validation error details, and status codes.
Errors are returned as RFC 7807
application/problem+json documents. The response Content-Type is
application/problem+json and the body always includes at least type,
title, and status.
Problem shape
{
"type": "about:blank",
"title": "Invalid query parameters",
"status": 400,
"detail": "limit: Expected number, received string"
}| Field | Type | Description |
|---|---|---|
type | string | A URI reference identifying the problem type. |
title | string | A short, human-readable summary of the problem. |
status | integer | The HTTP status code. |
detail | string | A human-readable explanation specific to this occurrence. |
errors | array | Per-field validation errors, when applicable (see below). |
Validation errors
When a request fails validation, the problem includes an errors array — one
entry per offending field:
{
"type": "about:blank",
"title": "Invalid query parameters",
"status": 400,
"detail": "limit: Expected number, received string; country: Too many items",
"errors": [
{ "field": "limit", "message": "Expected number, received string" },
{ "field": "country", "message": "Too many items" }
]
}Each entry has a field (the offending field path) and a message (what was
wrong with it).
Full-text search errors
These apply to the full-text q of
Search jobs and
Count jobs only — the q of
GET /locations/search is a plain
typeahead prefix (max 100 characters, no query syntax and no complexity budget)
and never produces these errors.
A q that the search engine rejects returns 400 with the title
Invalid search query and a detail explaining what was wrong. There is no
errors array on these — the whole query is the offending value.
{
"type": "about:blank",
"title": "Invalid search query",
"status": 400,
"detail": "search query too complex: 45 terms/operators (max 40)"
}detail | Cause |
|---|---|
search query too complex: N terms/operators (max 40) | Your query's own terms and operators exceed the 40-node budget. N is the count we measured — drop N - 40 nodes. |
search query must contain at least one positive term | The query is only exclusions (e.g. -python). Add something to match. |
The complexity budget counts only what you wrote, on the parsed query and
before server-side synonym expansion: a bare word costs 1 node plus 1 for
each OR/AND joining it (~20 OR'd words), a quoted two-word phrase costs 3 plus
1 for its OR (~10 phrases), a quoted three-word phrase costs 5 plus 1 (~6),
and a -term exclusion costs 3. English stopwords are free, including inside a
phrase — "director of engineering" costs 3 nodes (it parses as a two-word
phrase), not 5. Synonym expansion is never charged to you, and when an expansion
would grow too large the search silently runs without it rather than failing.
See Search jobs for the full q contract.
Breaking change. This detail text changed: complexity rejections
previously read search query too complex (numnode > 40) and counted the query
after synonym expansion, which made the cost invisible and rejected ordinary
multi-phrase queries. If you match on detail strings, match on the
search query too complex prefix rather than the whole sentence.
A well-formed q that is simply too broad to finish in the server's time
budget returns 422 instead — the query is valid, so narrow it (prefer the
default q_scope=title, or add filters) rather than retrying it unchanged.
URL resolution errors
Resolve a job by URL answers a miss with
404 and the title Not Found. Two stable detail sentences separate the one
case worth giving up on from the one worth retrying — match on the prefix:
detail | Meaning | What to do |
|---|---|---|
Unsupported job board URL. | The URL is not a job posting URL we can parse — an aggregator link, a bespoke careers site, or a board index page. | Stop retrying. This URL will not start resolving. |
No job matched the provided URL. | The URL parsed, but nothing in the catalog matches it. | Treat as "not indexed yet" — a later call may well resolve. |
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "No job matched the provided URL."
}No job matched the provided URL. is deliberately one answer: an employer
we do not index and a posting we have not seen on an employer we do index are
byte-identical here, and no field distinguishes them. Coverage grows over time,
so a URL that misses today can resolve tomorrow.
A missing url, a non-http(s) URL, or one longer than 2048 characters is a
400 validation problem, not a 404.
When the URL resolver itself is unreachable or too slow to answer, the lookup
returns 503 with the title Service Unavailable — nothing is wrong with your
request, so retry the same URL after a short pause. This is the only endpoint
that returns 503 under normal operation.
Status codes
| Status | Meaning |
|---|---|
400 Bad Request | Invalid query parameters, a malformed pagination cursor, or a rejected q (see above). Includes errors[] for field-level validation failures. |
401 Unauthorized | Missing or invalid API key. See Authentication. |
403 Forbidden | The key is valid, but the account is not entitled to a restricted parameter — today only include=source. See Entitlements. |
404 Not Found | No job exists with the requested id, or a Resolve a job by URL lookup returned nothing (see below). |
422 Unprocessable Entity | A valid q that exceeded the search time budget — narrow the query rather than retrying it. |
429 Too Many Requests | Per-account rate limit exceeded. Includes a Retry-After header. See Rate limits. |
500 Internal Server Error | An unexpected error occurred on our side. |
503 Service Unavailable | The Resolve a job by URL resolver was unreachable or too slow. Nothing is wrong with the request — retry the same URL shortly. |