Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.thehog.ai/llms.txt

Use this file to discover all available pages before exploring further.

Contact enrichment turns a person ID or social handle into verified email addresses and phone numbers. You can enrich contacts one at a time for immediate results, or submit large batches asynchronously and poll for completion. Before running a large enrichment job, a pre-flight estimate endpoint tells you exactly how many credits the request will consume.

Endpoint overview

EndpointMethodWhat it does
/api/people/enrichPOSTEnrich one or more contacts with email and phone
/api/people/enrich/estimatePOSTPre-flight credit and latency estimate
/api/operations/:idGETPoll the status of an async enrichment job

Enrichment request

POST https://api.thehog.ai/api/people/enrich

Input modes

You can identify who to enrich in two ways — use whichever you have available:
Pass person id values from a previous people search. Each object in the people array takes a single id field.
{
  "people": [
    { "id": "p_01habc" },
    { "id": "p_01hdef" }
  ]
}

Request fields

FieldTypeDefaultDescription
peoplePersonIdentifier[]Person IDs to enrich (use this or identities)
identitiesPlatformIdentity[]Platform handles to resolve and enrich
asyncPreferredbooleantruefalse → sync response (HTTP 200); true → async job (HTTP 202)
maxEmailProviderAttemptsnumber2Waterfall depth for email lookup: 1–2. Lower = cheaper, less coverage
maxPhoneProviderAttemptsnumber3Waterfall depth for phone lookup: 1–3. Lower = cheaper, less coverage
projectIdstringOptional project context
Run POST /api/people/enrich/estimate before enriching a large batch. The estimate response shows you the expected credit cost and whether the job will run sync or async — so there are no surprises on your bill.

Examples

curl -X POST https://api.thehog.ai/api/people/enrich \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "identities": [
      { "platform": "linkedin", "username": "jordan-rivera" }
    ],
    "asyncPreferred": false,
    "maxEmailProviderAttempts": 2,
    "maxPhoneProviderAttempts": 2
  }'

Responses

Sync enrichment (HTTP 200)

When asyncPreferred is false, you get an immediate response with enriched data.
{
  "data": {
    "people": [
      {
        "id": "enr_01habc",
        "canonicalPersonId": "p_01habc",
        "fullName": "Jordan Rivera",
        "title": "VP of Sales",
        "companyName": "Acme Corp",
        "location": "San Francisco, CA",
        "emailStatus": "available",
        "phoneStatus": "available",
        "emails": [
          {
            "email": "jordan@acme.com",
            "emailType": "work",
            "isVerified": true
          }
        ],
        "phoneNumbers": [
          {
            "phoneNumber": "+14155550100",
            "phoneType": "direct",
            "isVerified": false
          }
        ],
        "fromCache": false
      }
    ]
  },
  "meta": {
    "requestId": "req_01hxyz",
    "cost": { "estimated": 3, "actual": 3 }
  }
}

Async accepted (HTTP 202)

When asyncPreferred is true (the default), you receive a job reference immediately.
{
  "operationId": "op_01hxyz",
  "status": "queued",
  "pollUrl": "/api/operations/op_01hxyz",
  "meta": {
    "requestId": "req_01habc",
    "estimatedCost": 9
  }
}
Poll GET /api/operations/:id until status is "succeeded". The enriched records are in result.people.
{
  "id": "op_01hxyz",
  "status": "succeeded",
  "progress": 100,
  "result": {
    "people": [...]
  },
  "error": null
}

Pre-flight estimate response

{
  "data": {
    "estimatedCredits": 9,
    "likelySyncOrAsync": "async",
    "expectedLatencyRange": "10–30s",
    "providersLikelyUsed": ["provider-a", "provider-b"],
    "withinPlanLimits": true
  },
  "meta": {
    "requestId": "req_01hxyz"
  }
}

Enriched person fields

FieldTypeDescription
idstringEnrichment record ID
canonicalPersonIdstringThe underlying person ID (matches search results)
fullNamestringPerson’s full name
titlestringJob title
companyNamestringCurrent employer
locationstringLocation
emailStatusstring"available", "not_found", or "error"
phoneStatusstring"available", "not_found", or "error"
emailsarrayList of { email, emailType, isVerified } objects
phoneNumbersarrayList of { phoneNumber, phoneType, isVerified } objects
fromCachebooleantrue when the result was served from cache without hitting providers
messagestringOptional note when data is unavailable or partial

Controlling cost vs. coverage

The waterfall depth parameters let you trade off between credit spend and data coverage:

maxEmailProviderAttempts

Set to 1 to use only the first email provider. Set to 2 (default) to try a second provider when the first returns no result. More attempts = higher coverage, higher cost.

maxPhoneProviderAttempts

Set to 13. Each additional attempt queries a different phone data provider. The default (3) maximizes coverage; 1 minimizes spend when phone numbers are a lower priority.