Errors and limits
The status codes and error codes the API returns, and the limits a request can reach.
Error format
An error is JSON with an error object. Branch on its code: it is the machine-readable name, and part of the contract.
| Field | Meaning |
|---|---|
error.code | The error’s name, one of the codes below. |
error.message | What happened, in words a person can read. |
error.details | Present when there is more to say: the failing fields, the limit and what was used, or when it resets. |
request_id | On a search that failed after it started: quote it when you write to support. |
Status codes
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request | The request or a setting in it is not valid. details names the failing fields, and a search that names an unknown provider returns it too. |
| 400 | unsupported_filter | A filter the provider can’t apply. The request is refused rather than return unfiltered results that look filtered. |
| 401 | unauthorized | The key is missing, invalid or inactive. Send it as Authorization: Bearer $GROUNDER_KEY. |
| 402 | free_searches_exhausted | All 1,000 free searches on the account are used. details carries limit and used. |
| 409 | already_subscribed | The account already has billing. Manage it from your account page. |
| 429 | daily_limit_reached | The 100 free searches for this UTC day are used. They reset at midnight UTC; Retry-After is the seconds left, and details carries daily_limit, used_today and resets_at. |
| 429 | cap_reached | A monthly cap you set on your account page is reached: searches, tokens or search time. It resets on the 1st, UTC; details carries cap, limit, used and resets_at, and Retry-After is the seconds left. |
| 429 | rate_limited | More than 120 requests in a minute on one key. details carries limit and reset_at. |
| 429 | provider_error | A provider rate-limited the search. details.provider_code is rate_limited. |
| 500 | internal_error | A failure on Grounder’s side that nothing planned for. Try again in a minute. |
| 502 | billing_unavailable | Billing didn’t answer. Try again in a minute. |
| 503 | no_provider_available | No provider could serve the search: every provider failed, or none could take it. details.calls lists what each one did. |
| 503 | capacity_reached | Free searches have reached today’s limit across Grounder. They open again at midnight UTC; Retry-After is the seconds left. |
| 503 | provider_error | A provider failed or refused the search, with its own reason in details.provider_code. |
| 503 | internal_error | Grounder couldn’t finish the search: it couldn’t check your free searches or read your routing settings, or something failed on its side. Try again in a minute. |
| 503 | billing_unavailable | Billing isn’t set up yet. |
A code can come back with more than one status, so branch on error.code, not on the status.
Limits
| Limit | Value | How it works |
|---|---|---|
| Free searches in all | 1,000 | On each account. The next search returns free_searches_exhausted. |
| Free searches a day | 100 | In a UTC day, which starts again at midnight UTC. The next search returns daily_limit_reached. |
| Requests a minute | 120 | On each key, in a one-minute window. A search answers with X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. |
| Monthly caps | None until you set them | Set on your account page, for searches, tokens or search time. A search past one returns cap_reached. |
A search counts once it has searched. One that fails on every provider doesn’t count, and neither does the demo.