Bulk Person Enrichment API

The endpoint for the bulk enrichment api is /v5/person/bulk

Bulk Endpoint

Up to 100 persons can be enriched in a single HTTP request using the /v5/person/bulk endpoint. Enrichments executed against the bulk endpoint must be a POST. The request body of a bulk enrichment request must contain an array, requests, with 1-100 individual request objects, each containing an object params of request parameters. A JSON schema describing the structure of a /v5/person/bulk enrichment response can be found here.

import json

# See https://github.com/peopledatalabs/peopledatalabs-python
from peopledatalabs import PDLPY

# Create a client, specifying an API key
client = PDLPY(
    api_key="YOUR API KEY",
)

data = {
   "requests": [
       {
           "params": {
               "profile": ["linkedin.com/in/seanthorne"]
           }
       },
       {
           "params": {
               "profile": ["linkedin.com/in/randrewn"]
           }
       }
   ]
}

json_responses = client.person.bulk(**data).json()

for response in json_responses:
  if response["status"] == 200:

    record = response['data']

    print(
      record['work_email'],
      record['full_name'],
      record['job_title'],
      record['job_company_name']
    )

    print(f"successfully enriched profile with pdl data")

    # Save enrichment data to json file
    with open("my_pdl_enrichment.jsonl", "w") as out:
      out.write(json.dumps(record) + "\n")
  else:
    print("Enrichment unsuccessful. See error and try again.")
    print("error:", response)
curl -X POST "https://api.peopledatalabs.com/v5/person/bulk" \
-H 'Content-Type: application/json' \
-H 'X-Api-Key: XXX' \
-d ' {
    "requests": [
        {
            "params": {
                "profile": ["linkedin.com/in/seanthorne"],
                "location": ["SF Bay Area"],
                "name": ["Sean F. Thorne"]
            }
        },
        {
            "params": {
                "profile": ["https://www.linkedin.com/in/haydenconrad/"],
                "first_name": "Hayden",
                "last_name": "Conrad"
            }
        }
    ]
}'
// See https://github.com/peopledatalabs/peopledatalabs-js
import PDLJS from 'peopledatalabs';

const PDLJSClient = new PDLJS({ apiKey: "YOUR API KEY" });

const records = {
  requests: [
    {
      params: {
        profile: ['linkedin.com/in/seanthorne']
      }
    },
    {
      params: {
        profile: ['linkedin.com/in/randrewn']
      }
    }
  ]
};

PDLJSClient.person.bulk(records).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});
import requests
import json

API_KEY = # Enter your API Key here

headers = {
   'X-Api-Key': API_KEY,
   'Content-Type': 'application/json',
}
 
data = {
   "requests": [
       {
           "params": {
               "profile": ["linkedin.com/in/seanthorne"]
           }
       },
       {
           "params": {
               "profile": ["linkedin.com/in/randrewn"]
           }
       }
   ]
}
json_responses = requests.post(
   'https://api.peopledatalabs.com/v5/person/bulk',
   headers=headers,
   json=data
).json()
 
for response in json_responses:
  if response["status"] == 200:

    record = response['data']

    print(
      record['work_email'],
      record['full_name'],
      record['job_title'],
      record['job_company_name']
    )

    print(f"successfully enriched profile with pdl data")

    # Save enrichment data to json file
    with open("my_pdl_enrichment.jsonl", "w") as out:
      out.write(json.dumps(record) + "\n")
  else:
    print("Enrichment unsuccessful. See error and try again.")
    print("error:", response)

Responses are returned as an array of response objects.

[
    {"status": 200, "likelihood": 10, "data": ...},
    {"status": 200, "likelihood": 10, "data": ...}
]

Tracking Responses

Response objects are always returned in the same order as they were defined in the requests array. However you can also add an object metadata to each request, containing any information specific to that request. If metadata is defined in a request object, it will be returned, unchanged in that request's corresponding response object:

import json

# See https://github.com/peopledatalabs/peopledatalabs-python
from peopledatalabs import PDLPY

# Create a client, specifying an API key
client = PDLPY(
    api_key="YOUR API KEY",
)

data = {
    "requests": [
        {
            "metadata": {
                "user_id": "123"
            },
            "params": {
                "profile": ["linkedin.com/in/seanthorne"],
                "location": ["SF Bay Area"],
                "name": ["Sean F. Thorne"]
            }
        },
        {
            "metadata": {
                "user_id": "345"
            },
            "params": {
                "profile": ["https://www.linkedin.com/in/haydenconrad/"],
                "first_name": "Hayden",
                "last_name": "Conrad"
            }
        }
    ]
}

json_response = client.person.bulk(**data).json()

print(json.dumps(json_response))
curl -X POST "https://api.peopledatalabs.com/v5/person/bulk" \
-H 'Content-Type: application/json' \
-H 'X-Api-Key: XXX' \
-d ' {
    "requests": [
        {
            "metadata": {
                "user_id": "123"
            },
            "params": {
                "profile": ["linkedin.com/in/seanthorne"],
                "location": ["SF Bay Area"],
                "name": ["Sean F. Thorne"]
            }
        },
        {
            "metadata": {
                "user_id": "345"
            },
            "params": {
                "profile": ["https://www.linkedin.com/in/haydenconrad/"],
                "first_name": "Hayden",
                "last_name": "Conrad"
            }
        }
    ]
}'
// See https://github.com/peopledatalabs/peopledatalabs-js
import PDLJS from 'peopledatalabs';

const PDLJSClient = new PDLJS({ apiKey: "YOUR API KEY" });

const records = {
  requests: [
    {
      metadata: {
        user_id: "123"
      },
      params: {
        profile: ['linkedin.com/in/seanthorne'],
            location: "SF Bay Area",
            name: "Sean F Thorne"
      }
    },
    {
      metadata: {
        user_id: "345"
      },
      params: {
        profile: ["https://www.linkedin.com/in/haydenconrad/"],
        first_name: "Hayden",
        last_name: "Conrad"
      }
    }
  ]
};

PDLJSClient.person.bulk(records).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});
import requests
import json

headers = {
    'Content-Type': 'application/json',
    'X-api-key': #YOURAPIKEY
}

data = {
    "requests": [
        {
            "metadata": {
                "user_id": "123"
            },
            "params": {
                "profile": ["linkedin.com/in/seanthorne"],
                "location": ["SF Bay Area"],
                "name": ["Sean F. Thorne"]
            }
        },
        {
            "metadata": {
                "user_id": "345"
            },
            "params": {
                "profile": ["https://www.linkedin.com/in/haydenconrad/"],
                "first_name": "Hayden",
                "last_name": "Conrad"
            }
        }
    ]
}

json_response = requests.post(
  'https://api.peopledatalabs.com/v5/person/bulk',
  headers=headers,
  json=data
).json()

print(json.dumps(json_response))
[
    {"metadata": {"user_id": "123"}, "status": 200, "likelihood": 10, "data": ...},
    {"metadata": {"user_id": "345"}, "status": 200, "likelihood": 10, "data": ...}
]

Any of the response filtering or formatting params documented in the Parameters section can be defined globally for all request objects:

import json

# See https://github.com/peopledatalabs/peopledatalabs-python
from peopledatalabs import PDLPY

# Create a client, specifying an API key
client = PDLPY(
    api_key="YOUR API KEY",
)

data = {
    "required": "emails AND profiles",
    "requests": [
        {
            "params": {
                "profile": ["linkedin.com/in/seanthorne"],
                "location": ["SF Bay Area"],
                "name": ["Sean F. Thorne"]
            }
        },
        {
            "params": {
                "profile": ["https://www.linkedin.com/in/haydenconrad/"],
                "first_name": "Hayden",
                "last_name": "Conrad"
            }
        }
    ]
}

json_response = client.person.bulk(**data).json()

print(json.dumps(json_response))
curl -X POST "https://api.peopledatalabs.com/v5/person/bulk" \
-H 'Content-Type: application/json' \
-H 'X-Api-Key: XXX' \
-d ' {
    "required": "emails AND profiles",
    "requests": [
        {
            "params": {
                "profile": ["linkedin.com/in/seanthorne"],
                "location": ["SF Bay Area"],
                "name": ["Sean F. Thorne"]
            }
        },
        {
            "params": {
                "profile": ["https://www.linkedin.com/in/haydenconrad/"],
                "first_name": "Hayden",
                "last_name": "Conrad"
            }
        }
    ]
}'
// See https://github.com/peopledatalabs/peopledatalabs-js
import PDLJS from 'peopledatalabs';

const PDLJSClient = new PDLJS({ apiKey: "YOUR API KEY" });

const records = {
  required: "emails AND profiles",
  requests: [
    {
      params: {
        profile: ['linkedin.com/in/seanthorne'],
            location: "SF Bay Area",
            name: "Sean F Thorne"
      }
    },
    {
      params: {
        profile: ["https://www.linkedin.com/in/haydenconrad/"],
        first_name: "Hayden",
        last_name: "Conrad"
      }
    }
  ]
};

PDLJSClient.person.bulk(records).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});
import requests
import json

headers = {
    'Content-Type': 'application/json',
    'X-api-key': #YOURAPIKEY
}

data = {
    "required": "emails AND profiles",
    "requests": [
        {
            "params": {
                "profile": ["linkedin.com/in/seanthorne"],
                "location": ["SF Bay Area"],
                "name": ["Sean F. Thorne"]
            }
        },
        {
            "params": {
                "profile": ["https://www.linkedin.com/in/haydenconrad/"],
                "first_name": "Hayden",
                "last_name": "Conrad"
            }
        }
    ]
}

json_response = requests.post(
  'https://api.peopledatalabs.com/v5/person/bulk',
  headers=headers,
  json=data
).json()

print(json.dumps(json_response))

Response filtering/formatting params defined locally in an individual request object will override those defined in the request body root.

Any response object in a /v5/person/bulk response will either have a status code of 200, 404, or 400. Any valid /v5/person/bulk will return with a status code of 200.

The number of remaining enrichment matches in your account will be deducted by the number of 200 responses in a bulk enrichment request as though each request was made individually.

Any malformed, unauthenticated or throttled request will return errors in the same format as documented in the errors section.

import json

# See https://github.com/peopledatalabs/peopledatalabs-python
from peopledatalabs import PDLPY

# Create a client, specifying an API key
client = PDLPY(
    api_key="YOUR API KEY",
)

data = {"required": "names"}

try:
    json_response = client.person.bulk(**data).json()
except Exception as err:
    print(err);
curl -X POST "https://api.peopledatalabs.com/v5/person/bulk" \
-H 'Content-Type: application/json' \
-H 'X-Api-Key: XXX' \
-d ' {
    "required": "names"
}'
// See https://github.com/peopledatalabs/peopledatalabs-js
import PDLJS from 'peopledatalabs';

const PDLJSClient = new PDLJS({ apiKey: "YOUR API KEY" });

const records = {
  required: "names"
};

PDLJSClient.person.bulk(records).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});
import requests
import json

headers = {
    'Content-Type': 'application/json',
    'X-api-key': #YOURAPIKEY
}

data = {"required": "names"}

response = requests.post(
  'https://api.peopledatalabs.com/v5/person/bulk',
  headers=headers,
  json=data
)
{
    "status": 400,
    "error": {
        "type": "invalid_request_error",
        "message": "Request object must contain `requests` field"
    }
} 

Bulk Request Limitations

Currently, due to infrastructure constraints, there is a 1MB limit on API responses. Most bulk requests will not hit this limit, however an 80-100 record bulk request that returns rich records may approach or go over this limitation.

There are a few ways to ensure you never run into this limitation:

  1. Add the Accept-Encoding: gzip header to your request headers. The responses will be gzip compressed and around five times smaller.

  2. Use the data_include feature to only return fields that you need.

  3. Enrich less records per call. Enriching around 50 records instead of 100 should bypass this limitation.

Example Response

200 Response Fields

Note that the bulk response is a JSON Array of objects with the following fields:

Field NameTypeDescription
dataobjectThe person response object
statusintegerHTTP Status Code
likelihoodintegerLikelihood Score
metadataobjectAny metadata that the user included in the request*

Note - metadata is on a per-request basis and generally should be used to connect requests to responses within a call. See this section for more information.

[
{
  "status": 200,
  "likelihood": 10,
  "data": {
    "id": "qEnOZ5Oh0poWnQ1luFBfVw_0000",
    "full_name": "sean thorne",
    "first_name": "sean",
    "middle_initial": "f",
    "middle_name": "fong",
    "last_name": "thorne",
    "gender": "male",
    "birth_year": "1990",
    "birth_date": null,
    "linkedin_url": "linkedin.com/in/seanthorne",
    "linkedin_username": "seanthorne",
    "linkedin_id": "145991517",
    "facebook_url": "facebook.com/deseanthorne",
    "facebook_username": "deseanthorne",
    "facebook_id": "1089351304",
    "twitter_url": "twitter.com/seanthorne5",
    "twitter_username": "seanthorne5",
    "github_url": null,
    "github_username": null,
    "work_email": "[email protected]",
    "personal_emails": ["[email protected]"],
    "mobile_phone": "+14155688413",
    "industry": "computer software",
    "job_title": "co-founder and chief executive officer",
    "job_title_role": null,
    "job_title_sub_role": null,
    "job_title_levels": [
      "owner",
      "cxo"
    ],
    "job_company_id": "peopledatalabs",
    "job_company_name": "people data labs",
    "job_company_website": "peopledatalabs.com",
    "job_company_size": "11-50",
    "job_company_founded": "2015",
    "job_company_industry": "computer software",
    "job_company_linkedin_url": "linkedin.com/company/peopledatalabs",
    "job_company_linkedin_id": "18170482",
    "job_company_facebook_url": "facebook.com/peopledatalabs",
    "job_company_twitter_url": "twitter.com/peopledatalabs",
    "job_company_location_name": "san francisco, california, united states",
    "job_company_location_locality": "san francisco",
    "job_company_location_metro": "san francisco, california",
    "job_company_location_region": "california",
    "job_company_location_geo": "37.77,-122.41",
    "job_company_location_street_address": "455 market street",
    "job_company_location_address_line_2": "suite 1670",
    "job_company_location_postal_code": "94105",
    "job_company_location_country": "united states",
    "job_company_location_continent": "north america",
    "job_last_updated": "2020-12-01",
    "job_start_date": "2015-03",
    "location_name": "san francisco, california, united states",
    "location_locality": "san francisco",
    "location_metro": "san francisco, california",
    "location_region": "california",
    "location_country": "united states",
    "location_continent": "north america",
    "location_street_address": null,
    "location_address_line_2": null,
    "location_postal_code": null,
    "location_geo": "37.77,-122.41",
    "location_last_updated": "2020-12-01",
    "phone_numbers": [
      "+14155688413"
    ],
    "emails": [
      {
        "address": "[email protected]",
        "type": null
      },
      {
        "address": "[email protected]",
        "type": "professional"
      },
      {
        "address": "[email protected]",
        "type": "professional"
      },
      {
        "address": "[email protected]",
        "type": "professional"
      },
      {
        "address": "[email protected]",
        "type": "current_professional"
      },
      {
        "address": "[email protected]",
        "type": "current_professional"
      },
      {
        "address": "[email protected]",
        "type": "current_professional"
      }
    ],
    "interests": [
      "location based services",
      "mobile",
      "social media",
      "colleges",
      "university students",
      "consumer internet",
      "college campuses"
    ],
    "skills": [
      "entrepreneurship",
      "start ups",
      "management",
      "public speaking",
      "strategic partnerships",
      "strategy",
      "fundraising",
      "saas",
      "enterprise technology sales",
      "social networking"
    ],
    "location_names": [
      "san francisco, california, united states",
      "albany, california, united states",
      "portland, oregon, united states"
    ],
    "regions": [
      "california, united states",
      "oregon, united states"
    ],
    "countries": [
      "united states"
    ],
    "street_addresses": [],
    "experience": [
      {
        "company": {
          "name": "hallspot",
          "size": "1-10",
          "id": "hallspot",
          "founded": "2013",
          "industry": "computer software",
          "location": {
            "name": "portland, oregon, united states",
            "locality": "portland",
            "region": "oregon",
            "metro": "portland, oregon",
            "country": "united states",
            "continent": "north america",
            "street_address": "1231 northwest hoyt street",
            "address_line_2": "suite 202",
            "postal_code": "97209",
            "geo": "45.52,-122.67"
          },
          "linkedin_url": "linkedin.com/company/hallspot",
          "linkedin_id": "3019184",
          "facebook_url": null,
          "twitter_url": "twitter.com/hallspot",
          "website": "hallspot.com"
        },
        "location_names": [],
        "end_date": "2015-02",
        "start_date": "2012-08",
        "title": {
          "name": "co-founder",
          "role": null,
          "sub_role": null,
          "levels": [
            "owner"
          ]
        },
        "is_primary": false
      },
      {
        "company": {
          "name": "people data labs",
          "size": "11-50",
          "id": "peopledatalabs",
          "founded": "2015",
          "industry": "computer software",
          "location": {
            "name": "san francisco, california, united states",
            "locality": "san francisco",
            "region": "california",
            "metro": "san francisco, california",
            "country": "united states",
            "continent": "north america",
            "street_address": "455 market street",
            "address_line_2": "suite 1670",
            "postal_code": "94105",
            "geo": "37.77,-122.41"
          },
          "linkedin_url": "linkedin.com/company/peopledatalabs",
          "linkedin_id": "18170482",
          "facebook_url": "facebook.com/peopledatalabs",
          "twitter_url": "twitter.com/peopledatalabs",
          "website": "peopledatalabs.com"
        },
        "location_names": [],
        "end_date": null,
        "start_date": "2015-03",
        "title": {
          "name": "co-founder and chief executive officer",
          "role": null,
          "sub_role": null,
          "levels": [
            "owner",
            "cxo"
          ]
        },
        "is_primary": true
      }
    ],
    "education": [
      {
        "school": {
          "name": "university of oregon",
          "type": "post-secondary institution",
          "id": "64LkgfdwWYkCC2TjbldMDQ_0",
          "location": {
            "name": "eugene, oregon, united states",
            "locality": "eugene",
            "region": "oregon",
            "country": "united states",
            "continent": "north america"
          },
          "linkedin_url": "linkedin.com/school/university-of-oregon",
          "facebook_url": "facebook.com/universityoforegon",
          "twitter_url": "twitter.com/uoregon",
          "linkedin_id": "19207",
          "website": "uoregon.edu",
          "domain": "uoregon.edu"
        },
        "end_date": "2014",
        "start_date": "2010",
        "gpa": null,
        "degrees": [],
        "majors": [
          "entrepreneurship"
        ],
        "minors": []
      }
    ],
    "profiles": [
      {
        "network": "linkedin",
        "id": "145991517",
        "url": "linkedin.com/in/seanthorne",
        "username": "seanthorne"
      },
      {
        "network": "facebook",
        "id": "1089351304",
        "url": "facebook.com/deseanthorne",
        "username": "deseanthorne"
      },
      {
        "network": "twitter",
        "id": null,
        "url": "twitter.com/seanthorne5",
        "username": "seanthorne5"
      },
      {
        "network": "linkedin",
        "id": null,
        "url": "linkedin.com/in/sean-thorne-9b9a8540",
        "username": "sean-thorne-9b9a8540"
      },
      {
        "network": "angellist",
        "id": null,
        "url": "angel.co/deseanthorne",
        "username": "deseanthorne"
      },
      {
        "network": "gravatar",
        "id": null,
        "url": "gravatar.com/seanthorne5",
        "username": "seanthorne5"
      },
      {
        "network": "klout",
        "id": null,
        "url": "klout.com/seanthorne5",
        "username": "seanthorne5"
      },
      {
        "network": "aboutme",
        "id": null,
        "url": "about.me/sean_thorne",
        "username": "sean_thorne"
      }
    ]
  }
}
]

Did this page help you?