People and company enrichment
The agnt source is first-party. Instead of proxying one vendor, it runs a cheapest-first waterfall across several upstream providers and returns one normalized record, so you write against a single response shape and stop paying the most expensive provider for data a cheaper one already had.
What the agnt source is
Each endpoint has an ordered list of upstream providers, cheapest first. A call walks that list until it has the fields you asked for or runs out of budget, merges what it found, and returns one record in our own schema. You never branch on which provider answered.
Provider identities are stripped on the way out. Responses and usage rows report attempts as counts and HTTP statuses only, never as vendor names, so a change in the waterfall is invisible to your integration.
The endpoints
Twelve POST endpoints under two namespaces. People: email-finder, email-verifier, enrich, find-mobile, search, bulk-enrich. Companies: discover, domain-emails, enrich, search, intelligence, bulk-enrich.
companies/intelligence is one route with a signal of funding, competitors or technographics, plus a domain. Each signal is priced separately.
Two pricing models
Flat endpoints charge exactly their published price, whatever the upstream charged us. If the provider costs more that day, we absorb it; your bill does not move.
POST /v1/data/agnt/people/searchPOST /v1/data/agnt/companies/discoverPOST /v1/data/agnt/companies/domain-emailsPOST /v1/data/agnt/companies/intelligence (funding)POST /v1/data/agnt/companies/intelligence (competitors)POST /v1/data/agnt/companies/intelligence (technographics)Each flat price is published per endpoint rather than fixed in prose. Read it from GET /v1/platforms or on the endpoint page in the API reference, and never copy a number into your own docs or UI.
Range endpoints charge what the waterfall actually spent upstream, multiplied by 1.5, capped by your budget. A lookup the cheapest provider answers on the first attempt costs a fraction of one that walks the whole list. The published range runs from the cheapest single provider to every provider in sequence, and it arrives with each response in meta.priceRange.
| Range endpoint | Waterfall |
|---|---|
POST /v1/data/agnt/people/email-finder | two providers in the waterfall |
POST /v1/data/agnt/people/email-verifier | three providers |
POST /v1/data/agnt/people/enrich | four providers |
POST /v1/data/agnt/people/find-mobile | two providers |
POST /v1/data/agnt/people/bulk-enrich | four providers, budgeted per record |
POST /v1/data/agnt/companies/enrich | three providers |
POST /v1/data/agnt/companies/search | one provider today, so no cost cap is accepted |
POST /v1/data/agnt/companies/bulk-enrich | three providers, budgeted per record |
Capping what a call can cost
Range endpoints take max_cost_cents (single call) or max_cost_cents_per_record (bulk). The waterfall stops before any provider that would push spend past the ceiling, so a cap is a hard limit rather than a hint.
Two ways to get a 400 here. A cap below the endpoint's minimum is rejected, because no provider could run under it and the call would be guaranteed to fail. And a cap on an endpoint that currently has only one configured provider is rejected too, since there is nothing to choose between.
reserved vs billed
Bulk calls
The two bulk endpoints take 1 to 100 inputs. Each input may carry an identifier, a label of your own that is echoed back on the matching result, which is how you align rows without relying on array order.
curl -X POST "https://api.superagnt.com/v1/data/agnt/people/bulk-enrich" \
-H "Authorization: Bearer $AGNTDATA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"inputs": [
{ "identifier": "row-1", "email": "ada@example.com" },
{ "identifier": "row-2", "linkedin_url": "https://www.linkedin.com/in/example" }
],
"max_cost_cents_per_record": 4
}'Every result reports what happened to that record on its own: fields_returned, fields_missing and providers_attempted. A record the waterfall could not resolve comes back with a null record rather than failing the batch.
{
"success": true,
"data": {
"results": [
{
"identifier": "row-1",
"person": { "...": "normalized record, or null" },
"fields_returned": ["email", "job_title"],
"fields_missing": ["mobile"],
"providers_attempted": 2
}
]
},
"meta": {
"costCents": 3,
"purchasedBalanceCents": 4820,
"subscriptionRemainingCents": 1500,
"priceRange": { "minCents": 1.5, "maxCents": 9 },
"budgetCentsPerRecord": 4,
"records": 2,
"latencyMs": 2140
}
}Input rules that trip people up
People must resolve to an email or a LinkedIn URL. people/enrich, find-mobile and bulk-enrich need at least one of email or linkedin_url. A name plus a company is not accepted. If that is all you have, call people/email-finder first, which is the endpoint that does take a name plus a company and hands you back an email.
Companies need one strong handle. At least one of domain, name / company_name, or linkedin_url. Domain resolves best when you have it.
nesting differs between the two
companies/enrich nests its handles under identifiers. companies/bulk-enrich puts them top-level on each input object instead. Copying the shape from one to the other is the most common 400 on this surface.Reading the meta block
Alongside the standard costCents and the two balances, range endpoints add priceRange (the published floor and ceiling), budgetCents (the cap actually applied, yours or the default), providersAttempted, fieldsReturned and fieldsMissing. Together they tell you whether a disappointing result was a data gap or a budget you set too low.
Flat endpoints report providersAttempted but no range or budget, because there is nothing variable to report.
When the waterfall fails
PROVIDER_ERROR with HTTP 502 means no provider returned a result, or none could run inside your budget. Widening max_cost_cents is worth trying before you conclude the record does not exist.
RATE_LIMITED with HTTP 429 and retryAfter: 5 means every attempt was turned away by pacing upstream. Back off for those five seconds and retry; hammering it will not help.
Both are billed at zero. A failed enrichment never costs credits.
Full parameter and response schemas for every endpoint are in the API reference, and the rest of the curated catalog is on data sources.