Skip to main content

Documentation Index

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

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

Use case

Turn partial lead records into full contact profiles for sales outreach, CRM enrichment, or lead qualification.
This endpoint is also available at /enrich-lead and /enrich-lead-async. Both paths are fully supported and functionally identical.

Endpoint

POST https://api.sixtyfour.ai/people-intelligence

API Reference

See the full request/response schema and parameters in the API Reference.

Pricing

See Credits & Pricing Guide for credit costs by tier.

Errors

For error responses (400, 403, 422, etc.), see Handling Errors.

Tiers

The tier parameter controls research depth and cost.
TierDescriptionAccess
low (default)Baseline tier — fast and cheap. Good for high-volume enrichment where you mostly need a name → email/LinkedIn mapping.All orgs
mediumDeeper research with more sources and iterations. Better for hard-to-find contacts.All orgs
highOSINT-grade investigation — deeply recursive crawling across the open web, dark web, directories, proprietary sources. Designed for the hardest prospects, sensitive diligence, and investigative workflows.Exclusive — access is granted case-by-case by our team. Contact sales to request.
If tier is omitted, low is used. Requests with tier: "high" on an org without high-tier access return 403 — see Handling Errors.

Using the struct field

The struct field defines exactly what data you want back. Each key becomes a field in structured_data, and its value tells the agent what to find. You can pass either a plain-English description or an object with description and type:
{
  "struct": {
    "email": "The individual's email address",
    "github_url": {"description": "URL for their GitHub profile", "type": "str"}
  }
}
The agent uses these descriptions to guide its research. Be specific — "The individual's primary work email" returns better results than "email". For supported types, type resolution priority, and casting examples, see Struct & Type Casting.

Timeouts and parallelization

This endpoint performs deep research and is a long-running operation. Typical P95 runtime is about 5 minutes and can reach 10 minutes for complex leads. We are actively working on performance improvements.
  • Set client timeouts appropriately: If you call the sync endpoint, configure your HTTP client with a timeout of at least 15 minutes.
  • Prefer async in production: Use POST /people-intelligence-async and poll GET /job-status/{task_id}.
  • Parallelize for throughput: Submit multiple async jobs in parallel (bounded concurrency) rather than waiting for each to complete sequentially.

Understanding scores

FieldMeaningRange
confidence_scoreGlobal quality score — overall quality, consistency, and correctness of the returned data.0–10
The findings field on the response is deprecated. It currently returns an empty list and will be removed in a future update.

Sync usage

Make a direct request and wait for the response. Enrichment can take several minutes depending on depth of research.
curl -X POST "https://api.sixtyfour.ai/people-intelligence" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "lead_info": {
      "name": "Saarth Shah",
      "title": "CEO & Co-Founder @ Sixtyfour AI",
      "company": "Sixtyfour AI",
      "location": "San Francisco",
      "linkedin": "https://www.linkedin.com/in/saarthshah"
    },
    "struct": {
      "name": "The individual'\''s full name",
      "email": "The individual'\''s email address",
      "phone": "The individual'\''s phone number",
      "company": "The company the individual is associated with",
      "title": "The individual'\''s job title",
      "linkedin": "LinkedIn URL for the person",
      "website": "Company website URL",
      "location": "The individual'\''s location and/or company location",
      "industry": "Industry the person operates in",
      "github_url": "url for their github profile",
      "github_notes": "Take detailed notes on their github profile."
    }
  }'

Async pattern

For production workflows, use /people-intelligence-async to submit a job and poll for results. This avoids long-lived HTTP connections during deep research runs. The flow is:
  1. SubmitPOST /people-intelligence-async with the same body as the sync endpoint. Response includes a task_id.
  2. PollGET /job-status/{task_id} until status is completed, failed, or cancelled.
  3. Read result — When completed, the full enrichment is in the result field.
The async start endpoint returns uppercase RUNNING. Subsequent /job-status/{task_id} calls return lowercase statuses. charge_amount is returned in cents, not credits.

Polling example

import requests
import time

response = requests.post(
    "https://api.sixtyfour.ai/people-intelligence-async",
    headers={"x-api-key": "YOUR_API_KEY", "Content-Type": "application/json"},
    json={
        "lead_info": {
            "name": "Saarth Shah",
            "title": "CEO & Co-Founder @ Sixtyfour AI",
            "company": "Sixtyfour AI",
            "location": "San Francisco",
            "linkedin": "https://www.linkedin.com/in/saarthshah"
        },
        "struct": {
            "name": "The individual's full name",
            "email": "The individual's email address",
            "phone": "The individual's phone number",
            "company": "The company the individual is associated with",
            "title": "The individual's job title",
            "linkedin": "LinkedIn URL for the person",
            "website": "Company website URL",
            "location": "The individual's location and/or company location",
            "industry": "Industry the person operates in"
        }
    }
)
response.raise_for_status()
task_id = response.json()["task_id"]

while True:
    status = requests.get(
        f"https://api.sixtyfour.ai/job-status/{task_id}",
        headers={"x-api-key": "YOUR_API_KEY"}
    ).json()

    if status["status"] == "completed":
        results = status["result"]
        break
    if status["status"] in ("failed", "cancelled"):
        raise RuntimeError(f"Job {status['status']}: {status.get('error', 'Unknown error')}")

    time.sleep(10)