The Person Enrich API takes an identifier you already have — a LinkedIn URL or a business email — and returns a rich professional profile. This page walks you through the API step by step, starting with the simplest possible request and building up to advanced patterns.
Every request goes to the same endpoint:
POST https://api.crustdata.com/person/enrich
Replace YOUR_API_KEY in each example with your actual API key. All
requests require the x-api-version: 2025-11-01 header.
Your first enrichment: look up a LinkedIn profile
The simplest enrichment takes a single LinkedIn URL and returns the person’s professional profile. Pass the URL in the professional_network_profile_urls array.
curl --request POST \
--url https://api.crustdata.com/person/enrich \
--header 'authorization: Bearer YOUR_API_KEY' \
--header 'content-type: application/json' \
--header 'x-api-version: 2025-11-01' \
--data '{
"professional_network_profile_urls": [
"https://www.linkedin.com/in/abhilashchowdhary/"
]
}'
Response trimmed for clarity.
Understanding the response
The Enrich API returns an array — one entry per identifier you submitted. Each entry has three fields:
matched_on — the identifier you submitted (the LinkedIn URL or email).
match_type — either professional_network_profile_url or business_email, telling you which identifier type was used.
matches — an array of candidate profiles. Each match includes a confidence_score (0 to 1) and the full person_data object.
For LinkedIn URL lookups, you will typically get exactly one match with a confidence_score of 1.0, because the URL is a direct identifier.
What is inside person_data?
The person_data object contains several sections:
| Section | Key fields | Description |
|---|
basic_profile | name, headline, current_title, summary, location, languages | Core identity and role information |
professional_network | connections, followers, joined_date, verifications, open_to_cards, profile_picture_permalink | LinkedIn-specific metadata and network stats |
social_handles | professional_network_identifier.profile_url, professional_network_identifier.member_id | Canonical LinkedIn identifiers for deduplication |
experience | employment_details.current, employment_details.past | Full work history (when available) |
education | schools, all_schools, all_degrees | Education background (when available) |
skills | professional_network_skills | Listed professional skills (when available) |
contact | emails, phone_numbers, websites | Available contact information (when available) |
certifications | name, issuing_organization, issue_date | Professional certifications (when available) |
Reverse lookup: find a person from a business email
You do not always have a LinkedIn URL. If you have a business email, use business_emails to reverse-lookup the person behind the address.
curl --request POST \
--url https://api.crustdata.com/person/enrich \
--header 'authorization: Bearer YOUR_API_KEY' \
--header 'content-type: application/json' \
--header 'x-api-version: 2025-11-01' \
--data '{
"business_emails": ["abhilash@crustdata.com"],
"min_similarity_score": 0.8
}'
Response trimmed for clarity.
How email reverse lookup works
When you submit a business email, the API resolves it to a LinkedIn profile. The response structure is identical to a LinkedIn URL lookup, but match_type is business_email and matched_on shows the email you submitted.
The min_similarity_score parameter controls how strict the matching is. A value of 0.8 means the API only returns matches where it is at least 80% confident the email belongs to the person. Higher values give fewer but more reliable results.
min_similarity_score | When to use |
|---|
0.9 – 1.0 | High-confidence workflows (CRM enrichment, automated pipelines) |
0.7 – 0.8 | Balanced accuracy for most use cases |
0.5 – 0.6 | Exploratory lookups where you will manually verify |
| Not set | Returns all matches regardless of confidence |
Handle no-match results
Not every identifier will resolve to a person. When there is no match, the matches array is empty.
curl --request POST \
--url https://api.crustdata.com/person/enrich \
--header 'authorization: Bearer YOUR_API_KEY' \
--header 'content-type: application/json' \
--header 'x-api-version: 2025-11-01' \
--data '{
"business_emails": ["nonexistent@unknowndomain.com"],
"min_similarity_score": 0.8
}'
You still get a response entry for the identifier — matched_on tells you which input had no match. This makes it easy to track which lookups succeeded and which need a different approach (for example, trying Person Search with the person’s name instead).
Batch enrichment: look up multiple people at once
You can enrich up to 25 identifiers in a single request. The response returns one entry per identifier, in the same order you submitted them.
curl --request POST \
--url https://api.crustdata.com/person/enrich \
--header 'authorization: Bearer YOUR_API_KEY' \
--header 'content-type: application/json' \
--header 'x-api-version: 2025-11-01' \
--data '{
"professional_network_profile_urls": [
"https://www.linkedin.com/in/dvdhsu/",
"https://www.linkedin.com/in/abhilashchowdhary/"
]
}'
Response trimmed for clarity.
Batch enrichment tips
- The maximum batch size is 25 identifiers per request.
- You must use one identifier type per request — either all LinkedIn URLs or all emails, not a mix.
- Each entry in the response corresponds to the input at the same position, so you can match results back to your input list by index.
- If some identifiers fail to match, their
matches array will be empty, but the request still succeeds for the others.
Get fresh data with real-time enrichment
By default, the API returns cached data. If you need the latest information (for example, to detect a recent job change), enable real-time enrichment.
curl --request POST \
--url https://api.crustdata.com/person/enrich \
--header 'authorization: Bearer YOUR_API_KEY' \
--header 'content-type: application/json' \
--header 'x-api-version: 2025-11-01' \
--data '{
"professional_network_profile_urls": [
"https://www.linkedin.com/in/dvdhsu/"
],
"enrich_realtime": true,
"force_fetch": true
}'
Response trimmed for clarity.
Current platform behavior: The enrich_realtime and force_fetch flags
are accepted by the API and documented in the internal
PersonEnrichParsedRequest schema. They are not part of the public
PersonEnrichRequest schema.
The two real-time flags
| Flag | What it does |
|---|
enrich_realtime: true | Fetches fresh data if the cached version is stale. If the cache is recent enough, it may still return cached data. |
force_fetch: true | Always fetches fresh data, regardless of cache age. Must be used with enrich_realtime: true. |
When to use each combination:
| Combination | Use case |
|---|
| Neither flag (default) | Standard enrichment. Fastest response, lowest cost. Good for most workflows. |
enrich_realtime: true | CRM data cleaning. Fetches fresh data only when the cached version is old. |
enrich_realtime: true + force_fetch: true | Verifying a recent job change, pre-meeting research. Always gets the latest data. |
Real-time enrichment takes longer and may cost more credits than cached
lookups. Use it when data freshness matters, not for every request.
Request specific fields
By default, the API returns all available data. If you only need specific information, use the fields parameter to request just what you need.
curl --request POST \
--url https://api.crustdata.com/person/enrich \
--header 'authorization: Bearer YOUR_API_KEY' \
--header 'content-type: application/json' \
--header 'x-api-version: 2025-11-01' \
--data '{
"professional_network_profile_urls": [
"https://www.linkedin.com/in/dvdhsu/"
],
"fields": ["professional_network.joined_date", "professional_network.verifications"]
}'
Response trimmed for clarity.
Available fields
| Field path | What it returns |
|---|
professional_network.joined_date | When the person first created their LinkedIn account |
professional_network.verifications | LinkedIn verification badges (e.g., work email verified) |
certifications | Professional certifications listed on the profile |
This is useful for workflows that need specific metadata — for example, checking how long a prospect has been on LinkedIn, or verifying their identity through work email verification badges.
Preview mode
Use preview: true to get lightweight results before committing credits. This is useful for validating that your identifiers will resolve before running a full enrichment.
curl --request POST \
--url https://api.crustdata.com/person/enrich \
--header 'authorization: Bearer YOUR_API_KEY' \
--header 'content-type: application/json' \
--header 'x-api-version: 2025-11-01' \
--data '{
"professional_network_profile_urls": [
"https://www.linkedin.com/in/dvdhsu/"
],
"preview": true
}'
Preview responses have the same structure but may return fewer fields per profile.
Choosing between LinkedIn URL and email enrichment
Both paths return the same person_data shape, but they work differently.
| LinkedIn URL | Business email |
|---|
| Identifier | professional_network_profile_urls | business_emails |
| Match type | Direct lookup — the URL uniquely identifies a profile | Reverse lookup — the API infers which profile owns the email |
| Confidence | Always 1.0 (exact match) | Varies. Use min_similarity_score to control the threshold |
| Best for | When you have the LinkedIn URL (from search results, CRM data, business cards) | When you only have an email (inbound leads, event attendees, badge scans) |
| Batch limit | Up to 25 URLs per request | Up to 25 emails per request |
Common workflow: Search then Enrich
The most powerful pattern combines Person Search with Person Enrich. Search finds people matching your criteria; Enrich gets the full profile for each match.
Step 1: Search for decision-makers at a target company.
curl --request POST \
--url https://api.crustdata.com/person/search \
--header 'authorization: Bearer YOUR_API_KEY' \
--header 'content-type: application/json' \
--header 'x-api-version: 2025-11-01' \
--data '{
"filters": {
"op": "and",
"conditions": [
{
"field": "experience.employment_details.current.company_name",
"type": "in",
"value": ["Retool"]
},
{
"field": "experience.employment_details.current.title",
"type": "(.)",
"value": "VP|Director|Head of"
}
]
},
"limit": 5
}'
Step 2: Take the LinkedIn URLs from the search results and enrich them for full profiles.
curl --request POST \
--url https://api.crustdata.com/person/enrich \
--header 'authorization: Bearer YOUR_API_KEY' \
--header 'content-type: application/json' \
--header 'x-api-version: 2025-11-01' \
--data '{
"professional_network_profile_urls": [
"https://www.linkedin.com/in/dvdhsu/",
"https://www.linkedin.com/in/abhilashchowdhary/"
]
}'
This two-step pattern is the foundation for most sales, recruiting, and research workflows. Search narrows the universe; Enrich fills in the details.
Request parameter reference
| Parameter | Type | Required | Default | Description |
|---|
professional_network_profile_urls | string[] | One of professional_network_profile_urls or business_emails | — | LinkedIn profile URLs to enrich. Max 25. |
business_emails | string[] | One of professional_network_profile_urls or business_emails | — | Business emails for reverse lookup. Max 25. |
fields | string[] | No | All fields | Specific field paths to return (e.g., professional_network.joined_date). |
min_similarity_score | number (0–1) | No | None | Minimum confidence threshold for email reverse lookup matches. |
Current platform behavior (not in public PersonEnrichRequest schema):
The following parameters are accepted by the API but are documented in the
internal PersonEnrichParsedRequest schema only.
| enrich_realtime | boolean | No | false | Fetch fresh data if cached version is stale. |
| force_fetch | boolean | No | false | Always fetch fresh data. Requires enrich_realtime: true. |
| preview | boolean | No | false | Return lightweight preview results. |
Response fields reference
Each item in the response array contains:
| Field | Type | Description |
|---|
matched_on | string | The input identifier (LinkedIn URL or email) |
match_type | string | professional_network_profile_url or business_email |
matches | array | Array of candidate matches (may be empty for no-match) |
matches[].confidence_score | number | 0 to 1. How confident the match is. 1.0 = exact match. |
matches[].person_data | object | Full enriched profile (see table below) |
Person data sections
| Section | Key fields | Description |
|---|
basic_profile | name, pronoun, headline, current_title, summary, location, languages, last_updated | Core identity and role |
professional_network | profile_picture_permalink, connections, followers, joined_date, verifications, open_to_cards | LinkedIn-specific metadata |
social_handles | professional_network_identifier.profile_url, professional_network_identifier.member_id, twitter_identifier.slug | Canonical social identifiers |
experience | employment_details.current[], employment_details.past[] | Full employment history |
education | schools[], all_schools[], all_degrees[] | Education background |
skills | professional_network_skills[] | Professional skills |
contact | emails[], phone_numbers[], websites[] | Contact information |
certifications | name, issuing_organization, issue_date, credential_url | Professional certifications |
metadata | last_scraped_source, updated_at | Data freshness timestamps |
What to do next
- Search first, then enrich — use Person Search to find people by name, title, company, or location, then enrich the results.
- See more examples — browse person examples for ready-to-copy patterns.
- Read the overview — see Person Overview for a high-level guide to choosing between search and enrich.
- Check the API reference — see Enrich person API reference for the full schema.