Enrich Contacts

Find work emails, personal emails and phone numbers with POST /v1/enrich/email and POST /v1/enrich/phone.

POST https://api.jobspipe.dev/v1/enrich/email
POST https://api.jobspipe.dev/v1/enrich/phone

Given up to 100 people, each named by a LinkedIn profile URL or by full name and company domain, returns a verified work email, a personal email or a phone number for each one found. You pay only for contacts found: a miss costs nothing, and a contact your account revealed before comes back free. Requires authentication.

Try it live in the API Explorer.

Request

The body is a JSON object with an items array of 1 to 100 people. Each item needs linkedin_url, or full_name and domain.

FieldTypeDescription
linkedin_urlstringThe person's LinkedIn profile URL. Needed to find a phone or a personal email.
full_namestringThe person's full name. Send it with domain.
domainstringThe company's website domain, e.g. acme.com. Send it with full_name.
typestringEmail only. work (default) or personal. Phone items take no type.

A name and domain item can find a work email only: for a phone or a personal email it comes back not_found, free.

Send an optional Idempotency-Key header (a UUID, say) to make a request safe to retry. A retry with the same key within 24 hours replays the first response, with an Idempotent-Replayed: true header, and charges nothing. A duplicate sent while the first is still running gets 409 with {"error": "idempotency_conflict"}. A 402 (balance too low) and that 409 are never replayed, so the same key works again once you add credits or the first request returns.

curl https://api.jobspipe.dev/v1/enrich/email \
  -H "Authorization: Bearer jp_live_your_key_here" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6f1c2a4e-3b7d-4e8a-9c1f-0d2b5e7a9c31" \
  -d '{
    "items": [
      { "linkedin_url": "https://www.linkedin.com/in/jane-doe" },
      { "full_name": "Sam Lee", "domain": "acme.com" },
      { "linkedin_url": "https://www.linkedin.com/in/alex-kim", "type": "personal" }
    ]
  }'
import requests

resp = requests.post(
    "https://api.jobspipe.dev/v1/enrich/phone",
    headers={"Authorization": "Bearer jp_live_your_key_here"},
    json={"items": [{"linkedin_url": "https://www.linkedin.com/in/jane-doe"}]},
)
resp.raise_for_status()
body = resp.json()
for r in body["results"]:
    print(r["index"], r["status"], r["value"])
print("credits charged:", body["credits_charged"])
const resp = await fetch("https://api.jobspipe.dev/v1/enrich/email", {
  method: "POST",
  headers: {
    Authorization: "Bearer jp_live_your_key_here",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    items: [{ full_name: "Sam Lee", domain: "acme.com" }],
  }),
});
const body = await resp.json();
for (const r of body.results) {
  console.log(r.index, r.status, r.value);
}

Response

A 200 response has one result per item, in the order sent:

  • results - each with index (the item's position, from 0), status, type (work, personal or phone), value (the email or phone, or null) and credits (what this item cost).
  • found - items with a value (enriched or cached).
  • credits_charged - what the whole batch cost. One charge covers only the found items.
StatusMeaningCost
enrichedFound now.The contact's price
cachedYour account revealed this contact before.Free
not_foundNo contact found for this person.Free
insufficient_creditsYour balance ran out before this item; it was not looked up.Free
rate_limitedLookups are busy; try this item again shortly.Free
errorThe lookup failed; try again.Free
200 OK
{
  "results": [
    { "index": 0, "status": "enriched", "type": "work", "value": "jane.doe@acme.com", "credits": 15 },
    { "index": 1, "status": "not_found", "type": "work", "value": null, "credits": 0 },
    { "index": 2, "status": "cached", "type": "personal", "value": "alex.kim@gmail.com", "credits": 0 }
  ],
  "found": 2,
  "credits_charged": 15
}

Pricing

ContactCredits per contact found
Work email15
Personal email10
Phone100

A contact your account already revealed, in the API or the dashboard, is free every time it comes back. When your balance covers only part of a batch, the items it does not cover come back insufficient_credits and cost nothing. See plans.

Status codes

StatusMeaning
200Success, with a status per item
400No items, more than 100 items, an item with neither linkedin_url nor full_name and domain, or an unknown type
401Missing or invalid API key
402Your balance does not cover even one contact ({"error": "insufficient_credits", "message", "upgrade_url"})
409A request with the same Idempotency-Key is still running
429Per-second rate limit exceeded

See the error reference for handling guidance.

On this page