Rate limits & errors
Things fail. Networks blink. Providers go quiet. This page is about what abm.dev does when they do, and what you should do back.
The short version: abm.dev never guesses. A value is cited or it is not returned. So most of your error handling is not about bad data — it is about missing data, slow data, and the occasional bad request.
How requests work
Two endpoints. That is the whole surface for enrichment.
POST https://api.abm.dev/api/v2/enrichments
GET https://api.abm.dev/api/v2/enrichments/{id}Authenticate with a header. Send JSON.
x-api-key: YOUR_API_KEY
Content-Type: application/json{ "targets": [ { "type": "person", "email": "[email protected]" } ] }Each target also takes a LinkedIn URL or a company domain. You POST once to start an enrichment, then GET the same {id} to read it. The {id} is your handle for everything after.
Note
x-api-key header (used here) or Authorization: Bearer on POST /api/v2/enrichments. The full, live contract is at the API reference.What a “clean” response still won’t promise
There is no failure here, but you should plan for it anyway.
A response is a set of canonical fields — eighty-nine of them, forty-three person and forty-six company — plus up to forty signals. Resolved from ten data sources: LinkedIn, Companies House, Perplexity, Tavily, Hunter, and others, returned as one answer.
Every value carries three things: its source (which provider stood behind it), a confidence between 0 and 1, and a selection_reason explaining why that value was chosen. Higher confidence means more sources agreed. Lower confidence means fewer. Read it; do not assume it.
The rule that governs all of this: a value is cited or it is not returned.No fabricated facts. No silent fallbacks. So a “missing” field is not an error. It is honesty. If a contact has no verified title, you get no title — not a guess.
Treat absence as a first-class case. Branch on whether a field is present, not on whether the request succeeded.
When a request is rejected
A request can be rejected before any enrichment runs. The usual reasons:
- The key is wrong, missing, or revoked. Check the
x-api-keyheader. Generate or rotate keys from the dashboard and the getting-started guide. - The body is malformed. It must be valid JSON with
Content-Type: application/json. Match the shape above: atypeand aninput. - The input cannot be resolved. An address that points nowhere, a domain that does not exist. There is nothing to cite, so nothing comes back.
Lead with the simple checks. Most rejected requests are a bad header or a bad body, not a bad service.
The exact HTTP status codes and error-response shape are documented with the live endpoints — see the enrichment reference. We will not reprint numbers here that we cannot verify.
When a request is slow
Enrichment talks to ten sources. Sometimes one of them is slow, and the answer takes a moment to assemble.
For agent loops, abm.dev streams progress in real time over SSE, so a long-running enrichment is not a black box — you watch it fill in. For batch jobs, a webhook fires when the job finishes; you do not poll a queue by hand. (Streaming and webhook specifics are evolving — see the jobs reference and for-agents for the current contract.)
If you are not streaming, the pattern is plain: POST to start, then GET /api/v2/enrichments/{id} to read the result when it is ready.
How to retry without making it worse
The {id} is the safety rail. Reading an enrichment is just a GET — do it as many times as you like.
POSTonce to start. Keep the{id}it returns.- Re-read, don’t re-submit. If a read is slow or your connection drops,
GET /api/v2/enrichments/{id}again. You are reading the same job, not buying a new one. - Space out retries. Wait a little, wait longer the next time. A failed read is rarely fixed by an instant second try.
- Stop and look at persistent failures. If a
GETkeeps failing, the problem is the request or the key, not luck. Re-check the header and the{id}.
This matters for cost. Pricing is per enrichment — about €0.29 each, no subscription, credits that never expire, all ten sources included. Re-reading an {id} with GET does not start a new enrichment. Re-POSTing the same input does. When in doubt, read; do not re-submit. See pricing.
What we are not telling you (on purpose)
No invented rate-limit numbers. No plan-tier names. No retry schedule we cannot stand behind. No webhook signature scheme. The live API reference is the source of truth for limits, status codes, and the webhook contract; this page points you there rather than guessing.
If you hit a wall the docs don’t cover, open a ticket.
Where to go next
- API reference — the live contract, including limits and status codes.
- Enrichment reference — request and response detail.
- Jobs reference — batch and streaming behaviour.
- Confidence scores — how to read the
0–1value. - Data sources — the ten providers and how they resolve.
- For agents — the MCP server at
https://mcp.abm.dev/mcpand agent setup.
abm.dev is operated by Foxley Farm Operations Ltd (UK Company No. 16392009), Oakham, United Kingdom. GDPR-compliant.