// people and companies

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.

12 endpointsflat and range pricingbulk up to 100
01// the waterfall

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.

02// the endpoints

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.

03// two pricing models

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/search
POST /v1/data/agnt/companies/discover
POST /v1/data/agnt/companies/domain-emails
POST /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 endpointWaterfall
POST /v1/data/agnt/people/email-findertwo providers in the waterfall
POST /v1/data/agnt/people/email-verifierthree providers
POST /v1/data/agnt/people/enrichfour providers
POST /v1/data/agnt/people/find-mobiletwo providers
POST /v1/data/agnt/people/bulk-enrichfour providers, budgeted per record
POST /v1/data/agnt/companies/enrichthree providers
POST /v1/data/agnt/companies/searchone provider today, so no cost cap is accepted
POST /v1/data/agnt/companies/bulk-enrichthree providers, budgeted per record
04// capping cost

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

Your balance is reserved at the ceiling for the duration of the call, so a big cap needs the credits to back it. What you are actually billed is the real upstream spend times the markup, which is usually far less. The reservation is a gate, not a charge.
05// bulk calls

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.

bulk enrichbash
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.

bulk response (figures illustrative)json
{
  "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
  }
}
06// input rules

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.
07// reading meta

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.

08// when it fails

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.