Skip to content
heyenrich
API

One request, one record

Same data as the lookup box, same per-field pricing, same check dates. Keys are on the first screen after signup, the reference needs no login, and test keys return sample people without charging a credit.

The whole thing in one call

A lookup returns every field you asked for with its own state and check date, plus the credits actually charged. A miss is an HTTP 200 with match: false and credits_charged: 0.

POST https://api.heyenrich.io/v1/lookup
curl https://api.heyenrich.io/v1/lookup \
  -H "Authorization: Bearer he_live_…" \
  -H "Content-Type: application/json" \
  -d '{ "linkedin_url": "https://linkedin.com/in/priya-raman-example",
        "fields": ["work_email", "personal_email", "mobile"] }'

{
  "match": true,
  "name": "Priya Raman",
  "title": "Head of Growth",
  "company": { "name": "Northwind Traders", "domain": "northwind-traders.example",
               "headcount_band": "51-200", "industry": "Logistics" },
  "work_email":     { "value": "p.raman@northwind-traders.example",
                      "state": "verified", "checked_at": "2026-10-18" },
  "personal_email": { "value": "pr.raman@gmail.com",
                      "state": "verified", "checked_at": "2026-09-30" },
  "mobile":         { "value": "+15125550141", "line_type": "mobile",
                      "state": "verified", "checked_at": "2026-10-02" },
  "credits_charged": 8,
  "latency_ms": 171
}

Credits per endpoint

One table, every endpoint, including what a miss costs. Rate limits are per account and shared across sub-keys.

EndpointDoesCreditsOn a missRate limit
POST /v1/lookupOne person from a LinkedIn URL, name + domain, name + location, or work email1 work, 2 personal, 5 mobile060 to 1,000 rpm by plan
POST /v1/bulkUp to 100,000 rows; job id back; poll or webhookSame per filled field0Queued, not rate-limited
GET /v1/company/{domain}Email pattern with share, catch-all, MX provider, headcount band1, or free with a person match0Same as lookup
POST /v1/verifyCheck an address you already have0.50Same as lookup
GET /v1/creditsBalance, usage, rollover expiry00Unlimited

Measured, not claimed

180ms

median /v1/lookup, 30 days, at our edge

99.95%

uptime target, published on status.heyenrich.io

0

credits charged by he_test_ keys, ever

Behaviour worth knowing

A miss is a 200, not a 404

match: false and credits_charged: 0. Your pipeline doesn't need a special case.

Ask only for the fields you'll use

fields: ["work_email"] means you're never charged for a mobile you didn't want.

Idempotent bulk

Pass an Idempotency-Key on /v1/bulk and a retried upload won't run twice.

Sub-keys for agencies

Keys scoped to a client workspace with their own limits. Usage shows in your dashboard; the client never sees your main key.

Opt-outs by webhook

Subscribe to person.suppressed and delete the record on your side. Required if you store what we return.

Sandbox

Keys prefixed he_test_ return the three sample people from the homepage and never charge.

Keys on the first screen after signup

No form, no call. Create a key, make a lookup, read the states.

FAQ

API questions

What do the states mean?

verified: resolved at lookup time. risky: the domain accepts every address, so the value may or may not exist; charged and labelled. notfound: nothing on file; not charged.

Is there an MCP server?

Not yet. It ships when it works; we'd rather not list it until then. The REST API is simple enough that an agent can call it with one tool definition.

Can I use it from Clay?

Yes. Add an HTTP API column pointing at /v1/lookup with your key in the header. The walkthrough, with the exact body and column mappings, is on /integrations/clay.

Rate limits?

60 requests a minute on Starter, 300 on Growth; Custom plans set their own. Bulk jobs don't count. Headers tell you what's left.

Which SDKs exist?

None yet, on purpose. It's one endpoint with JSON in and out. The reference has curl, Node and Python samples for every call.