Resolve a Batch of Records
The pipeline for resolving a list of partial records — a conference registration list, a trade-show scan, an acquired CRM — to identities you can act on. Deep Match is asynchronous: you submit a batch, wait for it, then reconcile. What the answers mean is in Deep Match.
The pipeline#
https://api.aggknowledgeai.com/v3/{environment}. See Environments.metadata on each row to carry your own identifier through.batchId immediately with status pending, plus one rows entry per submitted row carrying its rowId. Tier 3.status is ready, items holds one entry per submitted row. Tier 4, and not billed — the matched rows were charged when they resolved.rowId or your own metadata, then branch on outcome.Submitting the batch#
Send only the fields you actually hold. An absent field costs nothing; a guessed one can push a row to multiple_candidates.
curl --request POST \
--url https://api.aggknowledgeai.com/v3/live/person/asynchronous/deep-match \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_API_KEY' \
--data '{
"rows": [
{
"fullName": "dan entrup",
"stateOrProvince": "new york",
"country": "united states",
"emails": ["dan.entrup@example.com"],
"employerNames": ["aggknowledge"],
"metadata": { "crmId": "A-17" }
},
{ "npis": ["1033479100"], "metadata": { "crmId": "B-99" } },
{ "fullName": "jay patel", "country": "united states", "metadata": { "crmId": "C-42" } }
]
}'The response gives you the handle and an upper bound on cost. rowCount is rows accepted, and only rows that resolve are charged, so the batch can cost anything from nothing to rowCount credits. Each row below is abbreviated; the API echoes every field you sent.
{
"batchId": "2db5ea61-1752-42cf-8ea1-ab1da060cd0a",
"rowCount": 3,
"status": "pending",
"rows": [
{ "rowId": "b6f0e2a1-9c3d-4f5e-8a7b-1d2c3e4f5a6b", "rowIndex": 0, "row": { "fullName": "dan entrup", "metadata": { "crmId": "A-17" } } },
{ "rowId": "c7a1f3b2-0d4e-4a6f-9b8c-2e3d4f5a6b7c", "rowIndex": 1, "row": { "npis": ["1033479100"], "metadata": { "crmId": "B-99" } } },
{ "rowId": "d8b2a4c3-1e5f-4b7a-8c9d-3f4e5a6b7c8d", "rowIndex": 2, "row": { "fullName": "jay patel", "metadata": { "crmId": "C-42" } } }
]
}rowId, not on position. The create response pairs every rowId with the row it came from, so build your map from that rather than from the order you sent. rowIndex still marks where a row sat in the batch, and items still comes back in that order — but it identifies a position, not a record, so it stops being true the moment you filter or reorder anything.Collecting the results#
Poll the batch by its batchId until status is ready. Reading a batch back is free and rate-limited at tier 4, so a steady interval costs you nothing but the request.
curl --request GET \
--url https://api.aggknowledgeai.com/v3/live/person/asynchronous/deep-match/BATCH_ID \
--header 'x-api-key: YOUR_API_KEY'status before you read items. Every submitted row is present in items from the moment the batch is accepted — while the batch is pending, their outcome and match fields are null. Iterating early yields a full-length array of unresolved rows, not an empty one, so a loop that does not gate on status === "ready" will silently record every row as a miss.Triage the outcomes#
A completed batch is not an all-matched batch. Branch on outcome — never on whether personId is populated, which misreads every professional resolved outside the dataset and nearly every healthcare match as a failure.
outcome | Resubmitting helps? | Action |
|---|---|---|
matched | — | Store whichever of personId, socialProfile, and aggkHcpId came back. |
multiple_candidates | Only with more evidence | Reconcile candidates against your own records first — often one of them is obviously the record you hold. Otherwise queue for a second pass once you can add an email, phone, or employer. Resubmitting the identical row returns the identical answer. |
no_match | Only with better input | Flag the source record. The signals you hold do not describe anyone we know. |
suppressed | No | Record the decline permanently and stop re-sending the record on later runs. |
failed | Yes | Transient. Collect these rows and submit them as a new batch. |
scoringVersion alongside the outcome. It is the only way to tell a change in your own input quality from a re-tune on our side when you compare this month’s match rate to last month’s.Cost control#
You are charged one credit per row that resolves, whatever evidence it returned — a trail carrying a dozen criteria is still one answer. multiple_candidates, no_match, suppressed, and failed rows are free — a shortlist of three evidenced candidates costs nothing — and reading a batch back is free.
So the lever is input quality, not batch size. Dropping rows that carry nothing but a common first name costs you nothing, but sending them costs nothing either — they will not resolve. Adding one real signal to a row that would otherwise come back multiple_candidates is what converts spend into answers. Run a sample against the test environment first to exercise your integration without spending credits.