Places API

# Errors and Quota Headers

Error response shape, every machine-readable error code, retry behavior, search warnings, and quota headers for the Open Places API.

Error format

## Use stable codes for client behavior.

Search errors use stable machine-readable codes so callers can distinguish validation, auth, quota, coverage, and layer selection failures without parsing prose messages. Every error body carries `code`, `message`, `request_id`, and `docs_url`, a link to that code's entry on this page (`https://openplacesapi.com/docs/errors#<code>`). Validation errors add `details`, a list of `field` and `message` pairs for each rejected parameter. 

JSON ErrorResponse 

```
{
  "error": {
    "code": "validation_error",
    "message": "Invalid search request.",
    "request_id": "550e8400-e29b-41d4-a716-446655440000",
    "details": [
      { "field": "radius_mi", "message": "radius_mi must be greater than 0 and at most 50." }
    ],
    "docs_url": "https://openplacesapi.com/docs/errors#validation_error"
  }
}
```

`quota_exhausted` also returns `quota_limit` and `upgrade_url`. Buy more searches from the dashboard billing page. There is no reset date or automatic charge.

JSON 402 quota\_exhausted 

```
{
  "error": {
    "code": "quota_exhausted",
    "message": "No searches left on this account. Buy more at https://app.openplacesapi.com/#billing.",
    "request_id": "550e8400-e29b-41d4-a716-446655440000",
    "quota_limit": 2500,
    "upgrade_url": "https://app.openplacesapi.com/#billing",
    "docs_url": "https://openplacesapi.com/docs/errors#quota_exhausted"
  }
}
```

Statuses

## HTTP status maps to the failure class.

| Status | Meaning                                                                                                                                                                                                                                                                                       |
| ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400    | Invalid query parameter shape.                                                                                                                                                                                                                                                                |
| 401    | Missing bearer API key (unauthenticated) or invalid key (invalid\_api\_key).                                                                                                                                                                                                                  |
| 402    | Credit balance exhausted (quota\_exhausted).                                                                                                                                                                                                                                                  |
| 403    | Requested layer selection is well-formed but unavailable to the authenticated account. layer\_entry\_cap\_exceeded means the account is at its layer capacity: 250 entries before buying, 5,000 after any purchase. Archive entries, buy a pack, or email support@openplacesapi.com for more. |
| 405    | Only GET is supported.                                                                                                                                                                                                                                                                        |
| 422    | Reserved for unsupported\_query; not currently returned.                                                                                                                                                                                                                                      |
| 429    | rate\_limited: the burst limit (120 requests per minute per account and per key, for everyone) or the concurrency cap (8 searches in flight per account) was exceeded, or too many failed authentication attempts came from one IP.                                                           |
| 500    | Generic internal error.                                                                                                                                                                                                                                                                       |
| 503    | Temporarily unavailable: coverage\_not\_ready, search\_timeout, or quota\_gate\_unavailable. Retry after Retry-After seconds.                                                                                                                                                                 |

Error codes

## Every public code and what to do about it.

Search errors link to their row through `docs_url`. Branch on `code`, not on `message`; messages can change wording. 

Management and billing responses from `app.openplacesapi.com` use a different shape: `{"error":{"code":"…","message":"…"}}`, without the search API's `request_id` or `docs_url` fields. The two management and billing codes below are marked in their descriptions. 

| Code                        | Status | Meaning and client action                                                                                                                                                                                          |
| --------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| validation\_error           | 400    | A parameter is missing, malformed, out of range, or unknown. Read details for each rejected field, fix the request, and do not retry it unchanged.                                                                 |
| unauthenticated             | 401    | No bearer API key was sent. Send Authorization: Bearer opa\_live\_... from a server-side environment.                                                                                                              |
| invalid\_api\_key           | 401    | The key is malformed, revoked, or unknown. Check the stored secret or create a new key in the dashboard; retrying with the same key will not help.                                                                 |
| method\_not\_allowed        | 405    | Only GET is supported on /v1/places and /v1/categories.                                                                                                                                                            |
| unsupported\_query          | 422    | Reserved for recognized but unsupported search shapes. Not currently returned; unsupported inputs are rejected with validation\_error.                                                                             |
| layer\_not\_available       | 403    | The layer selection is well-formed but not available to this account, or the preset does not exist. Check layers, layer\_preset, or the key's default preset.                                                      |
| quota\_exhausted            | 402    | The prepaid search balance is zero or expired and the request was not billed. Stop retrying. Buy more searches at upgrade\_url; there is no reset or automatic charge.                                             |
| rate\_limited               | 429    | Too many requests per minute, more than 8 searches in flight for the account, or too many failed authentication attempts from one IP. Not billed. Wait Retry-After seconds and reduce request rate or parallelism. |
| coverage\_not\_ready        | 503    | The data for this location is not ready to search yet. Retry after Retry-After seconds (30).                                                                                                                       |
| search\_timeout             | 503    | The search did not finish in time and was not billed. Retry after Retry-After seconds (5); a smaller radius or more specific query can help.                                                                       |
| quota\_gate\_unavailable    | 503    | The API key or quota could not be checked, or the search reservation expired. Retry after Retry-After seconds.                                                                                                     |
| layer\_entry\_cap\_exceeded | 403    | Management API: the account is at its layer-entry capacity (250 before a purchase, 5,000 afterward). Draft and published entries count; archive entries or email support for more capacity.                        |
| internal\_error             | 500    | Unexpected server error. Retry with backoff, and include request\_id if you contact support.                                                                                                                       |

Retries

## Retry only what the API says is temporary.

When a response includes `Retry-After`, wait at least that many seconds before retrying. For `rate_limited` it is the time until the burst window resets, or `1` when the account hit the concurrency cap. For `503` codes it is a short backoff hint. `quota_exhausted` has no `Retry-After` or reset date. Stop and buy more at `upgrade_url`. 

Each account can have at most 8 searches in flight at once. Requests over the cap are rejected immediately with `rate_limited` and are not billed. Bound client-side parallelism to stay under the cap. 

Search warnings

## Empty results explain themselves.

Successful searches can include `meta.warnings`, a list of `code` and `message`objects. Warnings do not change the HTTP status. `unknown_category` and `no_results_within_radius` are only added to an empty first page (`offset=0` with no results). 

| Warning                     | Meaning and client action                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| category\_alias             | A reviewed legacy category was resolved to resolved\_category, also returned in meta.category. This warning can appear on any successful page. Legacy parent aliases can narrow the old filter; check the resolved slug against the scope you need.                                                                                                                                                                                                                                                            |
| unknown\_category           | The category value is not a known Overture category. suggestions lists the closest known slugs when any are found. Retry with one of them, or look slugs up with [GET /v1/categories](/docs/reference#categories).                                                                                                                                                                                                                                                                                             |
| no\_results\_within\_radius | Nothing matched within radius\_mi. When a match was found within 100 miles, nearest\_match identifies the closest place found (public id, name, distance\_mi, and locality and country when available). It stays outside results. nearest\_match\_distance\_mi gives the same approximate distance and the message names the radius\_mi to retry with, or says the match is beyond the 50 mile maximum so the search should start from a closer point. Without that field, nothing was found within 100 miles. |
| address\_matching\_skipped  | A short mode=all query searched names only. Use a longer query to include addresses.                                                                                                                                                                                                                                                                                                                                                                                                                           |
| query\_relaxed              | q had no exact matches, so the search was retried once with a relaxed form of q(legal suffixes such as LLC, parenthesized asides, and connector words removed). The message names the text used. Check that the results are the place you meant before relying on them.                                                                                                                                                                                                                                        |
| category\_inferred          | No place names matched q, even relaxed, so it was read as the closest category by meaning (for example travel agency as travel\_agent). The results are nearby places in that category, named in the message and in meta.interpreted\_as; none of them is a place called q. Use mode=name to turn this off.                                                                                                                                                                                                    |
| pagination\_limit\_reached  | More places match a category browse than its 1,000-place window can page through, so next\_offset is null even though the results continue. Narrow radius\_mi, raise min\_confidence, or add q to reach the rest.                                                                                                                                                                                                                                                                                              |
| layer\_entries\_truncated   | The per-search layer read limit was reached, so some published layer entries were not applied.                                                                                                                                                                                                                                                                                                                                                                                                                 |

JSON meta.warnings 

```
{
  "warnings": [
    {
      "code": "unknown_category",
      "message": "\"coffeeshop\" is not a known category. Closest known categories: coffee_shop. List categories with GET /v1/categories?q=<text>.",
      "suggestions": ["coffee_shop"]
    }
  ]
}
```

Headers

## Quota and retry metadata travel in headers.

`X-Quota-Limit` and `X-Quota-Remaining` are sent on successful searches and `quota_exhausted` responses. Other failures, including invalid keys and validation errors, do not carry quota headers. 

| Header            | Use                                                                                          |
| ----------------- | -------------------------------------------------------------------------------------------- |
| X-Request-ID      | Server-generated request identifier for support and debugging.                               |
| X-Quota-Limit     | Current credit balance allocation.                                                           |
| X-Quota-Remaining | Unused, unexpired searches in the current balance.                                           |
| Retry-After       | Seconds to wait before retrying after rate\_limited or a 503. A credit balance never resets. |
