How enrichment works
The asynchronous request lifecycle, request and item statuses, the 24-hour deadline, credits and duplicate handling.
The Enrichment API turns an email into a person profile, and a domain into a company profile. Enrichment can take a while, so the API is asynchronous: you submit a batch, get back an enrichRequestId right away, and read the request until every item is finished.
Endpoints
| Method | Path | What it does |
|---|---|---|
POST | /v1/enrichment-requests/people | Submit up to 100 people by email. Returns 202. |
POST | /v1/enrichment-requests/companies | Submit up to 100 companies by domain or website URL. Returns 202. |
GET | /v1/enrichment-requests/{enrichRequestId} | Read a request: its status and every item's result. Returns 200. |
Each request holds one type of item: people and companies are always separate requests. All three endpoints need a key with the Enrichment API role (see Authentication).
The request lifecycle
Submit
POST a batch of people or companies. Knock validates the whole batch, starts enrichment and answers 202 Accepted:
{
"enrichRequestId": "7d0f4f1e-2c3b-4a8e-9a51-0e6f3b8c2d14",
"status": "pending"
}If any item is invalid (for example, a malformed email), the whole batch is rejected with 400 and nothing is submitted.
Knock enriches in the background
Each item finishes on its own. Some are final right away: a person Knock already holds an up-to-date profile for can already be final at submit, so the 202 request status may already be in_progress or completed. Read the request to see each item.
Poll for results
GET the request with its enrichRequestId. The response lists every item with its status and, once it's completed, its result. There are no webhooks or callbacks: polling is how you learn that work is done. See Get results for a polling function with backoff.
Stop when the request is final
When no item is pending any more, the request status is completed, partially_completed or failed, and it normally won't change again.
Item statuses
Every item in a request has its own status:
| Status | Final | Meaning |
|---|---|---|
pending | No | Knock is still working on this item. |
completed | Yes | Enrichment finished. result holds the person or company. |
not_found | Yes | Knock looked and found no match for this input. result is null. |
failed | Yes | The item couldn't be enriched, for example an invalid domain or no data by the deadline. result is null. |
An item only ever moves from pending to one final status. Once it's completed, not_found or failed, it normally stays that way. In rare cases a completed item Knock couldn't finish recording can read as pending again on a later read; keep the result you already received.
Request statuses
The request status is a summary of its items, recalculated every time you read it:
| Request status | When |
|---|---|
pending | Every item is still pending. |
in_progress | Some items are finished, some are still pending. |
completed | No item is pending and none failed. Items can be completed or not_found. |
partially_completed | No item is pending, and some (but not all) failed. |
failed | Every item failed. |
pending ──► in_progress ──► completed | partially_completed | failedA request can skip straight to a final status, even in the 202 response, when all of its items are final at submit.
completed doesn't mean every item has data
not_found counts as finished, not failed, so a request where nobody was found is completed. Always check each item's status and result.
Timing and the 24-hour deadline
How long an item takes depends on the input and on how much enrichment Knock is running at that moment. Companies go through a paced queue, so a large batch of companies finishes gradually rather than all at once.
Items don't stay pending forever. Once 24 hours have passed since the request's createdAt, Knock settles whatever is still pending:
- An item that is still
pending24 hours after the request was created is settled the next time you read the request. It becomescompletedif Knock has data for it by then, andfailedotherwise. - If Knock can't check an overdue item at that moment, it stays
pendingand is settled on a later read. Knock never reports "no data" when it simply couldn't look.
Design your integration so results can take up to 24 hours, and keep polling (slowly) until the request is final. The polling recipe includes a stop condition tied to this deadline.
Duplicates and retries
There is no idempotency key. Every successful POST creates a new enrichment request with a new enrichRequestId, even if its body is identical to an earlier one. What the API does with repeated input:
- Within one request, repeated inputs are collapsed into one item. People are matched by email, ignoring case. Companies are matched by their domain, so
acme.comandhttps://www.acme.com/aboutcount as the same company. Items keep the order of their first occurrence. - Across requests, resubmitting a person resolves to the same contact; Knock doesn't create a duplicate. Resubmitting a company that is still being enriched for you joins the work already in progress instead of starting it again.
- One finish, many requests. When enrichment for a person or company finishes, every pending item for that same person or company in any of your requests finishes with it.
Because positions can shift when duplicates are collapsed, match results to your records by each item's input, not by array position. See Match items to your records.
When it's safe to resubmit:
Response to your POST | Was anything created? | What to do |
|---|---|---|
202 | Yes, a new request. | Store the enrichRequestId. Don't resubmit. |
400, 401, 403, 413, 429 | No. | Fix the cause (or wait, for 429) and send it again. |
502 external-api.enrichment.unavailable | No request was stored. | Retry with backoff. |
500 external-api.enrichment-request.not-stored | Enrichment started, but the request couldn't be saved, so you have no ID to read. | Don't resubmit automatically: the items may already be enriched and charged. Contact Knock with the X-Request-Id response header. |
| Network error or client timeout | Unknown: the request may have been created. | Resubmit. Knock resolves the same people and companies and joins work in progress. |
Credits and side effects
Submitting is billable
Every POST starts real enrichment. There is no sandbox or test mode.
- Credits. Enrichment through the API uses your Knock account's enrichment credits, the same credits enrichment uses elsewhere in Knock. How much an item uses depends on whether Knock already holds fresh data for it: an item completed from data Knock already holds is billed once, as an existing record, when it completes. That can happen during a read.
- No double billing within a period. Knock doesn't bill you twice for the same person or company within a billing period, even if you submit it again.
- Rejected requests are free. A request rejected with a
4xxnever reaches enrichment and uses no credits. - Reading doesn't start work. A
GETnever starts new enrichment, so polling costs nothing beyond the items you submitted. It still counts toward your rate limit. - People become contacts. Every person you submit is added to your Knock account's contacts.
Limits
| Limit | Value |
|---|---|
| Items per request | 1 to 100 |
| Request body size | 100 KB (102,400 bytes); larger bodies get 413 |
| Body format | JSON, sent with Content-Type: application/json |
email | A valid email address, at most 254 characters |
firstName, lastName | At most 320 characters each |
domain | A domain or website URL, 1 to 320 characters |
| Rate limit | 600 requests per minute per account by default. See Rate limits. |
Unknown fields in the body are ignored. A batch of 100 people with very long names, especially names with non-Latin characters, can pass 100 KB; split it into smaller requests if you get 413.