Skip to content

API

API errors and rate limits

By the MapsData team · Last updated

Every failure uses one envelope with a stable code. Branch on the code, not on the status or the message. Statuses are conventional and messages are written for humans and may be reworded; codes are part of the contract.

{"error": { "code": "lead_limit_reached", "message": "This cycle's lead allowance is spent: 4,812 of 5,000 used.", "field": "total_limit", "details": {"leads_used": 4812, "lead_limit": 5000}, "request_id": "req_..." }}
  • field names the offending input when one is to blame.
  • details carries whatever is useful to act on, such as the suggestions for an unrecognised category or the figures behind a quota rejection.
  • request_id is worth logging. Quote it to us and we can find the exact request.

Codes

Authentication and access

CodeStatusWhat to do
invalid_api_key401Check the header and the key. Do not retry with the same value.
key_revoked401Create a new key in Settings.
key_expired401Create a new key.
insufficient_scope403The key lacks the scope named in details.
api_not_available_on_plan403API access is on every paid plan: Starter, Pro, Scale and custom.
api_disabled503The API is temporarily off. Retry after the interval given.

Your request

CodeStatusWhat to do
validation_error422The body failed schema validation. field names the culprit. Unknown fields are rejected, so check for a typo.
unsupported_query400Not a Google Maps category. Use the suggestions, or search /categories.
unknown_regions400A region name was not recognised. Use full names, not abbreviations.
missing_region400No valid region was supplied.
missing_location400Give either states or cities.
unresolvable_cities400None of the named cities exist in our index.
unsupported_country400Use one of us, au, uk, ca.
too_many_queries400Up to three categories per job.
too_many_cities400Up to fifty cities per job.
invalid_total_limit400total_limit must be a positive number of rows.
total_limit_exceeds_max400Above your per-scrape ceiling. Split the job.
invalid_max_emails_per_company400Must be 1 or more, or omitted entirely.
invalid_cursor400Pass a next_cursor from a previous page, or omit it.
client_forbidden403This key cannot use that client_id. See /clients.

Your workspace

CodeStatusWhat to do
lead_limit_reached402This cycle's allowance is spent. It resets on your billing date.
org_past_due402Payment failed, so new scrapes are paused. Existing results still download.
org_cancelled403Subscription cancelled. Resume it in billing.
org_blocked403The workspace is suspended. Contact us.
queue_depth_exceeded409Too many scrapes already waiting. Let one start first.

Jobs and files

CodeStatusWhat to do
job_not_found404No such job in this workspace.
job_not_complete409The scrape has not finished, so no file exists yet.
download_not_available404That format or scope does not exist for this job. Check the job's downloads flags.
job_not_cancellable409Already finished.
download_unavailable503Could not mint a link. Retry.

Retries

CodeStatusWhat to do
idempotency_key_reuse409That key was used with a different body. Use a new key.
request_in_progress409A request with that key is still being processed. Retry shortly.
rate_limited429Back off for Retry-After seconds.

Rate limits

Limits are per minute, in fixed windows.

ScopeLimitApplies to
Per key120 / minEvery request
Per workspace300 / minEvery request, across all your keys
Submissions10 / minPOST /jobs only

An idempotent replay does not count against the submission limit, because it creates nothing.

In front of all of that sits an edge limit of 300 requests per minute per source address, covering the REST API, the MCP server and the OAuth endpoints. A runaway loop is refused there before it reaches the application at all, and that response carries no X-RateLimit-* headers because nothing authenticated it.

Headers

Every response carries your current position:

X-RateLimit-Limit: 120 X-RateLimit-Remaining: 118 X-RateLimit-Reset: 1788387840

X-RateLimit-Reset is a Unix timestamp for when the window rolls over. On a 429 you also get Retry-After in seconds, computed from that boundary rather than being a flat minute, so honouring it resumes as early as possible.

Retrying well

  • 429 and 503 are worth retrying. Wait for Retry-After, then use exponential backoff with jitter.
  • 5xx is worth one or two retries with backoff.
  • 4xx other than 429 will not succeed on retry. Fix the request.
  • Put an Idempotency-Key on every submission you might retry. It is the difference between a retry and a duplicate scrape.

Build on MapsData

The REST API and the MCP server are included on every paid plan, with the same allowance as the app. Subscribe or start a trial, then create a key in Settings.

See plans and API access