# Pipl Search API Documentation Portal > Welcome to the Pipl Search API Documentation Portal. You'll find comprehensive guides and documentation to help you start working with Pipl Search as quickly as possible. This file contains all documentation content in a single document following the llmstxt.org standard. ## Data Sources Pipl includes more than 3 billion online identities cross-referenced from more than 25 billion individual records. Our search platform gathers data from sources such as public records, business listings, marketing lists, phone directories, and crowd-sourced information. Pipl also extracts facts and relevant information from web documents, personal profiles, blogs, news articles, and publications (see [PiplBot](https://pipl.com/bot)). Data gathered from all sources is cleansed, merged, and clustered to create more than three billion detailed online identities. For each query, Pipl searches for results across millions of data sources. Some sources that are no longer available online can be found in our API's "Deep Web Archives". This page describes our sources and provides examples of sources we use. This list is not exhaustive. ## Data Source Categories We categorize data sources into one of 10 categories based on the type of data they contain. You can see the category of each source in the [Source](/reference/source) object in API responses. Below is the list of categories and a few examples of the websites you'll find in each: | **Category** | **Examples** | |-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Personal Profiles** | facebook.com pinterest.com last.fm | | **Professional & Business** | linkedin.com spoke.com zoominfo.com | | **Contact Details** | addresses.com anywho.com | | **Media** | picasa.com flickr.com youtube.com | | **Background Reports** | peoplefinders.com intelius.com peoplesmart.com | | **Public Records** | bop.gov archives.com ancestry.com | | **Publications** | uspto.gov portal.acm.org scirus.com | | **School & Classmates** | classmates.com reunion.com schoolbank.nl | | **Email Address** | intelius.com spokeo.com | | **Web Pages** | Default category. This includes data sources that don't match any of the above categories. | ## Sample Data Sources | # | Domain | Name | | :---- | :------------------------------------------------------------------------------------------ | :---------------------------------------------------- | | **1** | facebook.com | Personal Web Profile - Facebook | | **2** | amazon.com | Customer Profile - Amazon.com | | **3** | linkedin.com | Professional Profile & Networking - LinkedIn | | **4** | instagram | Photo Sharing Profile - Instagram.com | | **5** | tiktok | Video-sharing app | | **6** | twitter.com | Personal Profile - Twitter | | **7** | groups.google.com | Messages - Google Groups | | **8** | video.google.com | Video - YouTube | | **9** | youtube.com | Personal Profile - YouTube | | **10** | home.live.com | Window Live Profile - Windows Live | | **11** | ebay.com | Buyer, Seller Profile - eBay | | **12** | pinterest.com | Virtual Pinboard - Pinterest | | **13** | imgur | Image Sharing Personal Profile - Imgur | | **14** | amazon.co.uk | Wish Lists - Amazon (UK) | | **15** | amazon.ca | Wish Lists - Amazon (Canada) | | **16** | skype | Personal Profiles - Skype | | **17** | myspace.com | Personal Web Space - MySpace | | **18** | github | Open Source Collaboration - Github | | **19** | reddit.com | Personal Profile - Reddit | | **20** | yelp | Business Reviews - Yelp | | **21** | tripadvisor.com | Personal Profile - TripAdvisor | | **22** | imdb.com | Actor, Director, Producers Profile - IMDB | | **23** | vimeo.com | Personal Profile - Vimeo | | **24** | vk.com | Personal Profile - VK | | **25** | Academia | Scholar/Student Profile - Academia.edu | | **26** | wikipedia.org | The Free Encyclopedia - Wikipedia | | **27** | flickr.com | Online Photo Album - Flickr | | **28** | en.gravatar.com | Globally Recognized Avatars - Gravatar | | **29** | picasaweb.google.com | Web Albums - Picasa | | **30** | tumblr.com | Microblogging - Tumbler | | **31** | vids.myspace.com | Videos - MySpace | | **32** | tagged.com | Personal Profile - Tagged | | **33** | arin.net | American Internet Registry - ARIN | | **34** | ratemyteachers.com | Teachers Profile - RateMyTeachers | | **35** | plaxo.com | Online Address Book - Plaxo | | **36** | peoplesmart.com | Professional Listings - PeopleSmart | | **37** | infobel.com | Phone Directory - Infobel France | | **38** | nasza-klasa.pl | Personal Profile - Nasza-Klasa | | **39** | uspto.gov | Patent - US Patent & Trademark Office | | **40** | vitals.rootsweb.com | California Death Records - RootsWeb | | **41** | findagrave.com | Non-Famous Grave Record - FindAGrave | | **42** | findmypast.co.uk | UK family history records - Findmypast.co.uk | | **43** | instantcheckmate.com | Check Criminal Records Online - Instant Check Mate | | **44** | last.fm | Personal Music Profile - Last.fm | | **45** | grono.net | Profiles - Grono | | **46** | ratemyprofessors.com | Professors Profile - RateMyProfessor | | **47** | xanga.com | Personal Web Profile - Xanga | | **48** | gaiaonline.com | Virtual World Personal Profile - Gaia Online | | **49** | meetup.com | Member Profile - Meetup | | **50** | en.netlog.com | Personal Profile - Netlog | | **51** | webshots.com | Member's Profile - Webshots.com | | **52** | scribd.com | Sharing Community Member Profile - Scribd.com | | **53** | stumbleupon.com | Web Recommendations Personal Profile - StumbleUpon | | **54** | date.com | Personal Profile - Date.com | | **55** | datehookup.com | Dating Person Record - DateHookUp | | **56** | deviantart.com | Community of Artists and Art Devoted - DeviantArt | | **57** | behance.net | People - Behance Network | | **58** | wayn.com | Travelers Profile - Wayn | | **59** | soundcloud.com | Audio Platform Personal Profile - SoundCloud | | **60** | ustream.tv | Personal Profile - Ustream.TV | | **61** | dailymotion.com | Videos Community Personal Profile - Dailymotion | | **62** | qik.com | Personal Profile- Qik | | **63** | goodreads.com | Book Reading List & Profile - Goodreads | | **64** | plurk.com | Member Profile - Plurk | | **65** | twicsy.com | Twitter Pic Trends and Users - Twicsy | | **66** | bebo.com | Personal Profile - Bebo | | **67** | photobucket.com | Photo & Video Sharing - Photobucket | | **68** | metacafe.com | User Profiles - Metacafe | | **69** | club.ign.com | Personal Profile - IGN | | **70** | stickam.com | Photos and Personal Profile - Stickam | | **71** | break.com | Personal Profile - Break.com | | **72** | pbase.com | Member's Profile - PBase | | **73** | digg.com | Latest News Headlines, Videos and Images - Digg | | **74** | zedge.net | Mobile Entertainment - Zedge | | **75** | hubpages.com | Personal Profile - HubPages | | **76** | it.toolbox.com | IT Community Profile- ToolBox | | **77** | fotolog.com | Personal profile - Fotolog | | **78** | kongregate.com | Gamer's Profile - Kongregate | | **79** | taringa.net | Personal Profile - Taringa | | **80** | videojug.com | Video Sharing - VideoJug | | **81** | martindale.com | Law Professional Profile - LexisNexis | | **82** | strategis.ic.gc.ca | Corporation Canada - Strategis Canada | | **83** | avvo.com | Attorney Rating - Avvo | | **84** | zoominfo.com | Web Extracted Biography - ZoomInfo | | **85** | trulia.com | Real Estate Professional Profile - Trulia | | **86** | dirigeant.societe.com | Business Leaders Profiles - Dirigeant | | **87** | 118218.fr | White Pages - L'annuaire téléphonique en ligne | | **88** | paginebianche.it | White Pages - Paginebianche.it | | **89** | local.ch | White Pages - Tel.local | | **90** | tel.search.ch | Phone Directory - Switzerland | | **91** | telelistas.net | White Pages - Brazil | | **92** | 11880.com | Telephone Directory - 11880.com | | **93** | nettkatalogen.no | Phone Directory - Nettkatalogen | | **94** | phonebookonline.co.za | The Phone Book - South Africa's White Pages | | **95** | anywho.com | White Pages - AnyWho | | **96** | dasoertliche.de | White Pages - Germany | | **97** | canada411.ca | Personal Records - Canada411 | | **98** | whitepages.be | Phone Directory - WhitePages Belgium | | **99** | extrakoll.se | White Pages Swedan - Extrakoll | | **100** | 1881.no | Personal Contact Information - 1881.no | | **101** | hi5.com | Social Entertainment Personal Profile - hi5 | | **102** | scirus.com | Scientific Publication - Scirus | | **103** | patentstorm.us | Patent Record - PatentStorm | | **104** | deltacomputersystems.com | Case Record - Virtual Courthouse Marion County | | **105** | sos.mo.gov | Registered Agent Record - Missouri Secretary of State | | **106** | index.rbhayes.org | Obituary Index - RB Hayes, OH | | **107** | nationalarchives.gov.uk | Family History - National Archives | | **108** | recorder.maricopa.gov | Public Records - Maricopa County, AZ | | **109** | indianaunclaimed.com | Unclaimed Property - Indiana | | **110** | leeclerk.org | Public Records - Lee County Clerk, FL | | **111** | tax1.co.monmouth.nj.us | Tax Record - Monmouth County, NJ | | **112** | archives.gov | Army Enlistment Records (1938 - 1946) - NARA | | **113** | dockets.justia.com | Case Records - Justia Federal District Court | | **114** | vitals.rootsweb.ancestry.com | Marriage Records - Rootsweb Kentucky | | **115** | 192.com | People In The UK - 192.Com | | **116** | ancestry.com | Message Boards Search - Ancestry | | **117** | familysearch.org | Genealogical Index - Familysearch | | **118** | vampirefreaks.com | User Profile - Vampirefreaks.com | | **119** | fr.netlog.com | Personal Profile - Netlog France | | **120** | upcoming.yahoo.com | Personal Profile - Upcoming Events Yahoo | | **121** | pof.com | User Profile - Plentyoffish | | **122** | disqus.com | Webwide Discussion - Disqus | | **123** | slideshare.net | Slide Sharing - SlideShare | | **124** | veoh.com | Free Videos Watch TV Online - Veoh | | **125** | recruitingblogs.com | Recruiting Community - RecruitingBlogs | | **126** | reverbnation.com | Member's Profile - ReverbNation.com | | **127** | cis.state.mi.us | Insurance Licensee - DLEG, Michigan | | **128** | phonebook.yellowpages.co.za | PhoneBook - South Africa | | **129** | laguia.com.ve | White Pages - Venezuela | | **130** | paginasamarillas.com.pe | White Pages - Peru | | **131** | pagesjaunes.fr | Phone Lookup - Pagesjaunes | | **132** | yellowpages.com | Phone LookUp - YellowPages | | **133** | klicktel.de | Telefonbuch auf klicktel - klicktel | | **134** | reunion.com | School & Contact Details - MyLife.com | | **135** | patents.ic.gc.ca | Patents - Canada Intellectual Property Office | | **136** | ilsos.gov | Public Domain Land Tract Sales Database - Illinois | | **137** | criminalcheck.com | Sex Offenders - CriminalCheck | | **138** | reviewcentre.com | Consumer Review & Price Comparison - Review Centre | | **139** | myyearbook.com | Personal Profile - MeetMe | | **140** | nummar.fo | White Pages - Nummar.fo | | **141** | buttecourt.ca.gov | Court Case Record - Butte County, California | | **142** | co.bibb.ga.us | Property Ownership Inquiry - Bibb County, GA | | **143** | maricopa.gov | Property Records - Maricopa County, Arizona | | **144** | abish.byui.edu | Death Certificates - Special Collections | | **145** | miamidade.gov | Property Tax Information - Miami Dade County, FL | | **146** | genealogy.az.gov | Birth and Death Certificates - Arizona Genealogy | | **147** | friendster.com | Social Networking Profile - Friendster | | **148** | ning.com | Member's Profile - Ning.com | | **149** | medium | Read and Write Things That Matter - Medium | | **150** | strava | Track athletic activity - Strava | | **151** | Infospace | White Pages - Infospace | | **152** | fotki | Online Photo Album - Fotki | | **153** | friend finder | Dating Person Record - Friend Finder | | **154** | sonico.com | Personal Profile - Sonico | | **155** | badoo.com | Photos, Videos & Personal Profile - Badoo | | **156** | flixster.com | Movie Fan Profile - Flixster | | **157** | care2.com | Green Living Community Personal Profile - Care2 | | **158** | irc-galleria.net | Photos And Personal Profile - IRC-Galleria | | **159** | perfspot.com | Personal Profile - PerfSpot | | **160** | skyrock.com | Blogging and Personal Profile - Skyrock.com | --- ## Data Types import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faCheck, faMobile, faPhone, faEnvelope, faUsers, faBirthdayCake, faTransgender, faMapMarker, faBriefcase, faGraduationCap, faCar, faLink, faLanguage, faThumbTack, faExternalLinkSquare, faGlobe, faImage, faRing, faHeartCrack, faSkull, faHouse, faIdCard, faUserDoctor } from '@fortawesome/free-solid-svg-icons'; Our API returns a wide range of data types for each query. These data types contain what we know about the person you’re looking for. Each field comes from our records, our data sources, or is inferred using advanced statistical analysis. If a field is [inferred](inferred-data), it will be marked as inferred. You also can turn off this feature. This page explains the kinds of data you can expect to receive in search results. For a technical explanation of each field, please refer to our [full API reference](/reference/data-fields). Note that a response can be variable and not contain all the data types you might be looking for. To only pay for responses that contain the data types you want, specify match requirements with your [match criteria](/reference/match-criteria). | **Field** | **CONTACT** | **SOCIAL** | **BUSINESS** | | ------------- | ----------- | ---------- | ------------ | | [Name](/reference/name)Current name as well as maiden name and nicknames. | | | | | [Email addresses](/reference/email)Full email addresses. Personal and Work emails. | | | | | [Phones](/reference/phone)Phone numbers. Current and past, mobile and landline , home and office.*CONTACT and SOCIAL keys do not include mobile phones . The BUSINESS key includes all phone types including mobile.* | * | * | | | [Usernames](/reference/username)Usernames in use online by the person. This includes screen names, handles, and nicknames from across the web, social media sites, forums, and more. | | | | | [Images](/reference/image)Image URL of profile images and other images that are related to the person. | | | | | [Age](/reference/date-of-birth)Date of Birth results might be given as a range if the exact date is unknown. | | | | | [Gender](/reference/gender)Male or Female | | | | | [Addresses](/reference/address)Home and work, current and past addresses associated with the person. Includes house number, street, city, ZIP code, state, and country. | | | | | [Career](/reference/job)Current and past jobs. Includes the Period, Job Title and Organization. | | | | | [Education](/reference/education)Degrees from various schools. Includes the Institution, Degree, and the Period. | | | | | [Vehicles](/reference/vehicle)Vehicles owned by the individual. | | | | | [Associates](/reference/relationship)Friends, family, colleagues, social media followers, and other people associated with the person. | | | | | [Language](/reference/language)Languages spoken by the individual. | | | | | [Origin Country](/reference/origin-country)An individual's ancestral country. | | | | | [Related URLs](/reference/url)URL of pages related to the person. Includes social profiles, professional licenses, publications, phone directories, court records, blogs, and much more. | | | | Pipl may also return the following data, some of which appears in [tags](pipl-api-tags)): | **Data** | **CONTACT** | **SOCIAL** | **BUSINESS** | | ------------- | ----------- | ---------- | ------------ | | Marriage and divorce records | | | | | Deceased information | | | | | US properties information such as ownership, APN and tax assessed value | | | | | A Brazilian ID (CPF) for Brazilian individuals | | | | | A National Provider Identity (NPI) for medical professionals | | | | --- ## Frequently Asked Questions ## How do you bill for API usage? Billing is simple. You are charged only when the API response includes a match to your query. A match can be a person or a list of possible persons that meet your criteria (see below). Each API response that meets your criteria will be charged once. Whether the list of possible persons contains 3 or the maximum of 50 people, you are charged only once per response. The cost per match depends on the API plan you use to make the query. > 🚧 Duplicates are charged > > Every query that returns a match is charged. Because Pipl's unique Identity Resolution engine continuously obtains new data, a query performed today might return a different result in an hour, day, or even a month later. For this reason, each query represents a new search. ## Can I define what's considered a match? Yes! You're in complete control of what qualifies as a match for your account. The options you have to define your match are: ### Must-have data types You decide which types of data must be returned to constitute a match. For example, "a match must include an email address or phone number." You'll only receive and be billed for API responses that include your minimum fields—everything else is ignored. You can make the criteria as simple or as complex as needed. For example, you can simply specify that you require email addresses. Or, you can create nested requirements, such as: "name AND address AND (email OR phone)". For more information about constructing match requirements criteria, please visit our [Match Criteria Parameters](/reference/match-criteria) section in the API reference. ### Minimum match Set the minimum confidence level desired for your API response to be considered a match. The default is 0. An API response can include one or both of: - **Person object (definite match)**: This is a single person who is the person you're looking for with all of their information. - **Possible persons (possible match)**: This is a list of people who might be the person you're looking for. Each possible person includes summary data and search pointers for a follow-up search. - You can raise or lower your minimum match to include or exclude possible persons. Setting your minimum match to 1 means only definite matches (person objects) will be returned. ### Minimum probability This parameter allows you to set a minimum confidence level for the data returned in a match. In some cases, we can use statistical models to infer part or all of the data—such as email address or gender—for the person you’re querying. You can raise or lower your minimum probability to include or exclude inferred data. Setting your minimum probability to 1 means no inferred data will be used to determine a match or be included in matches. For more information, please see [Inferred Data]inferred-data). ## How many calls can I make per second? Queries made with live_feeds allow up to 10 asynchronous parallel calls per second. Queries without live_feeds allow up to 20 asynchronous parallel calls per second. You can learn more about this [here](/docs/rate-limiting). If these limits hinder your API usage, you can create custom settings. Please contact your Account Director or Integration Specialist to learn how. ## How fast is the API response time? Our API typically returns results in \<1 second for queries that do not use live_feeds and \<2 seconds for queries with live_feeds. ## Where does Pipl get its data? Pipl gathers data from sources such as public records, business listings, marketing lists, phone directories, and crowd-sourced data. Pipl also extracts facts and other relevant information from web documents, personal profiles, blogs, news articles, and publications. Data gathered from all sources is cleansed, merged, and clustered to create more than three billion detailed online identities. For more information, please see [Data Sources]data-sources). ## How accurate is Pipl's data? In short, very accurate. Pipl combines and cross-references data from more than one million publicly available sources. Although it is difficult to effectively verify the accuracy of each data field in more than 25 billion records, Pipl still delivers higher accuracy than other people-data providers. ## What about privacy? Understanding the potential sensitivity of people's data makes privacy critical for us. The API only provides information already publicly available from free or paid sources. For more information, please see [Pipl's Privacy Center](https://pipl.com/privacy-center). ## Can I add multiple users to my Pipl account? Yes, you can create multiple users for one Pipl account. Simply sign up for an account and invite additional users in your [account area](https://pipl.com/accounts/manage-users/users/). Be sure to set them as administrators to have access to the API keys. ## Can I use MD5 hashes to query the API instead of full email addresses? When information privacy is important, an email address can be sent as an MD5. See the [Email](/reference/email) section in the API reference for instructions on MD5 calculation guidelines. However, we suggest sending the full email address when possible to enhance the value of possible results and inferred data in case we don't have an exact email match. ## Can I use Pipl to query social network services? You can query Pipl using the username, user_id, or URL of the social service. You can search for the username across all social network services or by specifying the specific service with an @service suffix, where "service" is the name of the service. For a list of all the supported social network services, please see [User ID](/reference/user-id) in the API reference. --- ## Inferred Data Our people data is source-validated, meaning that every piece of information originates from records in one or more of our data sources. Full details of these sources are available in the API response. In addition to source-validated data, we offer inferred data. This data might not be validated by a source, but based on our advanced statistical model it is highly likely to be correct. Inferred data is useful when information does not have to be precisely accurate, such as when it's used for marketing purposes. You can set the accuracy level that fits your application or turn this feature off. Note that whenever a data element—or even part of an element is inferred, Pipl clearly marks it as “inferred” so you can easily separate it from source-validated data. Examples of inferred data: - Gender from Name - Location from Phone number - Workplace from Email address You can use the [minimum_probability and infer_persons parameters](/reference/configuration-parameters) to define when the Search API returns inferred data. For more information about inferred data, see [Get data outta thin air](https://pipl.com/resources/blog/data-outta-thin-air). --- ## API Key Security - Best Practices ![](../static/img/api_security_key_theft.jpg 'key_theft.jpg') ## You are responsible for your key protection. Keys are directly connected to your account and accrued usage is charged at the end of each billing cycle. It is imperative to make sure active keys are stored securely on your system with access only to trusted personnel in your organization. _If you suspect your key is compromised, deactivate your key immediately and generate a new key. Please [contact us online](https://pipl.com/customer-support) or contact your Account Manager ASAP. We can help you locate potential culprits._ :::info IP Address Allowlisting Available As a robust security addition, Pipl can provide an allowlist of IP addresses (also known as whitelisting). By providing your list of IPs, we can ensure that only your API keys may be used by the listed IP addresses. Simply [contact us](https://pipl.com/customer-support) to add the IP addresses you require. ::: ## 7 Quick Best Practice DO’s 1. DO deactivate old/unused keys. 2. DO deactivate any key you suspect is compromised IMMEDIATELY from the [API management console](https://search.pipl.com/api/manage/keys/). Then create a new key only if needed. 3. DO review your logs regularly for suspicious key use. 4. DO only use secure methods to send your key such as encrypted email, encrypted documents, encrypted text messages, etc). 5. DO use the only last four digits when communicating your key to appropriate parties. Even if you’re communicating with Pipl, please only use the last 4 characters of your key. ## Best Practice DO NOT’s 1. DO NOT store your API key in public facing source code repositories such as public Github’s. 2. DO NOT store your API key in phone apps, browsers or any software running outside your secure control. It can be cracked using tools such as sniffers, HTML viewers, hex viewers, etc. 3. DO NOT send your full API key in email. 4. DO NOT store your API key in an insecure hard drive or network resource. 5. DO NOT reveal your key to employees or contractors who do not need to know. ## Secondary Best practices DO’s: 1. DO use separate keys for separate functions/business units to isolate & analyze key usage. 2. If building mobile Apps, browser apps and/or uncontrolled software, DO store your key in your network servers and force your remote app to call your server to get the Pipl API data. If the key is always on your server, it’s more secure. 3. DO only expose your key to relevant employees/contractors. Two sets of keys can be created, one for production and one for development/other. 4. DO make sure the admins on your Pipl account are related to your organization and are authorized to handle sensitive data. 5. DO set [quotas on your keys](/docs/rate-limiting#key-quota-limits). 6. DO keep a strong password on your Pipl login account. If they can hack your portal, all of your keys are exposed. 7. DO store your keys on secure devices/servers inside your controlled network with appropriate permissions. 8. DO draft and enforce a key storage policy within your organization. ## Key Attack Vectors - Insecure network handling, lack of HTTPS or using GET for API calls. - Clear text reveal via email or insecure document handling. - Poor application design which reveals your keys over TCP/IP such as phone app or browser. - Employees or contractors leaking keys. --- ## Best Practices By Use Case import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Best Practices by Use Case Pipl Search applies to a variety of use cases. Each use case has unique objectives and requirements, as well as preferred ways of working with the Pipl Search API. This article provides recommendations based on successful approaches for key use cases. This provides a starting point for integration and optimization efforts; adapt it based on your specific goals and requirements. ## Contact Enrichment The contact enrichment use case is using the Pipl Search API to add new data points to an existing profile or contact. New data might include contact information such as phone numbers, email addresses or social media profiles. To return the most relevant results for each contact, limit queries to only those that have the information you need. To do this, [set your match requirements](/reference/match-criteria#match-requirements) appropriately. For example if you are enriching contacts with social media profiles, you can limit the query to only return matches for people that have a social media profile: `match_requirements=social_profiles` Use boolean operators (`OR` and `AND`) to further refine the match requirements. ### Recruiting #### LinkedIn to Contact Information LinkedIn URLs, usernames or UserIDs are often sufficient, on their own, to match to a profile and find contact information. You can also try adding supplementary demographic information such as a name and location (even just a country or country + state). The [sources layer](/reference/know-your-sources) includes tags for professional skills and courses that may be relevant to your application. _Recommended Parameters:_ - `minimum match=1.0` (for LinkedIn alone) or `top_match=true` when including demographic info - `match_requirements= 'phone OR email'` - `live_feeds=false` (except for low volume/throughput) - `show_sources=matching` ```python SearchAPIRequest.set_default_settings(api_key=u'YOURKEY', minimum_match=1.0, match_requirements='phone OR email', live_feeds=False, show_sources='matching') request = SearchAPIRequest(url='https://www.linkedin.com/in/clarkkent') response = request.send() contact_phone_1 = response.person.phones[0].number contact_email_1 = response.person.emails[0].address ``` ```ruby Pipl.configure do |c| c.api_key = 'YOURKEY' c.minimum_match = 1.0 c.match_requirements = 'phone OR email' c.live_feeds = false c.show_sources = 'matching' end response = Pipl::client.search url: 'https://www.linkedin.com/in/clarkkent' contact_phone_1 = response.person.phones[0].number contact_email_1 = response.person.emails[0].address ``` ```java import com.pipl.api.search.SearchAPIRequest; import com.pipl.api.search.SearchAPIResponse; import com.pipl.api.search.SearchConfiguration; SearchConfiguration defaultConfiguration = SearchAPIRequest.getDefaultConfiguration(); defaultConfiguration.apiKey = "YOURKEY"; defaultConfiguration.minimumMatch = 1.0; defaultConfiguration.matchRequirements = "phone OR email"; defaultConfiguration.liveFeeds = false; defaultConfiguration.showSources = "matching"; SearchAPIRequest request = new SearchAPIRequest.Builder() .url("https://www.linkedin.com/in/clarkkent") .configuration(defaultConfiguration) .build(); SearchAPIResponse response = request.send(); String contactPhone1 = response.getPerson().getPhones().get(0).getNumber(); String contactEmail1 = response.getPerson().getEmails().get(0).getAddress(); ``` ```php api_key = "YOURKEY"; PiplApi_SearchAPIRequest::get_default_configuration()->minimum_match = 1.0; PiplApi_SearchAPIRequest::get_default_configuration()->match_requirements = "phone OR email"; PiplApi_SearchAPIRequest::get_default_configuration()->live_feeds = false; PiplApi_SearchAPIRequest::get_default_configuration()->show_sources = "matching"; $request = new PiplApi_SearchAPIRequest(array('url' => 'https://www.linkedin.com/in/clarkkent')); $response = $request->send(); $contact_phone_1 = $response->person->phones[0]->number; $contact_email_1 = $response->person->emails[0]->address; ?> ``` ```csharp using Pipl.APIs.Search; SearchConfiguration defaultConfiguration = SearchAPIRequest.DefaultConfiguration; defaultConfiguration.ApiKey = "YOURKEY"; defaultConfiguration.MinimumMatch = 1.0; defaultConfiguration.MatchRequirements = "phone OR email"; defaultConfiguration.LiveFeeds = false; defaultConfiguration.ShowSources = "matching"; SearchAPIRequest request = new SearchAPIRequest(url: "https://www.linkedin.com/in/clarkkent", requestConfiguration: defaultConfiguration); var response = await request.SendAsync(); string contactPhone1 = response.Person.Phones[0].Number; string contactEmail1 = response.Person.Emails[0].Address; ``` ```bash curl "https://api.pipl.com/search/?key=YOURKEY&minimum_match=1.0&match_requirements=phone%20OR%20email&live_feeds=false&show_sources=matching&url=https%3A%2F%2Fwww.linkedin.com%2Fin%2Fclarkkent" ``` #### Name and Job to Contact Info Searching by job requires using a full person search; See [Searching by job]searching-by-specific-parameters#jobeducation). If you have job history, consider adding multiple jobs to increase the probability that Pipl Search finds the individual. Adding a LinkedIn profile, if you have it, may increase your match rate (see the [Linkedin to Contact Information]best-practices-by-use-case#recruiting) section above). When searching for work email addresses, you can get a greater fill of inferred work emails by reducing the threshold needed for an inferred email to be included in a response (with parameter `minimum_probability`). _Recommended Parameters:_ - `top_match=true` - `match_requirements='phone OR email'` - `live_feeds=false` (except for low volume/throughput) - `minimum_probability=0.6` ```python SearchAPIRequest.set_default_settings(api_key=u'YOURKEY', top_match=True, match_requirements='phone OR email', live_feeds=False, minimum_probability=0.6) ``` ```ruby Pipl.configure do |c| c.api_key = 'YOURKEY' c.top_match = true c.match_requirements = 'phone OR email' c.live_feeds = false c.minimum_probability = 0.6 end ``` ```java import com.pipl.api.search.SearchAPIRequest; import com.pipl.api.search.SearchConfiguration; SearchConfiguration defaultConfiguration = SearchAPIRequest.getDefaultConfiguration(); defaultConfiguration.apiKey = "YOURKEY"; defaultConfiguration.topMatch = true; defaultConfiguration.matchRequirements = "phone OR email"; defaultConfiguration.liveFeeds = false; defaultConfiguration.minimumProbability = 0.6; ``` ```php api_key = "YOURKEY"; PiplApi_SearchAPIRequest::get_default_configuration()->top_match = true; PiplApi_SearchAPIRequest::get_default_configuration()->match_requirements = "phone OR email"; PiplApi_SearchAPIRequest::get_default_configuration()->live_feeds = false; PiplApi_SearchAPIRequest::get_default_configuration()->minimum_probability = 0.6; ?> ``` ```csharp using Pipl.APIs.Search; SearchConfiguration defaultConfiguration = SearchAPIRequest.DefaultConfiguration; defaultConfiguration.ApiKey = "YOURKEY"; defaultConfiguration.TopMatch = true; defaultConfiguration.MatchRequirements = "phone OR email"; defaultConfiguration.LiveFeeds = false; defaultConfiguration.MinimumProbability = 0.6; ``` ```bash # Set these parameters in your API requests: # top_match=true&match_requirements=phone%20OR%20email&live_feeds=false&minimum_probability=0.6 ``` ### Real Estate A common use-case for the Search API in real estate is to find contact or social media information for the owner or resident of an address. To do this, use [the address](/reference/address) and any other information you have on the person as the query input. While a US Address alone meets [the minimum requirements](/reference/request-overview#minimum-requirements) for a query, this type of search will usually return a [possible person response](/reference/response-types#possible-person), since there are almost always multiple people connected to a single address (multiple residents, previous residents, owner and renter). Include a name and/or other information to help the API determine which of those connected people is the individual you are searching for. To ensure the API reads the address correctly, we recommend splitting it into individual components (country, state, city, zip, street & house) to send to the API. The API can also take an address in raw form (the full address in a single input parameter), but you will need to verify that our API is parsing correctly for your address format. For US addresses, [the source layer](/reference/know-your-sources) includes [tags]pipl-api-tags) for home ownership (apn), most recent sale, and home type. This information can be used to verify current home ownership. Search for tags with the classifications 'apn', 'last_sale_date' and 'type'. See [popular tag classifications for more details]pipl-api-tags#popular-tag-classifications). _Recommended Parameters:_ - `top_match=true` - `match_requirements= 'phone OR email OR social_profiles'` - `show_sources=all` - `live_feeds=true`(depends on expected volume/throughput) ```python SearchAPIRequest.set_default_settings(api_key=u'YOURKEY', top_match=True, match_requirements='phone OR email OR social_profiles', show_sources='all', live_feeds=True) ``` ```ruby Pipl.configure do |c| c.api_key = 'YOURKEY' c.top_match = true c.match_requirements = 'phone OR email OR social_profiles' c.show_sources = 'all' c.live_feeds = true end ``` ```java import com.pipl.api.search.SearchAPIRequest; import com.pipl.api.search.SearchConfiguration; SearchConfiguration defaultConfiguration = SearchAPIRequest.getDefaultConfiguration(); defaultConfiguration.apiKey = "YOURKEY"; defaultConfiguration.topMatch = true; defaultConfiguration.matchRequirements = "phone OR email OR social_profiles"; defaultConfiguration.showSources = "all"; defaultConfiguration.liveFeeds = true; ``` ```php api_key = "YOURKEY"; PiplApi_SearchAPIRequest::get_default_configuration()->top_match = true; PiplApi_SearchAPIRequest::get_default_configuration()->match_requirements = "phone OR email OR social_profiles"; PiplApi_SearchAPIRequest::get_default_configuration()->show_sources = "all"; PiplApi_SearchAPIRequest::get_default_configuration()->live_feeds = true; ?> ``` ```csharp using Pipl.APIs.Search; SearchConfiguration defaultConfiguration = SearchAPIRequest.DefaultConfiguration; defaultConfiguration.ApiKey = "YOURKEY"; defaultConfiguration.TopMatch = true; defaultConfiguration.MatchRequirements = "phone OR email OR social_profiles"; defaultConfiguration.ShowSources = "all"; defaultConfiguration.LiveFeeds = true; ``` ```bash # Set these parameters in your API requests: # top_match=true&match_requirements=phone%20OR%20email%20OR%20social_profiles&show_sources=all&live_feeds=true ``` ## Investigation and Background Checks Routine background checks, criminal and OSint investigations use Pipl Search to uncover as much useful information as possible on an applicant or person of interest. While you can run a search with just a single piece of information (see [minimum search requirements](/reference/request-overview#minimum-requirements) ), including as much information as possible in your query will generally connect to more records and return more data in your response. [The sources layer](/reference/know-your-sources) can provide additional data and context to your person of interest. _Recommended Parameters:_ - `show_sources=all` \*`live_feeds=true` (up to 10 QPS) ```python SearchAPIRequest.set_default_settings(api_key=u'YOURKEY', show_sources='all', live_feeds=True) ``` ```ruby Pipl.configure do |c| c.api_key = 'YOURKEY' c.show_sources = 'all' c.live_feeds = true end ``` ```java import com.pipl.api.search.SearchAPIRequest; import com.pipl.api.search.SearchConfiguration; SearchConfiguration defaultConfiguration = SearchAPIRequest.getDefaultConfiguration(); defaultConfiguration.apiKey = "YOURKEY"; defaultConfiguration.showSources = "all"; defaultConfiguration.liveFeeds = true; ``` ```php api_key = "YOURKEY"; PiplApi_SearchAPIRequest::get_default_configuration()->show_sources = "all"; PiplApi_SearchAPIRequest::get_default_configuration()->live_feeds = true; ?> ``` ```csharp using Pipl.APIs.Search; SearchConfiguration defaultConfiguration = SearchAPIRequest.DefaultConfiguration; defaultConfiguration.ApiKey = "YOURKEY"; defaultConfiguration.ShowSources = "all"; defaultConfiguration.LiveFeeds = true; ``` ```bash # Set these parameters in your API requests: # show_sources=all&live_feeds=true ``` ### Reverse relationship searches Use reverse relationship searches to discover more about a person you find in the relationship section of a Pipl Search result. Say you are searching for Alex Jensen and you see in your API response that he has a family relationship with Brian Jensen and you want to find out more about him. To do this, swap the name element with the relationship element from the API response, in this case name is "Brian Jensen" and the relationship to "Alex Jensen". ![](../static/img/reverse_relationship_searches.jpg 'Search By Relationship.jpg') See [how to perform a search using the relationship parameter ]searching-by-specific-parameters#relationship) ## Identity Investigation and Fraud The Search API can be used in fraud investigation and identity resolution to confirm whether specific data points connect to an individual and to build a full picture of the identity behind a piece of data. In addition, the data from Pipl search can be used in decisioning engines or machine learning models to calculate fraud risk scores. It is especially important in these use cases to make sure that all query parameters provided to the API are known to be accurate and connected to the person you are searching for. Leave out any data points that are not certain to be connected to a person. > 📘 Pipl Trust > > [Pipl Trust](https://trust.pipl.com) is another suite in the Pipl portfolio. It scores the risk of a data point or action using identity, connectivity, behavioral, and device signals — powered by Elephant, Pipl's large risk model. For more information about using Pipl Search as part of a machine learning model see [Using-Pipl-Search-in-Machine-Learning-and-Data-Driven-Decisioning]using-pipl-search-in-machine-learning-and-data-driven-decisioning) ### Data Point Validation One common use of the Pipl Search API in the fraud investigation and identity resolution space is to validate whether certain data points connect to an individual. For example if you have a user account and the phone number changes, you want to validate if that new phone number is connected to the account owner. When doing this, separate your data into two categories: 1. Known data with a confirmed link to the individual and 2. Data to be verified. Only send the known data in the search query, then in the response, check for the data you are trying to confirm. Pipl Search does not have 100% fill of all data points, so not finding the data point in the response is not definitive proof that it is not connected to the individual. Expect lower latency responses for searches by just a phone or email address. It may be helpful to see [the source layer](/reference/know-your-sources) to check what source was used to validate the data point. _Recommended Parameters:_ - `live_feeds=false` (except for low volume/throughput) - `minimum_probability=0` - `show_sources=all` ```python SearchAPIRequest.set_default_settings(api_key=u'YOURKEY', show_sources='all', live_feeds=False, minimum_probability=0) ``` ```ruby Pipl.configure do |c| c.api_key = 'YOURKEY' c.show_sources = 'all' c.live_feeds = false c.minimum_probability = 0 end ``` ```java import com.pipl.api.search.SearchAPIRequest; import com.pipl.api.search.SearchConfiguration; SearchConfiguration defaultConfiguration = SearchAPIRequest.getDefaultConfiguration(); defaultConfiguration.apiKey = "YOURKEY"; defaultConfiguration.showSources = "all"; defaultConfiguration.liveFeeds = false; defaultConfiguration.minimumProbability = 0.0; ``` ```php api_key = "YOURKEY"; PiplApi_SearchAPIRequest::get_default_configuration()->show_sources = "all"; PiplApi_SearchAPIRequest::get_default_configuration()->live_feeds = false; PiplApi_SearchAPIRequest::get_default_configuration()->minimum_probability = 0; ?> ``` ```csharp using Pipl.APIs.Search; SearchConfiguration defaultConfiguration = SearchAPIRequest.DefaultConfiguration; defaultConfiguration.ApiKey = "YOURKEY"; defaultConfiguration.ShowSources = "all"; defaultConfiguration.LiveFeeds = false; defaultConfiguration.MinimumProbability = 0; ``` ```bash # Set these parameters in your API requests: # show_sources=all&live_feeds=false&minimum_probability=0 ``` ### Identity Discovery and Scoring Another investigation use case is to try to build a profile for the identity behind a data point and, in some cases, provide a score for that identity. You may want to access the source layer to be able to include tag data such as vehicle and home ownership and professional credentials in your analysis. _Recommended Parameters:_ - `live_feeds=false` (except for low volume/throughput) - `minimum_probability=0` - `show_sources=all` ```python SearchAPIRequest.set_default_settings(api_key=u'YOURKEY', show_sources='all', live_feeds=False, minimum_probability=0) ``` ```ruby Pipl.configure do |c| c.api_key = 'YOURKEY' c.show_sources = 'all' c.live_feeds = false c.minimum_probability = 0 end ``` ```java import com.pipl.api.search.SearchAPIRequest; import com.pipl.api.search.SearchConfiguration; SearchConfiguration defaultConfiguration = SearchAPIRequest.getDefaultConfiguration(); defaultConfiguration.apiKey = "YOURKEY"; defaultConfiguration.showSources = "all"; defaultConfiguration.liveFeeds = false; defaultConfiguration.minimumProbability = 0.0; ``` ```php api_key = "YOURKEY"; PiplApi_SearchAPIRequest::get_default_configuration()->show_sources = "all"; PiplApi_SearchAPIRequest::get_default_configuration()->live_feeds = false; PiplApi_SearchAPIRequest::get_default_configuration()->minimum_probability = 0; ?> ``` ```csharp using Pipl.APIs.Search; SearchConfiguration defaultConfiguration = SearchAPIRequest.DefaultConfiguration; defaultConfiguration.ApiKey = "YOURKEY"; defaultConfiguration.ShowSources = "all"; defaultConfiguration.LiveFeeds = false; defaultConfiguration.MinimumProbability = 0; ``` ```bash # Set these parameters in your API requests: # show_sources=all&live_feeds=false&minimum_probability=0 ``` [Pipl Trust](https://trust.pipl.com) is another suite in the Pipl portfolio. It scores the risk of a data point or action based on connections between elements, associated profiles, and other signals — powered by Elephant, Pipl's large risk model. ## General Recommendations ### Performance Optimization Depending on the metrics that are most important to your application, there are different configuration strategies you can use. Often optimizing for one metric comes with trade-offs in another metric, so be sure to balance your approach according to your priorities. ### Optimizing for Match and Fill Rates In general, the more data you provide in search query parameters, the better the match and fill rate will be on a search response. Try adding more information about the person to the query. For example, if you’ve searched by email address alone, try adding the name and location to the query. Adding even just a country or a country + state to a search query can significantly increase the match and fill rate. When searching for individuals in the US, turning on live feeds can also slightly increase your match and fill rates. Live feeds are data partners outside of Pipl's infrastructure that can provide additional data (approximately 2-3% more) specifically within the USA. Please note that this will come with the downside of increased latency and [decreased throughput](/docs/rate-limiting-your-queries). ### Optimizing Query Speed The most important factor to increase speed is to turn off live feeds. This will both decrease latency and increase your [throughput rate limit](/docs/rate-limiting-your-queries) You can do this by setting the parameter 'live_feeds' to 'false'. Please note that turning off live feeds will lead to a slight reduction in data match and fill rates (see Optimizing for Match and Fill Rates section above) If low latency is your top priority, there are a few single-parameter queries that will run faster than multi-parameter queries. These include phone-only, email-only and address-only queries. Keep in mind that these single parameter queries come with significant trade-offs in terms of match and fill rate, so be sure that the benefit in latency is worth the cost of data fill. --- ## Searching by Address import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Searching by Address This guide walks through the best practices for using an address or location as an input parameter of a Search API query ## Using the Address Parameters The best way to include an [address](/reference/address) into an API query is to separate it into individual fields (`house, street, city, state, country, zip_code`). This ensures that the address is parsed correctly. If it is not possible to separate the address into individual fields, there is also the option to use the `raw address` field to pass the full address. The Search API will do its best to interpret the address into the separate fields for the query. The address should be comma separated and follow the standard formatting of the country. If the address is outside of the US, you must include the two-digit country code at the end of the address for it to be parsed correctly. Check the [query field in an API response](/reference/response) to see how the API parsed your address and ensure that it was done correctly. Below are some examples of addresses that can be parsed successfully by the Search API in the `raw_address` field: - `510 S Clearwater Loop, Post Falls, ID, 83854, US` - `1600 Pennsylvania Avenue NW, Washington, DC 20500` - `2 Gabriel Avenue, 75008 Paris, FR` > 🚧 Meeting Minimum Search Criteria > > In the US, a full street address (down to the house number) can be searched by itself. Outside the US, you must include at least one other required parameter in order to fulfil the [minimum requirements](/reference/request-overview#minimum-requirements) for a valid search ## Partial Addresses Even if you do not have the full street address of a person, if you are able to include location information in a query in the form of a partial address, this can significantly improve your results. For example, if you are searching by a combination of name + email address, but you have information on the country of these individuals, consider adding this information into the query using the `country` field. If you have details of location down to the state or city level, this will likely improve the results even further. ### Examples ```text //Example 1: Country only email=clark.kent@example.com&country=US //Example 2: Country, State and City email=clark.kent@example.com&country=US&state=NY&city=New York City ``` ```text //Example 1: Country only https://api.pipl.com/search/?key=YOUR-API-KEY&email=clark.kent@example.com&country-US //Example 2: Country, State and City https://api.pipl.com/search/?key=YOUR-API-KEY&email=clark.kent@example.com&country-US&state=NY&city=New York City ``` ```python from piplapis.data import Person, Email, Address from piplapis.search import SearchAPIRequest #Example 1: Country only fields = [Email(address='clark.kent@example.com'), Address(country='US')] request = SearchAPIRequest(person=Person(fields=fields), api_key='YOUR-API-KEY') response = request.send() #Example 2: Country, State and City fields = [Email(address='clark.kent@example.com'), Address(country='US', state='NY', city='New York City')] request = SearchAPIRequest(person=Person(fields=fields), api_key='YOUR-API-KEY') response = request.send() ``` ```ruby require 'pipl' #Example 1: Country only person = Pipl::Person.new person.add_field Pipl::Email.new(address: 'clark.kent@example.com') person.add_field Pipl::Address.new(country: 'US') response = Pipl::client.search person: person, api_key: 'YOUR-API-KEY' #Example 2: Country, State and City person = Pipl::Person.new person.add_field Pipl::Email.new(address: 'clark.kent@example.com') person.add_field Pipl::Address.new(country: 'US', state: 'NY', city: 'New York City') response = Pipl::client.search person: person, api_key: 'YOUR-API-KEY' ``` ```java import java.util.ArrayList; import java.util.List; import com.pipl.api.search.SearchAPIRequest; import com.pipl.api.data.containers.Person; import com.pipl.api.data.fields.*; import com.pipl.api.search.SearchConfiguration; SearchConfiguration configuration = new SearchConfiguration(); configuration.setProtocol("https"); configuration.apiKey = "YOUR-API-KEY"; //Example 1: Country only List fields = new ArrayList(); fields.add(new Email.Builder().address("clark.kent@example.com").build()); fields.add(new Address.Builder().country("US").build()); Person person = new Person(fields); SearchAPIRequest request = new SearchAPIRequest(person, configuration); SearchAPIResponse response = request.send(); //Example 2: Country, State and City fields = new ArrayList(); fields.add(new Email.Builder().address("clark.kent@example.com").build()); fields.add(new Address.Builder().country("US").state("NY").city("New York City").build()); person = new Person(fields); request = new SearchAPIRequest(person, configuration); response = request.send(); ``` ```php use_https = true; $configuration->api_key = 'YOUR-API-KEY'; //Example 1: Country only $fields = array( new PiplApi_Email(array("address" => "clark.kent@example.com")), new PiplApi_Address(array("country" => "US")) ); $person = new PiplApi_Person($fields); $request = new PiplApi_SearchAPIRequest(array('person' => $person), $configuration); $response = $request->send(); //Example 2: Country, State and City $fields = array( new PiplApi_Email(array("address" => "clark.kent@example.com")), new PiplApi_Address(array("country" => "US", "state" => "NY", "city" => "New York City")) ); $person = new PiplApi_Person($fields); $request = new PiplApi_SearchAPIRequest(array('person' => $person), $configuration); $response = $request->send(); ?> ``` ```csharp using Pipl.APIs.Search; using System.Collections.Generic; SearchConfiguration searchConfiguration = new SearchConfiguration( apiKey: "YOUR-API-KEY", url: "api.pipl.com/search/", useHttps: true ); //Example 1: Country only List fields = new List() { new Email(address: "clark.kent@example.com"), new Address(country: "US") }; var person = new Person(fields); SearchAPIRequest request = new SearchAPIRequest( person: person, requestConfiguration: searchConfiguration ); var response = await request.SendAsync(); //Example 2: Country, State and City fields = new List() { new Email(address: "clark.kent@example.com"), new Address(country: "US", state: "NY", city: "New York City") }; person = new Person(fields); request = new SearchAPIRequest( person: person, requestConfiguration: searchConfiguration ); response = await request.SendAsync(); ``` --- ## Searching by Names import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Searching by Names ## Introduction Names are the most common data field used in a Pipl Search query. However, they are also a common source of API errors, especially when used alone without any other data fields. Incorrectly formatted names may be parsed incorrectly leading to erroneous results and API warnings. This guide gathers some of the best practices on how to use names in your Pipl Search API queries. You can send a name to Pipl Search in one of two ways: - The first name, middle name/initial and last name, all in separate fields - A single raw name field which will be automatically parsed into the first, middle name/initial and last name fields ### Examples ```text //Using parsed name fields first_name=Clark&middle_name=Joseph&last_name=Kent //Using raw name field raw_name=Clark Joseph Kent ``` ```text //Using parsed name fields https://api.pipl.com/search/?key=YOUR-API-KEY&first_name=Clark&middle_name=Joseph&last_name=Kent //Using raw name field https://api.pipl.com/search/?key=YOUR-API-KEY&raw_name=Clark Joseph Kent ``` ```python from piplapis.data import Person, Name from piplapis.search import SearchAPIRequest #Using parsed name fields fields = [Name(first='Clark', middle='Joseph', last='Kent')] request = SearchAPIRequest(person=Person(fields=fields), api_key='YOUR-API-KEY') response = request.send() #Using raw name field (direct parameter) request = SearchAPIRequest(raw_name='Clark Joseph Kent', api_key='YOUR-API-KEY') response = request.send() #Using raw name field (in Person object) fields = [Name(raw='Clark Joseph Kent')] request = SearchAPIRequest(person=Person(fields=fields), api_key='YOUR-API-KEY') response = request.send() ``` ```ruby require 'pipl' #Using parsed name fields person = Pipl::Person.new person.add_field Pipl::Name.new(first: 'Clark', middle: 'Joseph', last: 'Kent') response = Pipl::client.search person: person, api_key: 'YOUR-API-KEY' #Using raw name field (direct parameter) response = Pipl::client.search raw_name: 'Clark Joseph Kent', api_key: 'YOUR-API-KEY' #Using raw name field (in Person object) person = Pipl::Person.new person.add_field Pipl::Name.new(raw: 'Clark Joseph Kent') response = Pipl::client.search person: person, api_key: 'YOUR-API-KEY' ``` ```java import com.pipl.api.search.SearchAPIRequest; import com.pipl.api.search.SearchAPIResponse; import com.pipl.api.data.containers.Person; import com.pipl.api.data.fields.*; import com.pipl.api.search.SearchConfiguration; import java.util.ArrayList; import java.util.List; SearchConfiguration configuration = new SearchConfiguration(); configuration.setProtocol("https"); configuration.apiKey = "YOUR-API-KEY"; //Using parsed name fields List fields = new ArrayList(); fields.add(new Name.Builder().first("Clark").middle("Joseph").last("Kent").build()); Person person = new Person(fields); SearchAPIRequest request = new SearchAPIRequest(person, configuration); SearchAPIResponse response = request.send(); //Using raw name field (direct parameter) request = new SearchAPIRequest.Builder() .rawName("Clark Joseph Kent") .configuration(configuration) .build(); response = request.send(); //Using raw name field (in Person object) fields = new ArrayList(); fields.add(new Name.Builder().raw("Clark Joseph Kent").build()); person = new Person(fields); request = new SearchAPIRequest(person, configuration); response = request.send(); ``` ```php use_https = true; $configuration->api_key = 'YOUR-API-KEY'; //Using parsed name fields $fields = array( new PiplApi_Name(array("first" => "Clark", "middle" => "Joseph", "last" => "Kent")) ); $person = new PiplApi_Person($fields); $request = new PiplApi_SearchAPIRequest(array('person' => $person), $configuration); $response = $request->send(); //Using raw name field (direct parameter) $request = new PiplApi_SearchAPIRequest( array('raw_name' => 'Clark Joseph Kent'), $configuration ); $response = $request->send(); //Using raw name field (in Person object) $fields = array( new PiplApi_Name(array("raw" => "Clark Joseph Kent")) ); $person = new PiplApi_Person($fields); $request = new PiplApi_SearchAPIRequest(array('person' => $person), $configuration); $response = $request->send(); ?> ``` ```csharp using Pipl.APIs.Search; using System.Collections.Generic; SearchConfiguration searchConfiguration = new SearchConfiguration( apiKey: "YOUR-API-KEY", url: "api.pipl.com/search/", useHttps: true ); //Using parsed name fields List fields = new List() { new Name(first: "Clark", middle: "Joseph", last: "Kent") }; var person = new Person(fields); SearchAPIRequest request = new SearchAPIRequest( person: person, requestConfiguration: searchConfiguration ); var response = await request.SendAsync(); //Using raw name field (direct parameter) request = new SearchAPIRequest( rawName: "Clark Joseph Kent", requestConfiguration: searchConfiguration ); response = await request.SendAsync(); //Using raw name field (in Person object) fields = new List() { new Name(raw: "Clark Joseph Kent") }; person = new Person(fields); request = new SearchAPIRequest( person: person, requestConfiguration: searchConfiguration ); response = await request.SendAsync(); ``` ## Basic Rules for Names The basic rules regarding names in the Pipl API, and the validation thereof are as follows: - When searched alone, names must include a first and last name. Because of Pipl’s worldwide index, a name alone will likely return many Possible Persons - especially if a name is very common. It is best practice to include other searchable fields such as a [high-level address](/reference/address) (e.g. with country and/or state and/or city) when available with a name to help narrow down the results. - Both the first name and the last name must be at least 2 characters in length. \*\* These conditions are relaxed with [partial name searches](/reference/name#partial-name-searching) as long as the [minimum search requirements](/reference/request-overview#minimum-requirements) are met by adding other searchable fields - The middle name can be 1 or more characters in length. Initials are allowed with or without a dot suffix. - The first, middle or last fields can include multiple names. These can be separated by spaces, or by a dash/hyphen (i.e double-barrel names). - “Double-barrel” or “Triple-barrel” names should be sent using a dash/hyphen between the names (e.g. Van-Der-Bank) - It is suggested to also try alternatives such as VanDerBank - Foreign characters and special characters can be used for a search should they meet the minimum character length requirements. They will be parsed as UTF-8 encoded strings. - Company names should not be used (the technology is used to search for a person), but they can be included [as a job](/reference/job) . - Don’t include two people’s names in one, the identity resolution technology is used to find a single person ### How raw names are parsed Pipl recommends sending the name parsed into the first, middle and last parts to dismiss any doubt as to how the name should be parsed. However in some cases, you might not have the name separated into first, middle and last, and would need to send the name in a single field to have the Pipl API parse out the name parts for you automatically. Sending the full name in a single field can be done by using the ‘raw’ name field in a [Person request](/reference/full-person) or [raw_name](/reference/name) in a search parameter request. The “query” section of a Pipl Search API response shows how the API interpreted all the query fields sent to it including how raw names were parsed. ![](../static/img/raw_names.jpg) The parsing of names is straightforward for simple names that include first, middle and last name, all as a single string such as “Clark Joseph Kent” or “Clark J Kent”. Example 1. Taking for example the name “Clark Joseph Kent”, the API parses names from the raw field in the following manner: | Name Component | Detail | Example Parsed | Example Result | | :------------- | :----------------------------------------------------------------------------------------------------------------- | :-------------------- | :------------- | | First name | The first string token, up to the first space character | **Clark** Joseph Kent | Clark | | Last Name | The last string token, from the last space character | Clark **Joseph** Kent | Kent | | Middle Name | Anything between the first string token and the last string token ( excluding the first and last space characters) | Clark Joseph **Kent** | Joseph | Example 2. Taking for example a name with a comma such as “Kent, Clark Joseph”, the API parses names from the raw field in the following manner: | Name Component | Detail | Example Parsed | Example Result | | :------------- | :--------------------------------------------- | :--------------------- | :------------- | | First Name | The first string token after the comma | Kent, **Clark** Joseph | Clark | | Last name | The first string token before the comma | **Kent**, Clark Joseph | Kent | | Middle name | All string tokens after the first string token | Kent, Clark **Joseph** | Joseph | > 📘 How are names searched on Pipl? > > When sending names in raw_name, the search engine, although parsing the name as described above, might attempt, in some cases, to switch first name and last name in order to find the person you are seeking. This might happen when the last name is a common first name, for example Jackson Curtis (parses to Curtis Jackson), Ryan Phillip (parses to Phillip Ryan). > > The search engine will recognize some surnames with more than one word (ie “De La Rocha” or “Von Welsbach”) and preserve them as the last name it extracts from a raw_name search. Due to the near infinite number of possible surnames this process is not perfect, but should hold for most compound surnames. ### Examples of raw name parsing The following **valid raw names** illustrate how titles and names consisting of more than 3 words are parsed. | Raw Name | Parsed First Name | Parsed Middle Name | Parsed Last Name | | :----------------------------- | :---------------- | :----------------- | :--------------- | | Clark Joseph Kent | Clark | Joseph | Kent | | Clark J Kent | Clark | J | Kent | | Ramon Antonio Gerard Estevez | Ramon | Antonio Gerard | Estevez | | Daniel Michael Blake Day-Lewis | Daniel | Michael Blake | Day-Lewis | | Dr. Victor Frankenstein\* | Victor | | Frankenstein | | Professor Albert Einstein\* | Albert | | Einstein | | Robert Downey Jr.\*\* | Robert | | Downey | | Dench, Judi | Judi | | Dench | | David Larry | Larry | | David | | Zach De La Rocha | Zach | | De La Rocha | | Zacarias Manuel De La Rocha | Zacarias | Manuel | De La Rocha | | Jorge Dos Santos | Jorge | | Dos Santos | - Pipl will parse the title to the sub-field ‘prefix’ \*\* Pipl will parse the suffix to the sub-field ‘suffix’ The following are examples of **invalid names**, unless searched as a [partial name](/reference/name#partial-name-searching) with additional search parameters included in the search. | Raw Name | Error/Issue | | :--------------- | :------------------------------------------- | | C Kent | First name does not contain 2 characters. \* | | Clark K. | Last name does not contain 2 characters. \* | | Dr. Frankenstein | “Dr.” will be parsed as a first name. \* | | R. Downey Jr. | First name does not contain 2 characters. \* | - Cannot be searched alone, is however a valid partial name ## Partial name searches [Partial name searches](/reference/name#partial-name-searching) in Pipl Search allow you to search with a portion of the name if the minimum query requirements have already been met with an additional field such as an email, phone or username. | First | Middle | Last | Additional Data Field in Query | | :------ | :----- | :----------- | :----------------------------- | | J | | | phone | | | | Frankenstein | email | | Patrick | | | username | ### Examples ```text //Example 1: First name only with phone first_name=J&phone=+15551234567 //Example 2: Last name only with email last_name=Frankenstein&email=victor.frankenstein@example.com //Example 3: First name only with username first_name=Patrick&username=patrick@twitter ``` ```text //Example 1: First name only with phone https://api.pipl.com/search/?key=YOUR-API-KEY&first_name=J&phone=+15551234567 //Example 2: Last name only with email https://api.pipl.com/search/?key=YOUR-API-KEY&last_name=Frankenstein&email=victor.frankenstein@example.com //Example 3: First name only with username https://api.pipl.com/search/?key=YOUR-API-KEY&first_name=Patrick&username=patrick@twitter ``` ```python from piplapis.data import Person, Name, Email, Phone from piplapis.search import SearchAPIRequest #Example 1: First name only with phone fields = [Name(first='J'), Phone(raw='+15551234567')] request = SearchAPIRequest(person=Person(fields=fields), api_key='YOUR-API-KEY') response = request.send() #Example 2: Last name only with email fields = [Name(last='Frankenstein'), Email(address='victor.frankenstein@example.com')] request = SearchAPIRequest(person=Person(fields=fields), api_key='YOUR-API-KEY') response = request.send() #Example 3: First name only with username request = SearchAPIRequest(first_name='Patrick', username='patrick@twitter', api_key='YOUR-API-KEY') response = request.send() ``` ```ruby require 'pipl' #Example 1: First name only with phone person = Pipl::Person.new person.add_field Pipl::Name.new(first: 'J') person.add_field Pipl::Phone.new(raw: '+15551234567') response = Pipl::client.search person: person, api_key: 'YOUR-API-KEY' #Example 2: Last name only with email person = Pipl::Person.new person.add_field Pipl::Name.new(last: 'Frankenstein') person.add_field Pipl::Email.new(address: 'victor.frankenstein@example.com') response = Pipl::client.search person: person, api_key: 'YOUR-API-KEY' #Example 3: First name only with username response = Pipl::client.search first_name: 'Patrick', username: 'patrick@twitter', api_key: 'YOUR-API-KEY' ``` ```java import com.pipl.api.search.SearchAPIRequest; import com.pipl.api.search.SearchAPIResponse; import com.pipl.api.data.containers.Person; import com.pipl.api.data.fields.*; import com.pipl.api.search.SearchConfiguration; import java.util.ArrayList; import java.util.List; SearchConfiguration configuration = new SearchConfiguration(); configuration.setProtocol("https"); configuration.apiKey = "YOUR-API-KEY"; //Example 1: First name only with phone List fields = new ArrayList(); fields.add(new Name.Builder().first("J").build()); fields.add(new Phone.Builder().raw("+15551234567").build()); Person person = new Person(fields); SearchAPIRequest request = new SearchAPIRequest(person, configuration); SearchAPIResponse response = request.send(); //Example 2: Last name only with email fields = new ArrayList(); fields.add(new Name.Builder().last("Frankenstein").build()); fields.add(new Email.Builder().address("victor.frankenstein@example.com").build()); person = new Person(fields); request = new SearchAPIRequest(person, configuration); response = request.send(); //Example 3: First name only with username request = new SearchAPIRequest.Builder() .firstName("Patrick") .username("patrick@twitter") .configuration(configuration) .build(); response = request.send(); ``` ```php use_https = true; $configuration->api_key = 'YOUR-API-KEY'; //Example 1: First name only with phone $fields = array( new PiplApi_Name(array("first" => "J")), new PiplApi_Phone(array("raw" => "+15551234567")) ); $person = new PiplApi_Person($fields); $request = new PiplApi_SearchAPIRequest(array('person' => $person), $configuration); $response = $request->send(); //Example 2: Last name only with email $fields = array( new PiplApi_Name(array("last" => "Frankenstein")), new PiplApi_Email(array("address" => "victor.frankenstein@example.com")) ); $person = new PiplApi_Person($fields); $request = new PiplApi_SearchAPIRequest(array('person' => $person), $configuration); $response = $request->send(); //Example 3: First name only with username $request = new PiplApi_SearchAPIRequest( array('first_name' => 'Patrick', 'username' => 'patrick@twitter'), $configuration ); $response = $request->send(); ?> ``` ```csharp using Pipl.APIs.Search; using System.Collections.Generic; SearchConfiguration searchConfiguration = new SearchConfiguration( apiKey: "YOUR-API-KEY", url: "api.pipl.com/search/", useHttps: true ); //Example 1: First name only with phone List fields = new List() { new Name(first: "J"), new Phone(raw: "+15551234567") }; var person = new Person(fields); SearchAPIRequest request = new SearchAPIRequest( person: person, requestConfiguration: searchConfiguration ); var response = await request.SendAsync(); //Example 2: Last name only with email fields = new List() { new Name(last: "Frankenstein"), new Email(address: "victor.frankenstein@example.com") }; person = new Person(fields); request = new SearchAPIRequest( person: person, requestConfiguration: searchConfiguration ); response = await request.SendAsync(); //Example 3: First name only with username request = new SearchAPIRequest( firstName: "Patrick", username: "patrick@twitter", requestConfiguration: searchConfiguration ); response = await request.SendAsync(); ``` --- ## Blacklisting People with Pipl import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Blacklisting People with Pipl The following is a guide for blacklisting people on your product for opt-out and compliance purposes. You can use this strategy with or without multiple data providers. ## Overview There may be a requirement to blacklist people who have requested their data to not appear in your product. This will require you to maintain a list of data and/or IDs and mask those. If a person requests to be blacklisted, that person's ID/data is added to the blacklist. Pipl results don't have a persistent ID for profiles (person_ids differ per response), so it's impossible to search for them in the blacklist & filter them out. In addition, even if you create an ID for a person, identity resolution imperfections may cause the same person to be represented as multiple different IDs, so blacklisting an ID isn't guaranteed to block all of that person's information. ## Solutions A 3-pronged approach to dealing with blacklists should be taken, with each step providing an additional safeguard against accidentally showing blocked information. ### Approach 1: Blacklisting by internal ID If you maintain an internal ID for a person, maintain this blacklist list and they are filtered by that info. ### Approach 2: Blacklist Pipl Source IDs Each Pipl person has an associated list of sources, which are the original web pages/online and offline data from which data was obtained. Pipl indexes such source records and assigns these individual records a unique source ID. Here is an example of a source ID record, which can be enabled by using the show_sources parameter: ```json { "@id": "34892949906cd1b52b690f86e2370c59", "@category": "professional_and_business", "@name": "USA Business Contact", "@premium": true, "@person_id": "efad9998-6d2d-4dbe-8333-7b7b4861f2f5", "@match": 1.0, ... } ``` - The "@id" of the source will remain static, and will not change - The "@match" has a value of 1, indicating that the source record was used to create the profile - The "@person_id" value is dynamic and will change on every request. This is an indicator that the source record was used in the profile Please use the following approach when blacklisting using Pipl source IDs: - When a person is to be blocked, all of the Pipl source IDs associated with that person should be added to a blacklist. Since the source IDs will remain static and never change, should a future search for the person be made the same source IDs will be returned - Set show_sourceids=true with your SEARCH API query to include a list of source IDs for each person or possible person in a response (see examples below). Store these source IDs in your blacklist. - In subsequent responses, if any source IDs are returned that match a source ID in the blacklist, then mask that response. You can enable the sources layer with show_sources=matching to view the source that corresponds with each source ID. - It is possible to apply this retroactively by running Pipl queries for all the people who are currently blacklisted, and then adding all returned matching source IDs into a "Source ID blacklist". - The show_sourceids parameter is available on all Pipl Search keys, including the Teaser key. **Example list of source IDs for a person response when using show_sourceids=true:** **Example list of source IDs for a possible person response when using show_sourceids=true:** **Examples for turning on source ID array in a response:** ```java //Update the default configuration on init, which will be used. //Use the extraParams variable of the defaultConfiguration. See example below: SearchConfiguration defaultConfiguration = SearchAPIRequest.getDefaultConfiguration(); defaultConfiguration.extraParams = "&show_sourceids=True"; ``` ```python # Extend the BASE_URL before making an API request. SearchAPIRequest.BASE_URL += "&show_sourceids=true" request = SearchAPIRequest(email="clark.kent@example.com") ``` ```php /* Please see the source code on GitHub for the code library for reference (base_url definition - https://github.com/piplcom/piplapis-php/blob/master/src/piplapis/search.php#L84). Once you construct a PiplApi_SearchAPIRequest object, you will need to change the base_url from: */ public static $base_url = 'api.pipl.com/search/?'; /* to the following to execute a request */ $base_url = 'api.pipl.com/search/?show_sourceids=true&'; ``` ```csharp //Use reflection to modify the Url property of your SearchAPIRequest object instance typeof(SearchAPIRequest).GetProperty("Url") .SetValue(yourSearchAPIRequest, "https://api.pipl.com/search/?show_sourceids=true&"); ``` ### Approach 3: Blacklist core data hash In addition to blacklisting IDs, it may be useful to block the actual identity of a person from showing up again in a provider-agnostic fashion. - For each currently blacklisted person, create one/more combinations of identifying information (``, `` or any other such combination), hash the data, and blacklist the hash. - When a teaser person results are obtained from any provider, run a similar algorithm on it, so that you search the data-blacklist with various hashes of possible combinations. - Do NOT be tempted to hash the entire data of a person, since this hash will stop being matched whenever there's any new data, and will also not work due to small differences between providers. --- ## Checking for new data updates In some cases, Pipl allows caching of search results as long as you’re a paying customer, you may end up looking for the best way to update that cache. This may be useful for getting the most recent contact information of an individual or finding up to date knowledge of an individual in an investigation. This document explains a strategy to do so, and provides best practices for such data update requests. ## Index updates Pipl updates its data index periodically with new data coverage. All administrators of an API account will be informed of data index updates. ## Recommended time frame > ❗️ Maximum Update Frequency > > The recommended timeframe to check for updates of data is three months from each request, or once there has been an update to the index - whichever comes first. Please do not query for updates more frequently than every 3 months as you will not see any significant changes to profiles in between index updates and these requests will bog down our system from other requests. Pipl considers too frequent update checks to be an abuse of our API platform. There are certain things to consider with regards to what data fields would change over time for an individual. For example: - An individual may keep a personal email address for a long time, but if they switch jobs they’ll get a new work email address. - The time period that the average person stays at a job should be considered. - Some data may not change very often, such as the person’s phone number. ## The strategy ![](../static/img/new_data_updates_strategy.png "new_data_updates_strategy.png") It is recommended to cache the search pointer of the person you’re saving into your cache, as it’ll be used to check for any new information. After the recommended time frame, should you wish to check for updates, you should make use of the following API mechanisms: - Query the API by search pointer, using the search pointer you have cached. - Use the new\_ feature of the match_requirements query parameter (see [match criteria](/reference/match-criteria)), to specify which data fields you’re looking to update (costs can be reduced by requiring important updates, such as new emails/jobs). - Use minimum_match=1.0 to make sure that you are still getting a single matching profile. Should the response have no new information of the data types you’ve specified, you’ll get a non-matching response (with no person or possible_person appearing in the response), and you won’t be charged. If there is updated information, a new Person will be returned, which will contain the up-to-date information we have about that individual. For example, if your match_requirements criteria was ‘new_email’, you will want to compare the cached emails with the new emails, to see which is (are) the new email(s) that was (were) received. In most cases, you’ll want to simply replace your current cache with the new response, including the new search pointer. --- ## Data-Driven Decisioning > 📘 Pipl Trust > > Pipl Trust is Pipl's fraud-decisioning suite. It uses the same identity data foundation as Search — plus connectivity, behavioral, and device signals scored by Elephant, Pipl's large risk model — to generate a risk score for an action or data point. If you are looking into machine-learning solutions for identity-risk scoring or fraud prevention, consider whether [Pipl Trust](https://trust.pipl.com) will meet your needs. ## Pipl Search API in Data-driven Decisioning The Pipl Search API response includes a wide array of person-centric information that can be leveraged for your data-driven decisions in methods such as Machine Learning (ML) models and Rules Engines. This document summarizes some best practices to consider when using Pipl data. ## Confirming Identity with Pipl The Pipl response contains a vast amount of information about the identity of a person that can be used in a rules engine or an ML model to help confirm an identity and/or gain additional knowledge about them. This data includes: [data fields](/reference/data-fields), [metadata](/reference/response), [sources](/reference/source), and [tags](/docs/pipl-api-tags). Each of these categories of data can be useful and should be considered in building a rules engine or an ML model. ### Best Practices When Comparing Data Fields When confirming and comparing your existing data with a Pipl API response, consider the following for specific data fields: - **Emails: **Normalize emails before comparison. Personal email services such as Gmail can be written as both [bob.franklin@gmail.com](mailto:bob.franklin@gmail.com) and [bobfranklin@gmail.com.](mailto:bobfranklin@gmail.com.) [These guidelines](/reference/email#md5-calculation-guidelines) in the Pipl API reference for md5 calculations will be useful as you begin to compare data fields. - **Names:** Due to spelling variations or people from the same family using the same account, consider breaking up a name into first, middle and last components and comparing them separately. These individual parts can then be confirmed using methods such as fuzzy matching, comparing common nicknames, sounds like, and transliteration if in foreign languages. - **Addresses:** Compare the individual address components (street, city, state, zip) by using methods such as fuzzy matching and spelling variations. Use fuzzy logic to accurately compare street name variations, such as “731B Union Street” vs “731 B Union St” - **Phones:** Phone numbers vary in local and international formats in different countries. Compare phone numbers in international format to get the best results. ### Gaining Additional Knowledge About an Identity The Pipl response returns a complete online/offline historical footprint of an identity which contains additional layers of information that may be useful. The following data points are worth considering as you design a model to make a determination about an identity: - **Counts:** _The quantity of data returned may correlate to confirming a real identity_ - Data field counts. The Pipl API response contains a section called “available data” indicating a summary for the number of data fields associated with the person (e.g. the number of emails, phones, addresses, etc). A real person typically has multiple emails, phones, or addresses over the course of their lifetime. - Number of sources. The identity of a person is created from various public source records. A real person typically appears in many public sources. - **Time Stamps:** _A history of public source records may correlate to confirming a real identity_ - Pipl returns timestamps as to when the data was first seen and when we last came across the data. A real person typically appears in public records over a long period of time proportional to their age. - It is possible to extract the age of data, for example, how long Pipl has known about an email or phone number and generally what is the “oldest” piece of information related to an identity as real identities tend to have rich data history. - **Data Types:** _Knowing more about the types of data may correlate to confirming a real identity_ - Pipl returns metadata that describes the type of specific data fields. For example, an email is indicated as personal, work, whether the email is of a free service provider such as Gmail or Hotmail or a one-time disposable email service. Similarly, [phones](/reference/phone) are marked as mobile, home_phone, or work_phone. - **Boolean indicators:** _Knowing more about the existence may correlate to confirming a real identity_ - Pipl returns social media data from networks such as Facebook, Twitter, Linkedin, and others. The existence of social media profiles over time may be an indicator of a real identity. For example, a person who has several social media accounts that have been in existence for several years is more likely to be a real person versus one who just created a social media account last month. You might find that the mere existence of a Job in a profile is a valid signal. ### Handling multiple results In some cases, especially when using Pipl to query for a phone number or an address, [Pipl Search returns multiple persons](/reference/response-types#possible-person) relating to that data point. There is no need to decide which person to compare, as in investigation and fraud-assessment situations there is a high likelihood that people who share an address, phone or email will use the same account for a transaction, so any comparison of any data point to any of the persons relating to that piece of information will usually prove valuable. ## Example Use Cases Pipl data combined with or compared to your data can provide an opportunity to improve your rules engine or ML models to achieve better outcomes. The combination of these two data sets can help answer questions to validate the identity of a new customer on your platform or a transaction in which the purchaser ships to a new recipient at a new address. For these use cases, the following are questions you may want to consider when using Pipl data in your data-driven decisions: ### Validate the identity of a new customer on your platform Using Pipl you may be able to determine if a new customer is who they say they are. - Does the Pipl API return a Person response when queried by the personal information they provided? - How long has Pipl known about the data associated with the person? - Does the name in the Pipl response match the name on record? - Is the billing address, shipping address, or phone number present in the Pipl response? - Is there a partial match? What is the distance between the physical locations in the response? ### Validate if a new shipping address or a new person shipped to is associated with the account holder Using Pipl you may be able to determine if the new person and/or the new address is related in any way to the account holder. Query the Pipl API for the account holder and the new person being shipped to. Based on the Pipl Search response: - Is there a relationship between the persons? - Are there shared addresses or phone numbers? --- ## Basic Coding Flowchart Many applications using the Pipl Search API follow the same general structure. This is a starting point and will need to be adjusted and enhanced depending on your specific needs and application. 1. [Person Response](/reference/response-types#person-perfect-match) 2. [Possible Person Response](/reference/response-types#possible-person) 3. [No Match Response](/reference/response-types#no-match) 4. [Minimum Request Requirements](/reference/request-overview#minimum-requirements) 5. [Rate limiting](rate-limiting) 6. [Key quota limits](rate-limiting#key-quota-limits) --- ## Monitoring Package key usage and spend Congratulations on your new Search API package key! Now we'll teach you how to use its features to monitor and control your usage and spend for the key. Please note that this article is complementary to the article '[Monitoring usage and spend](/docs/monitoring-usage-and-spend)'. ## Understanding your API key quota Package API keys have a specific quota (number of matches) associated with them when they are generated. The key’s quota is for the full term of the key. API package key match limits represent the number of matches you have to use during the package period, for example: | Key | Price per match | Package limit | Package period | Package Cost | | :--------------- | :-------------- | :------------ | :------------- | :----------- | | Package Business | $0.55 | 15000 | 1 year | **$8250** | To know how many matches you have left on your Package key, see the[ API keys](https://search.pipl.com/api/manage/keys) page on your Pipl account. You also can set a quota for a more specific time frame, such as 100 matches per day. Please see [setting your API key quota]monitoring-usage-and-spend#setting-your-api-key-quota). ## Using the HTTP headers The Package key usage details are shown on every API response in the [HTTP header](/reference/rate-limiting-information) : - "X-Package-Allotted" —The total number of matches defined on the key. - "X-Package-Current" —The number of used matches. - "X-Package-Expiry" —The date and time when the key and remaining matches will expire. Every billable response (i.e. every match) you get from the API will be counted against the package key limit and will be added to the "X-Package-Current". Applying the example used in the table above, the headers will return as follows: ```json X-Package-Allotted 12500 X-Package-Expiry 2018-10-08 00:00:00+00:00 ##1 year from issue date## X-Package-Current 16 ##after 16 matches were returned## ``` Use these three headers to calculate relevant values for your business. For example: 1. Calculate the number of queries you have left before your package key expires: **Queries Remaining** = **X-Package-Alloted** - **X-Package-Current** 2. Calculate the current spend on your package key: **Current Spend** = **Price-per-match/\***\_ x **X-Package-Current** \*_Depending on the key you used_ ## Example Python code The 'moneyed' and 'decimal' libraries are used to help handle the calculation and presentation. ```python from piplapis.error import APIError from piplapis.search import SearchAPIRequest from piplapis.search import SearchAPIResponse from piplapis.data import Person from piplapis.data.fields import Address, Email, Name, Phone from moneyed import Money from decimal import * person = Person() person.emails.append(Email('clark.kent@example.com')) SearchAPIRequest.set_default_settings(api_key='YOUR_PACKAGE_KEY_HERE') request = SearchAPIRequest(person=person) response = request.send() # Plain messages print("This is your Quota for the key: ", response.package_allotted) print("This is your usage of the key: ", response.package_current) print("This is when the key and quota expire: ", response.package_expiry) # Calculated messages usagePercent = Decimal(Decimal(response.package_current)/Decimal(response.package_allotted)) keyPrice = Decimal('0.40') totalUsage = Money(amount=(keyPrice*response.package_current),currency='USD') print("You have used ", response.package_current," of ",response.package_allotted,"queries.") print("You have used ",usagePercent,"% of your quota") ``` --- ## Monitoring usage and spend Did you know that as an API customer you can track your usage and billing in your Pipl account? The [usage page](https://search.pipl.com/api/manage/usage) shows a history of your queries and match rates. The [billing page](https://search.pipl.com/api/accounts/billing/) shows your previous invoices as well as your current spend, which is updated hourly. The current spend is displayed prior to applying any adjustments, refunds, or discounts. You also can monitor your account proactively via code using the [HTTP headers](/reference/rate-limiting-information) returned by every Search API [response](/reference/response) > 📘 Log Your Own API Usage > > We recommend logging every API request, including [search_ids](/reference/response), [errors](/reference/errors) and [warnings](/reference/warnings) in order to improve your integration. These logs should be reviewed regularly. ## Setting your API key quota API keys do not have a specific quota when they are generated. Only a Pipl account administrator can set your API key quota. To set a quota for the key you want to use: 1. Go to your [API keys page](https://search.pipl.com/api/manage/keys). 2. Hover over the key you want to use to view the options menu for that key. 3. Select ‘Set quota’ from the menu. ![](../static/img/set_key_quota.png) 4. The ‘Change Key Quota’ popup window will appear. 5. Select the quota limit. The quota limit is the number of **matches** you want to allow for the quota period. Setting the quota to 0 will reset the quota. 6. Select the quota period (hourly/daily/monthly). 7. Press ‘Change’. 8. The new quota you’ve set will show under the key. API key quotas represent the number of matches for a given period of time. They allow you to set a budget per key and control your spend. We’ve provided an example below. | Key | Price per match | Quota limit | Quota period | Quota per invoice | | :--------------- | :-------------- | :---------- | :----------- | :---------------- | | Business Premium | $0.55 | 2000 | Monthly | $1100 | ## Using the HTTP headers The quota that you have set will be shown on every API response in the [HTTP header](/reference/rate-limiting-information) as "X-APIKey-Quota-Alloted". The date and time of the quota reset will show in the [HTTP header](/reference/rate-limiting-information) as "X-Quota-Reset". Every billable response—such as every match returned from the API—will be counted against the quota of the key used and will be shown in the [HTTP header](/reference/rate-limiting-information) as "X-APIKey-Quota-Current". Applying the example used in the table above, the headers will return as follows: ```json X-APIKey-Quota-Allotted 2000 X-Quota-Reset 2018-10-01 00:00:00 ##The end of the month## X-APIKey-Quota-Current 1 ``` Use the three headers above to calculate relevant values for your business. For example: 1. Calculate the number of queries you have left before your quota is reached: **Queries Remaining** = **X-APIKey-Quota-Alloted** - **X-APIKey-Quota-Current** 2. Calculate your spend on an API key during a quota period: **Spend** = **Price-per-match\*** x **X-APIKey-Quota-Current** \*_Depending on the key you used_ --- ## Throttling Your Queries You might have just received an email error alert from Pipl with the subject “Whoa Nellie! Too many API calls per second…” What now? We can help. Pipl does use rate limiting, and here are tips for implementing a throttling mechanism for your Pipl API integration. ## Why the rate limit? The Pipl API has rate limits per account, across all keys. Pipl’s technology operates like a search engine rather than a traditional database. This means that records are indexed and clustered on every request made. We limit the number of queries per second (QPS) sent to the API at the same time to ensure that all customers have fair access. Implementing a throttling mechanism is important. First, it helps ensure that you receive the data you need. When you hit the rate limit, you will receive an HTTP 403 error status response. Second, rate limits help prevent abuse of our services. Consistently exceeding rate limits can result in suspension of your account. ## What are the limitations? If you use Pipl with peaks of query volumes, please make sure that your application is adhering to the [allotted rate limits](rate-limiting), otherwise we consider this abuse. Below is a chart indicating the allowed number of queries to be performed in a certain period. | API key type | Live feeds | Second | Minute | Hour | Day | Week | Month | | --- | --- | --- | --- | --- | --- | --- | --- | | Contact, Social, or Business | true (default) | 10 | 600 | 36,000 | 864,000 | 6,048,000 | 25,920,000 | | Contact, Social, or Business | false | 20 | 1200 | 72,000 | 1,728,000 | 12,096,000 | 51,840,000 | As the table above shows, the default is 10 QPS. You can increase your rate to 20 QPS, but you will need to use live_feeds=false in your queries. ## Error management and HTTP headers Each API response will return [HTTP headers](/reference/rate-limiting-information) to help you adhere to rate limits. QPS rate limits depend on whether or not you use live_feeds with your queries. Depending on the query, different QPS rates apply and different [HTTP headers](/reference/rate-limiting-information) need to be checked by your application code. Once you hit the rate limit and receive an HTTP 403 status message, every succeeding query received counts towards your rate-limiting quota. See the table below for the error message and the [HTTP headers](/reference/rate-limiting-information) to watch for, depending on whether you are using live feeds. | API Key Type | Configuration Parameter: live_feeds | QPS | Response HTTP Headers and Status Code | | --- | --- | --- | --- | | Contact, Social, or Business | true | 10 | • X-QPS-Live-Current > X-QPS-Live-Allotted• HTTP Status Code 403• Error Message "Per second limit for live calls reached" | | Contact, Social, or Business | false | 20 | • X-QPS-Current > X-QPS-Allotted• HTTP Status Code 403• Error Message "Per second limit for total calls reached" | ## How to best implement a throttling mechanism? To implement throttling, you can implement a pause (thread.sleep) between each request. If you need a multithreaded solution with low latency, there are many open source solutions available to help. Open source code libraries can be used in conjunction with your API for a rate limiting solution, but this solution depends on your use case. Some Pipl customers use open source libraries such as: ### Programming language and platform independent - [Nginx proxy](https://monterail.com/blog/2011/outbound-api-rate-limits-the-nginx-way/). Take advantage of the built-in nginx module, the HttpLimitReqModule. - [HAProxy](http://blog.serverfault.com/2010/08/26/1016491873/). Better Rate Limiting For All with HAProxy ### Java - [Google Guava RateLimiter class](https://google.github.io/guava/releases/19.0/api/docs/index.html?com/google/common/util/concurrent/RateLimiter.html). See also how this can be implemented using [Guava on StackOverflow](https://stackoverflow.com/questions/1407113/throttling-method-calls-to-m-requests-in-n-seconds). - [Java Rate Limit API](https://github.com/jabley/rate-limit). Contains the primitives and utilities used to rate-limit Java applications and a CircuitBreaker implementation. ### PHP - [Stiphle](https://github.com/davedevelopment/stiphle). A simple PHP library for throttling or rate limiting. ### Python - [Rate Limit](https://pypi.org/project/ratelimit/). API rate limit decorator. - [Limit](https://pypi.org/project/limit/). Decorator that limits the calling rate of a function. - [RequestsThrottler](https://pypi.python.org/pypi/RequestsThrottler/). Python HTTP requests throttler. - [Throttle](https://pypi.python.org/pypi/throttle). A robust and versatile throttling implementation relying on the token bucket algorithm. ### Ruby - [Sidekiq framework](https://github.com/sensortower/sidekiq-throttled) for background processing has a Concurrency and threshold throttling library. - [ThrottleQueue](https://github.com/ryancalhoun/throttle-queue). A thread-safe rate-limited work queue with foreground and background operations. - [Slow Web](https://github.com/benbjohnson/slowweb). An HTTP request governor. ### C#/ASP.net - [How to implement rate limiting in ASP.NET Core](https://www.infoworld.com/article/3442946/how-to-implement-rate-limiting-in-aspnet-core.html) > 🚧 What's under the hood of Pipl's rate limiting mechanism? > > If you’re curious about what’s under the hood, Pipl’s rate limiting engine uses a sliding window mechanism and starts counting from the time of the first request sent. If you’d like more specifics, visit [here](https://engagor.github.io/blog/2017/05/02/sliding-window-rate-limiter-redis/) and [here](https://engineering.classdojo.com/blog/2015/02/06/rolling-rate-limiter/) (note the second comment regarding the "Rolling Window") ## Consider queuing your requests to Pipl If your platform supports multiple users or requires a backlog of requests, consider using a modern queueing technology in your Pipl API integration. This will give you control over rate-querying the Pipl API and allow you to specify priority queues. ### Consider the following architecture and flow: ![](../static/img/recommended_architecture.JPG 'arch.JPG') ### 1. User Action - A user action can trigger single- and multiple-batch enrichments - You can segment users by subscription. For example, you can designate priority vs. normal users, with trial users receiving the lowest priority. ### 2. Queuing - A priority-based queue is created per user, FIFO - Define priority based on use case/flow ### 3. Threading - Multiple threads collect queries from each of the queues based on a priority algorithm - Serve multiple users fairly based on their subscription levels - Queues can be depleted based on priority - Run optimally and adhere to Pipl API rate limits. The thread turns requests into API requests and sends them according to the specified rate limit, based on the key. - Event-based, push to user feedback ### 4. User Feedback - UI Dialog to show progress - Show a progress bar. Estimate time remaining based on queue size and remainder. - Update the number of enriched data points as the queue gets smaller. - Upsell other features to customers. - User can optionally close dialog and be notified by email. - Use creative UI techniques instead of a dialog. Data gets updated on UI in near-real time as enriched. ![](../static/img/recommended_feedback_flow.JPG 'feedback.JPG') ## Rate limit not enough for your needs? Speak to your account manager. Pipl will assess your volume and requirements, and we can come to an agreement. You will need to use live_feeds=false, however. --- ## Rate Limiting in Pipl Search We want you to use our API as much as possible. However, sometimes we must limit the numbers of API calls run. This document outlines the default rate-limiting configurations for our API and the reasoning behind those limits. If you feel these limits hinder your API usage, contact your Account Director or Integration Specialist to create custom settings. ## Queries Per Second Limit The queries-per-second (QPS) limit is the number of queries you can run per second. > 🚧 Rate-limit your Pipl API integration > > We require Pipl API customers to implement a rate-limiting mechanism in their integrations to prevent HTTP status 403 throttling errors. Please see the tutorial on [throttling your queries]rate-limiting-your-queries) for best practices. **Why do we have this limit?** Limits enable us to deliver consistently high performance for all customers and to protect them from accidental overuse. **What is the default limit?** The default limit is different for queries that use live feeds and those that do not. With live feeds, limits help us protect our external feed providers from extreme usage spikes. Defaults are: - 20 total queries - 10 queries that includes live feeds **Where can I see my limit and current status?** Refer to the [HTTP headers of the API responses](/reference/rate-limiting-information). **What if I need more?** Please contact your Account Director or Integration Specialist. ### Live Feeds **What are live_feeds?** Live feeds are data partners outside of Pipl's infrastructure that can provide additional data—2-3% more—specifically within the USA. **Why do queries with live feeds have a lower QPS limit?** Live feeds have a lower default QPS limit in order to limit load on external data providers. Queries with live feeds also have increased latency. Consider turning live_feeds to false to increase your query throughput and decrease latency. ## Key Quota Limits In addition to our rate-limiting systems, we enable customers to configure hard quotas on specific API keys. Key quotas can be set as a number of matches/queries per day, week, or month. Quotas will apply to the number of billed queries, so if your API key is billed per-match then the quota will limit the number of matches whereas if your API key is billed per call, then the quota will limit your calls. **Why do we have this quota limit?** This enables you to set limits for specific applications, development environments (QA/staging) or for specific employees based on the key issued. **What is the default limit?** There are no default key quotas. **Can I set my own key quota limits?** Yes. Organization administrators—usually the person who opened the account— can manage custom quotas [on the API keys page](https://pipl.com/api/manage/keys). They can set a monthly, daily, or weekly quota per key. **Where can I see my limit and current status?** If you set custom quota limits, they will be displayed on your [key management page](https://pipl.com/api/manage/keys). The [HTTP headers of the API responses](/reference/rate-limiting-information) also show the quota. Notifications via email alerts will be sent out to account administrators when reaching 80% and 100% of quota. Read more about this in the tutorial on [monitoring usage and spend]monitoring-usage-and-spend). ## Account Spend Limit The account spend limit is a monthly limit on the amount of money you can spend on API queries. Once you reach the limit, further API queries will be rejected. **Why do we have this limit?** This limit protects customers from accidental overuse and protects Pipl from credit line abuse. **What is the default limit?** $1,000 per month. **Where can I see my limit and current status?** In your [API billing overview page](https://pipl.com/api/manage/billing). Notifications via email alerts will be sent out to account administrators when reaching 80% and 100% of spend. **What if I need more?** Once we verify your identity and payment information, simply contact us and request a new spend limit based on your needs and approved credit line. --- ## Code Libraries import PYTHON from '../static/img/python.png' import RUBY from '../static/img/ruby.png' import JAVA from '../static/img/java.png' import PHP from '../static/img/php.png' import CSHARP from '../static/img/csharp.png' import SWAGGER from '../static/img/swagger.png' # Code Libraries We love developers, so we want to make your life as easy as possible. We've created a set of client libraries for major programming languages so that you can integrate our APIs into your code in minutes. What are you waiting for? Just choose your preferred language and get started. | **Python** | **Ruby** | **Java** | **PHP** | **C#** | **Swagger** | | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | | | | | | | | ## Python The Python library is on PyPI, so you can use pip or easy_install. ``` pip install piplapis-python ``` Or grab the source from [github](https://github.com/piplcom/piplapis-python). ## Ruby The Ruby library is on RubyGems.org, so you can gem install it. ``` bundle install piplapis-ruby ``` Or grab the source from [github](https://github.com/piplcom/piplapis-ruby). ## Java The Java library is on [Maven Central](https://search.maven.org/artifact/com.pipl.api/piplapis/5.0.16/jar). ``` dependency groupIdcom.pipl.api/groupId artifactIdpiplapis/artifactId version5.0.16/version /dependency ``` Or grab the source from [github](https://github.com/piplcom/piplapis-java). ## PHP The PHP library is available on Packagist for Composer. ``` "pipl/piplapis-php": "*" ``` Or grab the source from [github](https://github.com/piplcom/piplapis-php). ## C# The C# library is available on NuGet ``` PM> Install-Package piplclient ``` Or grab the source from [github](https://github.com/piplcom/piplapis-csharp). ## Swagger The Swagger definition is available on [github](https://github.com/piplcom/search-api-examples/tree/main/Swagger) For more information on using swagger, see [Swagger's getting started guide](https://swagger.io/tools/open-source/getting-started/). --- ## Code Snippets and Example Programs import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faMale, faUsers } from '@fortawesome/free-solid-svg-icons'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Code Snippets and Example Programs The following snippets and examples are meant to highlight some commonly used capabilities of the API. For a complete understanding of the API's features, please refer to the libraries' source code (available on [github](https://github.com/piplcom/)). ## Example Scripts Example scripts using the Pipl API can be found at the [Search API Examples github page](https://github.com/piplcom/search-API-examples) ## Code Snippets Below are a few snippets for the basic things that you can do with the API [Code Libraries](code-libraries). ### Creating a request **Option 1** - This is a fast, direct method for simple requests with few parameters: ```python from piplapis.search import SearchAPIRequest request = SearchAPIRequest(email=u'clark.kent@example.com', api_key='YOURKEY') ``` ```ruby require 'pipl' response = Pipl::client.search email: 'clark.kent@example.com', api_key: 'YOURKEY' ``` ```java import com.pipl.api.search.SearchAPIRequest; import com.pipl.api.search.SearchAPIResponse; import com.pipl.api.search.SearchConfiguration; SearchConfiguration configuration = new SearchConfiguration(); configuration.setProtocol("https"); configuration.apiKey = 'YOURKEY' SearchAPIRequest request = new SearchAPIRequest.Builder().email("clark.kent@example.com").firstName("Clark").lastName("Kent").configuration(configuration).build(); ``` ```php use_https = true; $configuration->api_key = 'YOURKEY'; $request = new PiplApi_SearchAPIRequest(array('email' => 'clark.kent@example.com', 'first_name' => 'Clark', 'last_name' => 'Kent'), $configuration); ?> ``` ```csharp using Pipl.APIs.Search; SearchConfiguration searchConfiguration = new SearchConfiguration(apiKey: "YOURKEY",url: "api.pipl.com/search/", useHttps: true); SearchAPIRequest request = new SearchAPIRequest(email: "clark.kent@example.com", firstName: "Clark", lastName: "Kent", requestConfiguration: searchConfiguration); ``` **Option 2 - Using the data-model.** This method is useful for more complex queries, such as when you need to send multiple values of the same field type: ```python from piplapis.data import Person, Name, Address, Job fields = [Name(first=u'Clark', last=u'Kent'), Address(country=u'US', state=u'KS', city=u'Smallville'), Address(country=u'US', state=u'KS', city=u'Metropolis'), Job(title=u'Field Reporter')] request = SearchAPIRequest(person=Person(fields=fields), api_key='YOURKEY') ``` ```ruby person = Pipl::Person.new person.add_field Pipl::Name.new(first: 'Clark', last: 'Kent') person.add_field Pipl::Address.new(country: 'US', state: 'KS', city: 'Smallville') person.add_field Pipl::Address.new(country: 'US', state: 'KS', city: 'Metropolis') person.add_field Pipl::Job.new(title: 'Field Reporter') response = Pipl::client.search person: person, api_key: 'YOURKEY' ``` ```java import java.util.ArrayList; import java.util.List; import com.pipl.api.search.SearchAPIRequest; import com.pipl.api.data.containers.Person; import com.pipl.api.data.fields.*; import com.pipl.api.search.SearchConfiguration; SearchConfiguration configuration = new SearchConfiguration(); configuration.setProtocol("https"); configuration.apiKey = 'YOURKEY'; List fields = new ArrayList(); fields.add(new Name.Builder().first("Clark").last("Kent").build()); fields.add(new Address.Builder().country("US").state("KS").city("Smallville").build()); fields.add(new Address.Builder().country("US").state("KS").city("Metropolis").build()); fields.add(new Job.Builder().title("Field Reporter").build()); Person person = new Person(fields); // Or the short version: // Person person = new Person(new Name(null, "Clark", null, "Kent", null), new Address("US", "KS", "Smallville", null, null, null, null, null), new Address("US", "KS", "Metropolis", null, null, null, null, null), new Job("Field Reporter", null, null)); SearchAPIRequest request = new SearchAPIRequest(person, configuration); ``` ```php use_https = true; $configuration->api_key = 'YOURKEY'; $fields = array(new PiplApi_Address(array("country" => "US", "state" => "KS", "city" => "Metropolis")), new PiplApi_Address(array("country" => "US", "state" => "KS", "city" => "Smallville")), new PiplApi_Name(array("first" => "Clark", "middle" => "Joseph", "last" => "Kent")), new PiplApi_Job(array("title" => "Field Reporter")), ); $person = new PiplApi_Person($fields); $request = new PiplApi_SearchAPIRequest(array('person' => $person), configuration); return $request; ``` ```csharp using Pipl.APIs.Search; SearchConfiguration searchConfiguration = new SearchConfiguration(apiKey: "YOURKEY",url: "api.pipl.com/search/", useHttps: true); List fields = new List() { new Name(first: "Clark",last: "Kent"), new Address(country: "US", state: "KS", city: "Smallville"), new Address(country: "US", state: "KS", city: "Metropolis"), new Job(title: "Field Reporter") }; var person = new Person(fields); SearchAPIRequest request = new SearchAPIRequest(person: person, requestConfiguration: searchConfiguration); ``` ### Sending a request **Option 1 – Synchronously** ```python from piplapis.search import SearchAPIError try: response = request.send() except SearchAPIError as e: print(e.http_status_code, e) ``` ```ruby begin response = Pipl::client.search email: 'clark.kent@example.com' rescue Pipl::Client::APIError => e puts e.status_code, e.message end ``` ```java import java.io.IOException; import com.pipl.api.search.SearchAPIError; import com.pipl.api.search.SearchAPIResponse; try { SearchAPIResponse response = request.send(); } catch (SearchAPIError | IOException e) { e.printStackTrace(); } ``` ```php send(); } catch (PiplApi_SearchAPIError $e) { print $e->getMessage(); } ``` ```csharp try { var response = await _request.SendAsync(); } catch (SearchAPIError e) { Console.Out.WriteLine(e.ToString()); } catch (IOException e) { Console.Out.WriteLine(e.ToString()); } ``` **Option 2 – Async: Send the query with a non-blocking call** ```python def my_callback(response=None, error=None): print response or error request.send_async(my_callback) do_other_things() ``` ```ruby thread = Pipl::client.search email: 'clark.kent@example.com', async: true do |resp| puts resp[:response] or resp[:error] end do_other_things() ``` ```java import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; ExecutorService threadPool = Executors.newSingleThreadExecutor(); // Other alternatives contain more advanced thread pools and FutureTask. Future future = threadPool.submit(request.sendAsync(false)); doOtherThings(); try { SearchAPIResponse response = future.get(); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } ``` ```php # Not available in PHP ``` ```csharp var task = _request.SendAsync(); _doOtherThings(); try { var response = task.Result; } catch (TaskCanceledException e) { Console.Out.WriteLine(e.ToString()); } ``` ### Working with a response > 📘 A response can return either a Person , a list of Possible Persons , or no data. > > When working with the response, first check for a person object. If it's null, check for the possible_persons array. If there are neither, there is no data in the response (the persons_count property will be 0 in this case). The below syntax is available for all fields to quickly access frequently used data (the most recent name, last address, most prominent username, etc.). For example, when using the fast, direct option #1 method: ```python >>> print(response.name) u'Clark Joseph Kent' >>> print(response.gender) u'Male' >>> print(response.address) u'10-1 Hickory Lane, Smallville, Kansas' >>> print(response.job) u'Field Reporter at The Daily Planet (2000-2012)' ``` ```ruby puts response.name # Output: 'Clark Joseph Kent' puts response.gender # Output: 'Male' puts response.address # Output: '10-1 Hickory Lane, Smallville, Kansas' puts response.job # Output: 'Field Reporter at The Daily Planet (2000-2012)' ``` ```java System.out.println(response.name()); // Output: "Clark Joseph Kent" System.out.println(response.gender()); // Output: "Male" System.out.println(response.address()); // Output: "10-1 Hickory Lane, Smallville, Kansas" System.out.println(response.job()); // Output: "Field Reporter at The Daily Planet (2000-2012)" ``` ```php person->addresses[0]; // 10-1 Hickory Lane, Smallville, Kansas ``` ```csharp Console.Out.WriteLine(_response.Name); // Output: "Clark Joseph Kent" Console.Out.WriteLine(_response.Gender); // Output: "Male" Console.Out.WriteLine(_response.Address); // Output: "10-1 Hickory Lane, Smallville, Kansas" Console.Out.WriteLine(_response.Job); // Output: "Field Reporter at The Daily Planet (2000-2012)" ``` Access the person object that came with the response: ```python >>> response.person >>> response.person.addresses [Address(country=u'US', state=u'KS', city=u"Metropolis", street=u"Broadway", house=u"1000", apartment=u"355"), Address(country=u'US', state=u'KS', city=u"Smallville", street=u"Hickory Lane", house=u"10", apartment=u"1")] ``` ```ruby puts response.person.addresses # Output: '10-1 Hickory Lane, Smallville, Kansas' # Output: '1000-355 Broadway, Metropolis, Kansas' ``` ```java System.out.println(response.getPerson().getAddresses().get(0)); // Output: "10-1 Hickory Lane, Smallville, Kansas" ``` ```php person->addresses[0]; // 10-1 Hickory Lane, Smallville, Kansas ``` ```csharp Console.Out.WriteLine(_response.Person.Addresses[0]); // Output: "10-1 Hickory Lane, Smallville, Kansas" ``` ### Working with sources Access the response data's list of sources. This is only available if you set the “show_sources” flag to “all” or “matching”: ```python >>> len(response.sources) 2 >>> response.sources[0] >>> response.sources[0].phones [Phone(country_code=1, number=9785550145)] >>> response.sources[0].origin_url u'http://linkedin.com/clark.kent' ``` ```ruby response = Pipl::client.search email: 'clark.kent@example.com', show_sources: 'all' puts response.sources[1].phones[0].display # Output: '(978) 555-0145' puts response.sources[1].origin_url # Output: 'http://facebook.com/superman' ``` ```java System.out.println(response.getSources().size()); // Output: 2 System.out.println(response.getSources().get(1).getPhones().get(0).getDisplayInternational()); // Output: "+1 978-555-0145" System.out.println(response. getSources().get(0).getOriginUrl()); // Output: "http://linkedin.com/clark.kent" ``` ```php sources); // 2 print $response->sources[1]->phones[0]->display_international; // http://linkedin.com/clark.kent print $response->sources[1]->domain; // linkedin.com ``` ```csharp Console.Out.WriteLine(_response.Sources.Count); // Output: 2 Console.Out.WriteLine(_response.Sources[1].Phones[0].DisplayInternational); // Output: "+1 978-555-0145" Console.Out.WriteLine(_response.Sources[0].OriginUrl); // Output: "http://linkedin.com/clark.kent" ``` Group sources. Sources can be grouped by domain, category, match and more: ```python >>> type(response.group_sources_by_domain()) >>> response.group_sources_by_domain().get(u'linkedin.com') [, ] ``` ```ruby response = Pipl::client.search email: 'clark.kent@example.com', show_sources: 'all' puts response.group_sources_by_domain['linkedin.com'].size # Output: 1 ``` ```java System.out.println(response.groupSourcesByDomain().get("linkedin.com").size()); // Output: 1 ``` ```php group_sources_by_domain()['linkedin.com']); // array print get_class($response->group_sources_by_domain()['linkedin.com'][0]); // PiplApi_Source ``` ```csharp Console.Out.WriteLine(_response.GroupSourcesByDomain()["linkedin.com"].Count()); // Output: 1 ``` ### Useful utilities There are useful utilities implemented for the field objects. Here are some examples: ```python >>> address = response.address >>> address.state u'KS' >>> address.state_full u'Kansas' >>> email = response.email >>> email.username u'clark.kent' ``` ```ruby address = response.address puts address.state # Output: 'KS' puts address.state_full # Output: 'Kansas' email = response.email puts email.username # Output: 'clark.kent' ``` ```java Address address = new Address.Builder().country("US").state("KS").build(); System.out.println(address.getState()); // Output: "KS" System.out.println(address.stateFull()); // Output: "Kansas" Email email = new Email.Builder().address("clark.kent@example.com").build(); System.out.println(email.username()); // Output: "clark.kent" ``` ```php address()->state; // KS print $response->address()->state_full(); // Kansas print $response->email(); // clark.kent@example.com print $response->email()->username; // clark.kent ``` ```csharp Address address = new Address(country: "US", state:"KS"); Console.Out.WriteLine(address.State); // Output: "KS" Console.Out.WriteLine(address.StateFull); // Output: "Kansas" Email email = new Email(address: "clark.kent@example.com"); Console.Out.WriteLine(email.Username); // Output: "clark.kent" ``` ### Global Preferences You also can set search preferences globally, and they will apply to all search requests. Examples shown in the snippet are the default preferences. Setting global preferences is optional—you can choose query settings per request if you prefer. ```python SearchAPIRequest.set_default_settings(api_key=u'YOURKEY', minimum_probability=None, show_sources=None, minimum_match=None, hide_sponsored=None, live_feeds=None, use_https=True) ``` ```ruby Pipl.configure do |c| c.api_key = 'YOURKEY' c.show_sources = 'all' c.minimum_probability = 0.7 c.minimum_match = 0.5 c.strict_validation = true end ``` ```java import com.pipl.api.search.SearchAPIRequest; import com.pipl.api.search.SearchConfiguration; SearchConfiguration defaultConfiguration = SearchAPIRequest.getDefaultConfiguration(); defaultConfiguration.protocol = "https"; defaultConfiguration.apiKey = "YOURKEY"; defaultConfiguration.minimumProbability = null; defaultConfiguration.showSources = null; defaultConfiguration.possibleResults = null; defaultConfiguration.hideSponsored = null; defaultConfiguration.liveFeeds = null; ``` ```php api_key = "YOURKEY"; PiplApi_SearchAPIRequest::get_default_configuration()->minimum_probability = 0.9; PiplApi_SearchAPIRequest::get_default_configuration()->minimum_match = 0.8; PiplApi_SearchAPIRequest::get_default_configuration()->hide_sponsored = true; PiplApi_SearchAPIRequest::get_default_configuration()->live_feeds = false; PiplApi_SearchAPIRequest::get_default_configuration()->use_https = true; PiplApi_SearchAPIRequest::get_default_configuration()->show_sources = "all"; ``` ```csharp SearchConfiguration defaultConfiguration = SearchAPIRequest.DefaultConfiguration; defaultConfiguration.UseHttps = true; defaultConfiguration.ApiKey = "YOURKEY"; defaultConfiguration.MinimumProbability = null; defaultConfiguration.ShowSources = null; defaultConfiguration.MinimumMatch = null; defaultConfiguration.HideSponsored = null; defaultConfiguration.LiveFeeds = null; ``` --- ## First Steps import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; ## 1. Get an API key All API calls must include a valid API key. This is our way of identifying you and authorizing your call. If you have an account, you can choose a key on your [API Keys page](https://search.pipl.com/api/manage/keys). To experiment with our API and try a few calls, use the [demo page](https://search.pipl.com/api/demo) or [try out the Postman collection](postman-collection). ## 2. Choose your code library Integrating to an API should be easy. We've written code libraries for major programming languages to make integration a breeze. Choose your preferred language. We currently support Python, Ruby, Java, C# and PHP. [Download a code library here](code-libraries) ## 3. Run a "Hello World" query When you query Pipl, simply enter the information you have about someone and we'll deliver all of the data available about that person. Let's say we're looking for Clark Kent, who's using the email [clark.kent@example.com](mailto:clark.kent@example.com): ````text https://api.pipl.com/search/?first_name=Clark&last_name=Kent&email=clark.kent@example.com&key=YOURKEY ```` > 📘 Free query > > Any query that contains the email address `clark.kent@example.com` will not be charged and it will provide static example output as a result. > 👍 Use Encryption > > We require SSL—change any URL prefix to HTTPS instead of HTTP. > **API Endpoint:** [https://api.pipl.com/search/](https://api.pipl.com/search/) ```text https://api.pipl.com/search/?email=clark.kent@example.com&key=YOURKEY ``` ```python #imports from piplapis.search import SearchAPIRequest #run search (request/response) request = SearchAPIRequest(email=u'clark.kent@example.com', first_name=u'Clark', last_name=u'Kent', api_key='YOURKEY') response = request.send() #print portion of response if response.person: #Has data so single Full Person response currentPerson = response.person print("Hello World:") print("Number of Names:", len(currentPerson.names)) print("Name(s):" + "\n" .join(map(str, currentPerson.names))) print("Username(s):" + "\n" .join(map(str, currentPerson.usernames))) print("Emails(s):" + "\n" .join(map(str, currentPerson.emails))) print("\n") ``` ```ruby require 'pipl' response = Pipl::client.search email: 'clark.kent@example.com', first_name: 'Clark', last_name: 'Kent', api_key: 'YOURKEY' ``` ```java import com.pipl.api.search.SearchAPIRequest; import com.pipl.api.search.SearchAPIResponse; import com.pipl.api.search.SearchConfiguration; SearchAPIConfiguration configuration = new SearchConfiguration(); configuration.setProtocol("https"); configuration.apiKey = 'YOURKEY' SearchAPIRequest request = new SearchAPIRequest.Builder().email("clark.kent@example.com").firstName("Clark").lastName("Kent").configuration(configuration).build(); SearchAPIResponse response = request.send(); ``` ```php api_key = 'YOURKEY'; $configuration->use_https = true; $request = new PiplApi_SearchAPIRequest(array('email' => 'clark.kent@example.com', 'first_name' => 'Clark', 'last_name' => 'Kent'), $configuration); $response = $request->send(); ?> ``` ```csharp using Pipl.APIs.Search; SearchConfiguration searchConfiguration = new SearchConfiguration(apiKey: "YOURKEY",url: "api.pipl.com/search/", useHttps: true); SearchAPIRequest request = new SearchAPIRequest(email: "clark.kent@example.com", firstName: "Clark", lastName: "Kent", requestConfiguration: searchConfiguration); SearchAPIResponse response = await request.SendAsync(); ``` ```bash curl https://api.pipl.com/search/\?email=clark.kent@example.com\&key=YOURKEY ``` You can query with email addresses, phone numbers, usernames, names, addresses, age, or other attributes. Please review the full API reference. ## 4. Work with the results When your search is unique—such as entering an email address, social profile, or a very unique name—the search [response](/reference/response) will contain a **single person object**. This indicates that we've confidently matched your search parameters to a single, real-world person. The response will look like this: ```json { ... "person": {a person object}, ... } ``` If we cannot match your search to a single person, the [response](/reference/response) will contain a **list of possible persons**. This can happen if, for example, you searched for a common name such as `John Smith`. This list of people will be prioritized and ordered in descending order by a @match score, representing the confidence level that each result is the person you're looking for. ```json { ... "possible_persons": [{a person object}, {a person object}, ... , {a person object} ], ... } ``` The person objects in the response hold the actual data fields. ## 5. Learn More! [The API Reference](/reference/overview) is the best resource for learning about using the Pipl Search API. [The Pipl Search API Integration Checklist](pipl-search-api-integration-checklist) walks through the steps and tips for integrating the Pipl Search API [The Pipl Search Basic Workflow Diagram](general-application-flow-diagram) shows a simple coding workflow using the Pipl Search API. --- ## MCP Server Pipl provides an [MCP Server](https://modelcontextprotocol.io/) that connects the Pipl Search API to AI assistants like **Cursor**, **Claude Desktop**, **Windsurf**, and any other MCP-compatible client. Once configured, you can run identity searches using natural language — instead of writing API calls or switching to Postman, you can ask your assistant things like *"Search for john.smith@example.com"* and get full identity results inline. You can connect in two ways: - **Remote MCP (recommended)** — hosted by Pipl at [`https://mcp.pipl.com/search/`](https://mcp.pipl.com/search/). No install, no local Node.js, always up to date. - **Local MCP** — run the open-source server from [GitHub](https://github.com/piplcom/piplapis-search-mcp) on your own machine. Useful for offline development, air-gapped environments, or when you want to extend the server. Both options expose the same Search tools and require only a valid Pipl API key. ## What You Can Do The MCP server exposes the full power of the Pipl Search API through a set of purpose-built tools: | Tool | Description | |------|-------------| | `search_by_email` | Search by email address | | `search_by_phone` | Search by phone number (international format, e.g. `+15551234567`) | | `search_by_name` | Search by name, optionally combined with email, phone, or address | | `search_by_address` | Search by physical address | | `search_by_username` | Search by social username (e.g. `superman@facebook`) | | `search_by_url` | Search by social profile URL (e.g. LinkedIn, Facebook) | | `search_by_search_pointer` | Follow up on a previous result using a search pointer | | `search_by_person` | Advanced search with a structured person JSON object | | `search_raw` | Raw API call with any combination of parameters | Each tool returns identity data including names, emails, phone numbers, addresses, jobs, education, social profiles, and more. ## Prerequisites - A **Pipl API key** — sign in at [search.pipl.com/api/manage/keys](https://search.pipl.com/api/manage/keys), or [contact Pipl](https://pipl.com/contact-us) to get access - **Node.js** 18 or later — *only required for the local MCP option* ## Option 1: Remote MCP (Recommended) The remote MCP is hosted by Pipl at **`https://mcp.pipl.com/search/`** and serves the Pipl Search product. Authentication is handled per-request by passing your API key as a Bearer token in the `Authorization` header. ### Cursor IDE Open **Cursor Settings > MCP**, or edit `~/.cursor/mcp.json` directly: ```json { "mcpServers": { "pipl": { "url": "https://mcp.pipl.com/search/", "headers": { "Authorization": "Bearer YOUR_PIPL_API_KEY" } } } } ``` ### Claude Desktop Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows): ```json { "mcpServers": { "pipl": { "url": "https://mcp.pipl.com/search/", "headers": { "Authorization": "Bearer YOUR_PIPL_API_KEY" } } } } ``` Replace `YOUR_PIPL_API_KEY` with your Pipl API key. Restart your MCP client for the changes to take effect. :::tip Why use the remote MCP You don't need to clone a repo, install Node.js, or rebuild after updates — new tools and fixes are deployed automatically. ::: ## Option 2: Local MCP (Self-Hosted) Prefer to run the MCP server on your own machine? Clone the open-source server from GitHub: ```bash git clone https://github.com/piplcom/piplapis-search-mcp.git cd piplapis-search-mcp npm install ``` ### Cursor IDE Open **Cursor Settings > MCP**, or edit `~/.cursor/mcp.json` directly: **macOS / Linux:** ```json { "mcpServers": { "piplapis-search": { "command": "node", "args": ["/absolute/path/to/piplapis-search-mcp/index.js"], "env": { "PIPL_API_KEY": "YOUR_PIPL_API_KEY" } } } } ``` **Windows:** ```json { "mcpServers": { "piplapis-search": { "command": "node", "args": ["C:\\Users\\username\\piplapis-search-mcp\\index.js"], "env": { "PIPL_API_KEY": "YOUR_PIPL_API_KEY" } } } } ``` Restart Cursor for changes to take effect. ### Claude Desktop Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows): ```json { "mcpServers": { "piplapis-search": { "command": "node", "args": ["/absolute/path/to/piplapis-search-mcp/index.js"], "env": { "PIPL_API_KEY": "YOUR_PIPL_API_KEY" } } } } ``` Replace `/absolute/path/to/` with the actual path to the cloned repository and `YOUR_PIPL_API_KEY` with your Pipl API key. :::tip Security The API key is read from the `PIPL_API_KEY` environment variable and is never logged or exposed in tool outputs. ::: ## Use Cases ### Identity Lookup During Development While building onboarding, identity-enrichment, or investigation flows, ask your AI assistant to look up and connect real identity data without leaving the IDE: > *"Search for jane.doe@company.com and check if the name matches Jane Doe in San Francisco"* The assistant calls `search_by_email` (or `search_by_name` with email), returns the matched identity, and you can immediately see whether the name, location, and other attributes align — all without writing a single API call. ### Investigating Suspicious Users When reviewing flagged accounts or investigating fraud signals, pull up a complete identity profile in seconds: > *"Look up the phone number +14155550123 and show me all associated social profiles"* The assistant calls `search_by_phone`, returns names, emails, addresses, social URLs, and more — giving you a full picture of the person behind the number. ### Enriching Contact Data Enrich partial contact records by searching with what you have and getting back the full identity profile: > *"I have a LinkedIn profile linkedin.com/in/johndoe — find the person's email and phone number"* The assistant calls `search_by_url` and returns all available identity data associated with that profile. ### Resolving Ambiguous Matches When a search returns multiple candidates, use the search pointer to drill into a specific person: > *"Search for John Smith in New York"* If the API returns several possible persons, you can follow up: > *"Resolve the second candidate using their search pointer"* The assistant calls `search_by_search_pointer` to retrieve the full profile for that specific individual. ### Bulk Testing & Validation Use the `search_raw` tool for flexible queries during testing, or `search_by_person` for structured multi-field searches: > *"Search for a person with first name Clark, last name Kent, email clark.kent@example.com"* :::info Free Test Query Any query containing the email `clark.kent@example.com` is free and returns static example output — useful for testing your setup without consuming API credits. ::: ## Understanding Responses The Pipl Search API returns one of three outcomes: - **Person Match** — A single high-confidence person was found. This is a definitive match. - **Possible Persons** — Multiple candidates were found. Each includes a `@search_pointer` you can use with `search_by_search_pointer` to resolve a specific person. - **No Match** — No person found. :::warning Important A match score of `0` does **not** mean "no match" — it means the confidence level is undetermined (not enough data to rank). All returned possible persons are real candidates. ::: ## Resources - [Remote MCP Endpoint](https://mcp.pipl.com/search/) — hosted by Pipl - [Local MCP Server GitHub Repository](https://github.com/piplcom/piplapis-search-mcp) - [MCP Protocol Specification](https://modelcontextprotocol.io/) - [Pipl Search API Documentation](https://docs.pipl.com) - [API Reference](https://docs.pipl.com/reference) --- ## Integration Checklist As you integrate the Pipl Search API, you want to make sure that your integration is robust and optimized. This integration checklist is meant to help guide you through the process and make sure you covered all your bases. ## Optimizing Requests - [ ] Do you need [match criteria](/reference/match-criteria)? Set correctly to get as much useable data as possible - [ ] If multiple data fields can be used in a response, use the OR parameter - [ ] Use @type metadata for more granular filtering, if necessary - [ ] What [query parameters](/reference/using-search-parameters) are being sent to Pipl? - Generally, more info in the query leads higher match rate and data fill - [ ] Take a look at [some common search queries](/reference/using-search-parameters#common-search-queries) to get an idea for what you can include in a search query - [ ] Are you [optimizing for speed/throughput or maximum data fill]best-practices-by-use-case#performance-optimization) ? - [ ] Consider parameter [live_feeds=true](rate-limiting#live-feeds) for 2-3% more data fill, but with increased latency (1 to 2 seconds) and a maximum QPS of 10 (compared to 20 with live_feeds=false) - [ ] Have you implemented [query rate throttling](rate-limiting-your-queries)? - [ ] QPS limit (by default 20, 10 when live_feeds=true) - [ ] Review [Recommended libraries](rate-limiting-your-queries#how-to-best-implement-a-throttling-mechanism) - [ ] Are you validating data before sending? - [ ] Validate phone numbers using Google's libphonenumber (Pipl Search uses this). Raw phone numbers are in international format - [ ] Validate email format - [ ] Are you ensuring your queries meet [minimum requirements](/reference/request-overview#minimum-requirements)? ## Reading a Response - [ ] Are you taking advantage of [the source layer](/reference/know-your-sources)? - [ ] Set parameter show_sources=matching - [ ] Attributes data points in the response to their source - [ ] Use [Tags in the source layer](/docs/pipl-api-tags) for additional data such as professional skills and courses, vehicle info, NPI, home ownership, and death records - [ ] Are you keeping data in the order that Pipl returned it? - The data items in a Search response will be ordered by relevance and recency - [ ] Are you paying attention to [last seen and valid since dates](/reference/data-fields)? - [ ] Are you using the metadata @type(example: phone type= mobile vs work) - [ ] Can you handle null data fields? - If the response doesn’t have a data field, that field key will be removed. For example, if a response has no jobs, there will be no jobs key or field in the response. ## Processing and storing a query and response - [ ] How do you want to [handle possible person responses](/reference/response-types#how-to-handle-possible-person-responses)? - [ ] Show me the best possible person in the response ([parameter top_match](/reference/top_match-configuration-parameter)=true) - [ ] Don't show me possible person responses (parameter [minimum_match](/reference/match-criteria#minimum-match)=1) - [ ] Only show me possible persons above a certain threshold of match (parameter [minimum_match](/reference/match-criteria#minimum-match) between 0 and 1) - [ ] Dig deeper into possible person responses (use a two tiered search approach by searching on [the search pointer](/reference/search-pointer) of one or all of the possible persons) - [ ] Show me all possible persons (make no adjustments to configuration parameters) - [ ] Are you logging all queries made to the Pipl API? - [ ] Also log the @search_id for troubleshooting with Pipl - [ ] Do you have appropriate [error handling](/reference/errors) in your code? - [ ] Are you logging and reviewing warnings and errors returned by the Pipl Search API? - [ ] Review warnings in order to optimize searches (address or name was parsed wrong, a field was ignored because it was invalid) ## General - [ ] Have you tested your search flow using the non-billed example email, [clark.kent@example.com](mailto:clark.kent@example.com)? - [ ] Reach out to your Account Manager, Customer Success team or [contact customer support](https://pipl.com/customer-support) to answer any questions or review your search strategy --- ## Postman Collection Use Postman to test the Pipl Search API to troubleshoot query issues before integrating. To do this, [download and install Postman](https://www.postman.com/downloads/) and then [import](https://learning.postman.com/docs/getting-started/importing-and-exporting/importing-data#import-postman-data) the Pipl Search API Postman Collection. ## Configure Your Search API Key After importing the collection, open its **Authorization** tab and update the API key `value` with your own key. You can find your key on your [API Keys page](https://search.pipl.com/api/manage/keys). [Learn more about using Postman as an API testing tool](https://learning.postman.com/docs/getting-started/introduction/) --- ## Welcome to the Pipl Search API import { Card, CardGroup } from '@site/src/components/Card'; import { faRocket, faCode, faFlask, faDatabase, faGlobe, faTags, faWandMagicSparkles, faLightbulb, faGaugeHigh, faMagnifyingGlass, faLocationDot, faChartLine, faSitemap, faSliders, faImage, faBook, faClipboardList, faCircleQuestion, faEnvelope, faFileCode, faClockRotateLeft } from '@fortawesome/free-solid-svg-icons'; # About the Pipl Search API Pipl Search helps you gather information on customers and contacts to ensure that you are targeting the right people with the right content. This is useful across multiple use cases: - **Fraud Investigation & Risk** — Fraud / Risk Management, E-commerce, AML, Fintech. - **Investigation** — OSINT Platforms, Law Enforcement, Government, News Media, Risk Management, Cyber Security & Insurance. - **Consumer People Search** — Background reporting websites. - **Contact Enrichment** — Lead Enrichment, Recruitment, Real Estate and Sales Intelligence platforms. Medical Recruiting (US) & Marketing. Use the Pipl Search API to automate your searches and collect results into a format that is easily consumable by your website or application. If you need more detailed information on the API, see the [Pipl Search API Reference](/reference/overview). --- ## Get Started If you're new to Pipl Search, start here to set up your environment and make your first API call. Set up your API key and make your first search request. Official SDKs for Python, Ruby, Java, PHP, and C#. Ready-to-use code examples and sample programs for common API operations. Import our Postman collection for quick API testing. --- ## Learn About Pipl Data Understand the data types, sources, and capabilities of the Pipl Search API. Learn about the different data fields returned by the API. Discover where Pipl data comes from and how it's collected. Understand how Pipl infers additional data points. Use tags to get more data out of your integration. Access deceased info, marriage and divorce records, home ownership, and more. --- ## Best Practices Optimize your integration and get the most out of Pipl Search. Visual guide to the recommended integration flow. Tailored recommendations for contact enrichment, real estate, investigation, fraud prevention, and performance optimization. Understand and manage API rate limits effectively. Tips for getting the best results when searching by name. Optimize your address-based searches for better matches. Use Pipl data in machine learning models and identity investigation to make informed business decisions. --- ## Tutorials Step-by-step guides to help you master the Pipl Search API. Learn advanced search techniques including multiple fields, social profiles, VIN, CPF, NPI, job/education, relationships, and MD5 email searches. Display and use profile images in your application using the free Pipl Thumbnails API. --- ## Reference & Resources Complete API documentation with endpoints, parameters, and response formats. Ensure your integration follows all best practices before going live. Stay updated with the latest API changes, new features, and improvements. --- ## Support Find answers to frequently asked questions. Get help with technical issues, billing, or other support requests. --- ## Email Owner API Key Responses made from an Email Owner API key have the same basic response structure as other search API responses, but only can be queried by an email, and the name of the is returned (if available). Data coverage is similar to all other keys, including but live sources are not included. The Email Owner API key is used with the regular search endpoint (`https://api.pipl.com/search`), but a special key issued to your organization will tell the system that you're doing a Email Owner search. Email Owner is the Search-powered member of the **Pipl Elements** suite: it resolves the likely owner of an email address on the Pipl Identity Graph. Unlike Email Score and Email Intelligence, it is not powered by Elephant and does not return a Trust Score. ## **Practical Applications** *** The Email Owners key is intended for applications that require understanding of possible owners of a particular email address. If more data is needed than is included in the Email owner key response, one can opt to make the query using a regular Business key instead. ## **Main Characteristics** *** **Billing** – The Email Owner key, like any regular API key, is a Pay-Per-Match key, and both Person and Possible Persons responses are considered a match. **Use case** - Only an Identity Verification use case is permitted. **Query input** - Both parameter search and a Person search are permitted, but in the Person search, limited to a single email address in the search. Note that MD5 hash of an email address is permitted. **Data Coverage** – Responses return data from Pipl's indexes, however live sources are not available. **Data Types** – Only the data type of name is returned. Metadata tags such as @match, @valid_since and @last_seen are returned as well. In the query section, information about the Email address will be returned, including the type of email. See the [Email Search API reference](/reference/email) for a complete list of metadata that will be returned if available (prefixed with the @ sign). **Available Data** - The available data summary is not returned. **Configuration parameters** - No configuration parameters are permitted. By default any profile with a name will be returned by this key. **Testing** To test your key, you can query using your Email owner key with the email address '[clark.kent@example.com](mailto:clark.kent@example.com)' This query will not be charged and will return an API response that can be used for testing. **Response types** Only possible_person or no match responses will be returned for this key. **Errors and warnings** If an email address is not of valid format, and cannot be searched, an HTTP status code of 400 will be returned. --- ## Emails API Key Responses made from an Emails API key have the same basic response structure as other search API responses, but only the emails data field is returned (if available). Data coverage is similar to all other keys, including optional live sources. The Emails API key is used with the regular search endpoint (`https://api.pipl.com/search`), but a special key issued to your organization will tell the system that you're doing an Emails key search. ## **Practical Applications** *** The Emails key is intended for applications that require one or more email addresses but no other response elements. If more data is needed than is included in the Emails key response, one can opt to make the query using a regular Business key instead (either on the data elements used in the original query or on the search pointer that was returned for it.) ## **Main Characteristics** *** **Billing** – The Emails key, like any regular API key, is a Pay-Per-Match key. **Data Coverage** – Responses return data from Pipl's indexes, including optional live sources. **Data Types** – Only the data type of email is returned. Metadata tags such as @match, @valid_since and @last_seen are returned as well. **Available Data** - The available data summary returned is a reflection of what is available if the query were made with a Business key. **Configuration parameters** - All configuration parameters are supported according to the data that's available. By default any profile with an email will be returned by this key. [Match requirements](/reference/match-criteria) using [email subtypes](/reference/email) can further refine which profiles will be returned as matches. **Testing** To test your key, you can query using the email '[clark.kent@example.com](mailto:clark.kent@example.com)' This query will not be charged and will return an API response that can be used for testing. --- ## Phone Owner API Key Responses made from a Phone Owner API key have the same basic response structure as other search API responses, but only can be queried by a single phone number, and the name of the is returned (if available). Data coverage is similar to all other keys, including but live sources are not included. The Phone Owner API key is used with the regular search endpoint (`https://api.pipl.com/search`), but a special key issued to your organization will tell the system that you're doing a Phone Owner search. Phone Owner is the Search-powered member of the **Pipl Elements** suite: it resolves the likely owner of a phone number on the Pipl Identity Graph. Unlike Phone Score and Phone Intelligence, it is not powered by Elephant and does not return a Trust Score. ## **Practical Applications** *** The Phone Owner key is intended for applications that require understanding of possible owners of a particular phone number. If more data is needed than is included in the Phones owners key response, one can opt to make the query using a regular Business key instead. ## **Main Characteristics** *** **Billing** – The Phone Owner key, like any regular API key, is a Pay-Per-Match key, and only Possible Persons responses are considered a match. **Use case** - Only an Identity Verification use case is permitted. **Query input** - Both parameter search and a Person search are permitted, but in the Person search, limited to a single phone number in the search. **Data Coverage** – Responses return data from Pipl's indexes, however live sources are not available. **Data Types** – Only the data type of name is returned. Metadata tags such as @match, @valid_since and @last_seen are returned as well. In the query section, information about the Phone number will be returned, including the carrier of the phone number. See the [Phone Search API reference](/reference/phone) for a complete list of metadata that will be returned if available (prefixed with the @ sign). **Available Data** - The available data summary is not returned. **Configuration parameters** - No configuration parameters are permitted. By default any profile with a name will be returned by this key. **Testing** To test out this key, you can request a temporary testing key from your sales/account manager. Because this key only accepts phone numbers, the testing email address '[clark.kent@example.com](mailto:clark.kent@example.com)' will not work. **Response types** Only possible_person or no match responses will be returned for this key. **Errors and warnings** If a phone number is not valid and cannot be searched, an HTTP status code of 400 will be returned. --- ## Phones and Emails API Key Responses made from a Phones+Emails API key have the same basic response structure as other search API responses, but only the emails and phone numbers data fields are returned (if available). Data coverage is similar to all other keys, including optional live sources. The Phones+Emails API key is used with the regular search endpoint (`https://api.pipl.com/search`), but a special key issued to your organization will tell the system that you're doing a Phones+Emails key search. ## **Practical Applications** *** The Phones+Emails key is intended for applications that require one or more email addresses, phone numbers or both in the response but do not require other response elements. In case more data is needed than is provided in the Phones+Emails key response, one can make the query using a regular Business key instead (either on the data elements used in the original query or on the search pointer that was returned for it). ## **Main Characteristics** *** **Billing** - The Phones+Emails key, like any regular API key, is a Pay-Per-Match key, and both Person and Possible Persons responses are considered a match. **Data Coverage** - Responses return data from Pipl's indexes, including optional live sources. **Data Types** - Only the data types of [phone](/reference/phone) and/or [email](/reference/email) are returned. The meta data tags such as @match, @valid_since and @last_seen are returned. **Available Data** - The available data summary returned is a reflection of what is available when running on a Business key. **Configuration parameters** - All configuration parameters are supported according to the data that's available. By default any profile with either a phone or email will be returned by this key. [Match requirements](/reference/match-criteria) including with phone and email subtypes can further refine which profiles will be returned as matches. **Testing** To test your key, you can query using your phone+email key and the email '[clark.kent@example.com](mailto:clark.kent@example.com)' This query will not be charged and will return an API response that can be used for testing. --- ## Phones API Key Responses made from a Phones API key have the same basic response structure as other search API responses, but only the phones data field is returned (if available). Data coverage is similar to all other keys, including optional live sources. The Phones API key is used with the regular search endpoint (`https://api.pipl.com/search`), but a special key issued to your organization will tell the system that you're doing a Phones key search. ## **Practical Applications** *** The Phones key is intended for applications that require one or more phone numbers but no other response elements. If more data is needed than is included in the Phones key response, one can opt to make the query using a regular Business key instead (either on the data elements used in the original query or on the search pointer that was returned for it.) ## **Main Characteristics** *** **Billing** – The Phones key, like any regular API key, is a Pay-Per-Match key, and both Person and Possible Persons responses are considered a match. **Data Coverage** – Responses return data from Pipl's indexes, including optional live sources. **Data Types** – Only the data type of phone is returned. Metadata tags such as @match, @valid_since and @last_seen are returned as well. **Available Data** - The available data summary returned is a reflection of what is available if the query were made with a Business key. **Configuration parameters** - All configuration parameters are supported according to the data that's available. By default any profile with a phone will be returned by this key. [Match requirements](/reference/match-criteria) using [phone subtypes](/reference/phone) can further refine which profiles will be returned as matches. **Testing** To test your key, you can query using your phone key and the email '[clark.kent@example.com](mailto:clark.kent@example.com)' This query will not be charged and will return an API response that can be used for testing. --- ## Pipl Search Subscription Plan The subscription plan supports Pipl's customers in the contact enrichment space by subscribing you to a query result from Pipl Search for each of your contacts. It is a cost effective way to update and maintain a large list of contacts. You pay a monthly fee per enriched record for as long as you want to keep & update your database. A Pipl Search subscription entitles you to: 1. The Pipl Search result for all your subscribed contacts 2. Quarterly updates on all subscribed contacts for the duration of the subscription 3. Free, unlimited use of the [Teaser key](/docs/teaser-api) 4. Free, unlimited use of the [Summary key](/docs/summary-api) ## How it Works The Subscription API key is used with the regular search endpoint (`https://api.pipl.com/search`), but a special key issued to your organization. This same key will also be used for free quarterly updates. > 🚧 The [Pipl Search code libraries](/docs/code-libraries) do not currently support the Subscription plan. Responses made from a Subscription plan API key have the [same basic response structure](/reference/response) as other search API responses, but the only difference is that the search_pointer is replaced by an update_pointer for Person responses. The update_pointer can only be used with a Subscription plan key. Data coverage is the same as standard keys, including optional live sources. ![](/img/pipl-search-subscription-plan-1-Update_Key_Response.jpg) If a new query returns a match, then that query result will be added to your subscription. Queries using the update pointer will be counted toward your quarterly allotment of updates. Queries returning a [no match](/reference/response-types#no-match) or that do not meet [your match requirements](/reference/match-criteria#match-requirements) will not be counted towards your subscription. > 📘 Please note that all matches on the subscription key, except those using the update pointer, will add a contact to your subscription. If you send [duplicate queries](/docs/faq#how-do-you-bill-for-api-usage) without using the update pointer, each query that matches will be charged to your subscription. The subscription plan grants free, unlimited use of the Summary and Teaser keys. This can help you determine availability of data as well preview a "tease" of that data. Please note that the summary key doesn't differentiate between personal and work emails, so you would need to use the Teaser key for this. [Teaser key documentation](/docs/teaser-api) [Summary key documentation](/docs/summary-api) ## Plan Details **Billing** – All Subscription keys, like any regular API key, work similar to a Pay-Per-Match key, and both Person and Possible Person responses are considered a subscribed match. Please note: - Person responses will contain update_pointer instead of a search_pointer - Possible Person responses, will contain an update_pointer in the query section, and each Possible Person in the response will have search_pointer that can be used to [expand to a full person profile](/reference/response-types#how-to-handle-possible-person-responses). **Data Coverage **– Responses return data from Pipl's indexes, including optional live sources. **Data Types** – Data types returned are based on the Subscription plan key type used. Metadata tags such as @match, @valid_since and @last_seen are returned as well. **Available Data** - The available data summary returned is a reflection of what is available if the query were made with a Business key. This section of the response can also be seen using the [Summary key](/docs/summary-api) which is provided free of charge with the subscription plan. **Configuration parameters** - All configuration parameters are supported according to the data that's available for the key type used. It is recommended to use [match_requirements](/reference/match-criteria#match-requirements) to only subscribe to profiles that are relevant to the enrichment use case. ## Performing updates with the update pointer Subscription customers are entitled to free quarterly updates using the subscription key and the dedicated update_pointer parameter. Each quarter, you receive credit to update each contact you are subscribed to a single time. Each query that uses the update_pointer as a query input parameter will count towards your total allotment. Quarters are defined by month based on standard fiscal quarters (Q1 = January through March, etc.). This cadence lines up with Pipl's quarterly index updates. > 📘 Pipl sends email notifications each time we update our quarterly index, generally in the first month of each quarter. Your subscription record updates should be performed after this notification is sent to ensure the updates reflect the most recent data. > 🚧 We will count each update request (and reduce it from the quarterly limit of updates) - even if the update_pointer has already been requested several times. Your invoice reflects the number of contacts you are subscribed to. The update usage is not on your invoice, however. You can see through [your Pipl account](https://search.pipl.com/api/manage/usage) the number of remaining updates. ![](/img/pipl-search-subscription-plan-2-Update_Usage_Chart.jpg) ### Sending update pointer queries You may use all standard configuration parameters when running updates.It's recommended to run updates using minimum_match=1. Because update pointers can be very long, searches made with them should be made via POST with the update pointer included in the request body. Requests using GET or with POST and the search pointer embedded directly in the URL are likely to return HTTP 414 Request-URI too long errors. > 🚧 For most use cases, it's not recommended to run update_pointer requests returned from Possible Person responses. #### Example Replace UPDATE_POINTER_STRING with a valid update pointer and YOURKEY with a PIpl Search Key with an active subscription plan. ```curl curl -X POST https://api.pipl.com/search/ \ -d update_pointer='UPDATE_POINTER_STRING' \ -d key=YOURKEY ``` ## Testing To test your key, you can query using the email 'clark.kent@example,com' This query will not be charged and will return an API response that can be used for testing. ## Errors Please be sure to add error handling to your integration to accommodate for the following errors. | Status Code | Error Type | Error message | Description | Resolution | |-------------|------------|---------------|-------------|------------| | 400 | Reached Update Limit | Your updates have exceeded the limit. For more information, contact your account manager or our support team at [support@pipl.com](mailto:support@pipl.com) | You have run updates this quarter that meet your total number of subscribed records | Subscribe to more records or wait until the next quarter to update records. | | 400 | Invalid update_pointer or using an update_pointer on a non-subscription key | The provided parameter is not valid for this plan. | Update pointers and search pointers are not interchangeable. Attempting to use a search_pointer or anything other than an update pointer in the update_pointer query input parameter will result in this error. You will also see this error when trying to send the update pointer parameter in keys that are not subscription keys, or when sending an updated pointer that is not related to the plan (e.g sending a social plan update pointer to a business plan subscription key). | Make sure the API key you are using is valid and connected to an active subscription plan. Also make sure, if performing an update, that the update_pointer is a valid update_pointer. | | 403 | Subscription Expired | Your plan expired on 2019-04-08 04:59:59+00:00 | Your subscription expired | Contact your Pipl account manager to renew your Pipl Search subscription | --- ## Recruiter API Key Pipl's Recruiter Key API response is similar to a regular API response, except for certain data fields that are not shown. Data coverage is similar to the [Business key](https://pipl.com/api/pricing) including optional live sources. To use the Recruiter Key API, the regular API endpoint is used (`https://api.pipl.com/search`), but a special key issued to your organization will tell the system that you're doing a recruiter search. The data returned in the response will be structured the same as any regular key, but not all the fields will be included as well as some sub types as will be detailed below. ## Practical Applications The Recruiter key is intended for applications in which the response is used in order to provide only the relevant data fields to customers in the recruiting business . In case more data is needed than is provided in the Recruiter response, one can opt to use a regular Business key using the initial data or a [search-pointer](/reference/search-pointer) as the search base. The response, although partial, is designed to provide enough information to reliably identify the individual, and get a good overview of a person. ## Main Characteristics **Billing** – The Recruiter key, like any regular API key, is a Pay-Per-Match key. **Data Coverage** – Responses return data from Pipl's premium indexes, including optional live sources. **Data Types** – Not all data types are returned and not all data subtypes are returned. The meta data tags such as @match, @valid_since and @last_seen are returned. **Available Data** - The available data summary returned is a reflection of what is available when running on a Business key. The actual counts for data fields returned in the response may differ. **Configuration parameters** - All configuration parameters are supported according to the data that's available. The valid match_requirements fields that can be used are: name, address, phone (or phone.mobile), email.personal, images, education and job. Please note that if using email with the match requirements parameter, you must use the email.personal type. Using a match_requirement of just email (without the personal type) may return inconsistent results since the Recruiter key only returns personal emails. ## Field obfuscation behavior ### Gender > ❗️ Not shown ### Language > ❗️ Not shown ### Name > 👍 Always shown ### Relationship > ❗️ Not shown ### Address > 🚧 Partialy shown The city, state and country will always show. Street, house, apartment and zip code will not show, nor will there be an indication of their existence. ```json "addresses": [ { "@type": "work", "country": "US", "state": "TX", "city": "Austin", "display": "Austin, Texas" } ``` ### DOB > ❗️ Not shown ### Phone > 👍 Always shown ### Username > ❗️ Not shown ### UserID > 🚧 Partally shown If available, only LinkedIn user-id's will appear. ### Email > 🚧 Patially shown Only personal emails will be shown. Emails that do not have a subtype "personal" will not appear. ### Images > 👍 Always shown ### Education > 👍 Always shown ### Job > 👍 Always shown ### URL > 🚧 Partially shown If available, only Linkedin URLs will show --- ## Summary API Key The Pipl Summary API response is similar to a regular API response, however only the [header information](/reference/response) from the response is returned with no person nor possible_persons included. The information returned from a Summary API response includes: - The available_data summary - see [field count](/reference/field-count) - @persons_count - @available_sources - query Data coverage is similar to [Business Premium](http://pipl.com/api/pricing) key excluding live sources. To use the Summary API, the regular API endpoint is used (`https://api.pipl.com/search`), but a specialized key issued to your organization will tell the system that you're doing a summary search. ## Practical Applications The summary key is a way to discover the availability of data, but does not include the actual data returned in a full API response. This information is used to inform/tease a user of the availability of data which is then followed up by a Premium key call. ## Summary Key Example Below is an example of a SUMMARY key response after sending a request with the email [clark.kent@example.com](mailto:clark.kent@example.com) as the search query: ```json { "@http_status_code": 200, "@visible_sources": 0, "@available_sources": 3, "@persons_count": 1, "@search_id": "0", "query": { "emails": [ { "address": "clark.kent@example.com", "address_md5": "2610ee49440fe757e3cc4e46e5b40819" } ] }, "available_data": { "premium": { "relationships": 6, "usernames": 2, "jobs": 3, "addresses": 2, "ethnicities": 3, "phones": 1, "landline_phones": 1, "educations": 2, "languages": 1, "user_ids": 1, "social_profiles": 2, "names": 3, "dobs": 1, "images": 2, "genders": 1, "emails": 4, "work_emails": 2, "personal_emails": 1, "origin_countries": 1 } } } ``` ## Main Characteristics **Billing** - The API is billed per call (not per match). **Data Types** - @visible_sources will always be 0 as these are not revealed in the Summary API - If no information was found based on your search criteria, the available_data section will not appear in the JSON response. - The persons_count field will let you know if you received no match (persons_count = 0), a person result (persons_count = 1), or several possible persons in the result (persons_count >= 1). **Match criteria** - The _minimum_match_ and [top_match](/reference/top_match-configuration-parameter) configuration parameters may be used as a filter. The \_match_requirements \_and \_source_category_requirements \_parameters are not supported. **Data Coverage** – Responses return data from Pipl's index, but not from live sources. --- ## Teaser API Key The Pipl Teaser API response is similar to a regular API response, with some parts of the data obfuscated. Data coverage is similar to [Business Premium](https://pipl.com/api/pricing) excluding live sources. To use the Teaser API, the regular API endpoint is used (`https://api.pipl.com/search`), but a specialized key issued to your organization will tell the system that you're doing a teaser search. The data returned in the response can be obfuscated in 4 different visibility modes: Fully shown, masked, mentioned, and completely hidden. Each data field in the response is obfuscated differently, depending on the input provided in the search request. ## Practical Applications The Teaser key is intended for applications in which the response is used in order to provide a preview of the data to end users, usually before conversion. Following conversion, a regular API request can be made to retrieve the full response. The response, although obfuscated, is designed to provide enough information to reliably identify the individual, and get an overview of what can be retrieved from a full API request. Once a person from the teaser response is identified, it is straightforward to use the [Search pointer](/reference/search-pointer) to run a follow up full API request. ## Main Characteristics **Billing** – The Teaser key, unlike regular API keys, is a Pay-Per-Call key. **Data Coverage** – Responses return data from Pipl's basic and premium indexes, but not from live sources. **Data Types** – All data types may be returned (same as a Business key). The meta data tags such as @match, @valid_since and @last_seen are not returned in the Teaser response. **Obfuscation** - The search input data is _always_ fully visible in the response. Other data fields are shown based on the kind of search that has been executed (details below). **Configuration parameters** - No match criteria parameters are available except for _minimum_match_ which is used as a filter. Neither the _match_requirements_ nor _source_category_requirements_ parameters are supported. Additionally, the _show_sources_ parameter is not supported. ## Obfuscation The obfuscation model has 4 visibility modes: **Shown** – Data field is fully shown, as in the regular API response. **Masked** – Partial information is shown: Strings are fully or partially masked with "\*" With numbers, the last four digits of the number are replaced with 0. **Mention** – Availability of field is shown, but no actual information is given. Strings are converted to "value available in full api response". **Hidden** – The field is not displayed at all. Note that some fields are obfuscated differently depending on the query input. ## Field obfuscation behavior ### Gender > 👍 Always shown ### Language > 👍 Always shown ### Name > 📘 Shown or masked Name and relationship fields behave differently depending on the data sent in the request: Shown only when name is sent in the request. In all other cases it is masked. Masking is done by showing only the first letter of a first and middle name followed by 4 asterisks'. The last name is completely masked (i.e. all asterisks'). ```json "names": [ { "first": "H****", "last": "****", "display": "H**** ****" } ``` ### Relationship > 📘 Shown, masked or mentioned Shown only when name is sent in the request. When address is sent in the request all data in the relationship field is masked. In all other cases data in the relationship field is mentioned. Masking is done the same way name is masked (see above). ```json "relationships": [ { "@type": "value available in full api response", "names": [ { "first": "value available in full api response", "last": "value available in full api response", "display": "value available in full api response" } ``` ### Address > 🚧 Always masked The city, state and country will always show. Street, house, apartment and zip code will be mentioned. ```json "addresses": [ { "@type": "work", "country": "US", "state": "TX", "city": "Austin", "street": "value available in full api response", "house": "value available in full api response", "apartment": "value available in full api response", "zip_code": "value available in full api response", "display": "Austin, Texas" } ``` ### DOB > 🚧 Always masked Age is displayed. Exact date is not shown. ```json "dob": { "display": "36 years old" } ``` ### Phone > 🚧 Always masked The last 3 digits of phone are replaced with 000. If there is an extension, it will be removed. ```json "phones": [ { "type": "home_phone", "country_code": 1, "number": 9785556000, "display": "978-555-6000", "display_international": "978-555-6000" } ``` ### Username > 🚧 Always masked The first two characters of the username are shown followed by 4 asterisks. ```json "usernames": [ { "content": "ab****" } ``` ### UserID > 🚧 Always masked The first two characters of the user id are shown followed by 4 asterisks. The domain of the service will always show. ```json "user_ids": [ { "content": "12****@facebook" } ``` ### Email > 🚧 Always masked The first two letters of the local-part are shown followed by 4 asterisks. The domain will show only the first letter of the domain followed by 4 asterisks. ```json "emails": [ { "@type": "work", "@email_provider": false, "address": "cl****@h****.com", "address_md5": "eb3e11de3c9cefc2d9d70972350e2b28" } ``` ### Vehicles > 🚧 Always masked Make, model year and type are always shown. Vin will be mentioned. ```json "vehicles": [ { "vin": "value available in full api response", "year": "2002", "make": "ford", "model": "f150", "type": "pickup", "display": "value available in full api response" } ] ``` ### Images > 🚧 Always masked The textual results that are returned in the Teaser's json response can be easily parsed and displayed. To get the image you will need to call [Pipl's thumbnail server](/docs/thumbnails) with the image token from the Teaser's json response. The returned image will be a 100x100 pixels blurred image. ```json "images": [ { "thumbnail_token": "AE2861B242686E7BD0CB4D9049298EB7D18FEF66D950E8AB78BCD3F484345CE74536C19A85D0BA3D32DC9E7D1878CD4D341254E7AD129255C6983E6E154C4530A0DAAF665EA325FC0206F8B1D7E0B6A3AC92AD25ACB21DDC6CD20BE7D82734DAE4C8B5" } ], ``` #### Regular image vs. Teaser image ![Regular image](/img/teaser-api-1-CKent_Premium.png) ![Teaser image](/img/teaser-api-2-CKent_Teaser.png) ### Education > ❗️ Always mentioned ```json "educations": [ { "school": "value available in full api response", "display": "value available in full api response" }, { "degree": "value available in full api response", "school": "value available in full api response", "display": "value available in full api response" } ``` ### Job > ❗️ Always mentioned ```json "jobs": [ { "title": "value available in full api response", "organization": "value available in full api response", "industry": "value available in full api response", "display": "value available in full api response" } ``` ### URL > ❗️ Always mentioned All the details of the URL are shown except for the actual URL. ```json "urls": [ { "@source_id": "edc6aa8fa3f211cfad7c12a0ba5b32f4", "@domain": "linkedin.com", "@name": "LinkedIn", "@category": "professional_and_business" } ``` --- ## How to Manage API Keys ## Creating new keys As an administrator you can create additional Contact, Social and/or Business keys on your [API keys page](https://search.pipl.com/api/manage/keys/). Simply navigate to the bottom of the page, and click on the "+ New Search Key" button to add a new key. ![](/img/new_api_key.png) - The "+ New Search Key" button will only be available if you have a working credit card on the account or alternate arrangement with Pipl billing. - If you are contracted to any other type of key besides a standard Contact, Social or Business key, such as a package key, these keys cannot be created on this page. Please reach out to [Pipl support](https://pipl.com/contact-us) and/or your Account Manager. ## Deactivating a Key To deactivate an API key, simply hover over the key, click the three lines to the right of the key and select "Deactivate" from the popup menu. This will disable any use to the API key and result in HTTP status 403 errors being returned for any subsequent queries on the key. ![](/img/deactivate_key.png) Pipl recommends that you disable an API key if you suspect any misuse or exposure of the key to anyone unauthorized to use it. See our [API key security best practices](/docs/api-key-security-best-practices). ## Other Relevant Topics - [API key security best practices](/docs/api-key-security-best-practices) to learn how to keep your keys safe - [Setting quotas on your API keys](/docs/monitoring-usage-and-spend) to help monitor your usage and spend - [Monitoring package key usage and spend](/docs/monitoring-package-key-usage-and-spend) --- ## Linking Social Username, User ID and URL In this short tutorial we’ll help you to determine the link between a [user ID](/reference/user-id), [username](/reference/username) and [URL](/reference/url) by activating and using the sources layer. Switching on [the sources layer](/reference/know-your-sources) with the configuration parameter “show_sources=matching” will allow you to see the sources used to build the profile. This layer lets you know where the data was sourced, and helps you determine the linkage between a user-id, username and URL. To connect the data fields of a single social profile, search the sources layer for the source that includes one of the data points of interest, such as a username. The other data fields (user ID and url) under this same source will be the fields that are connected together for this social profile. ## Example In the example below, we’ve highlighted the user-id, username and URL from a “Facebook” source which we acquired when we queried the Pipl API by email address [clark.kent@example.com.](mailto:clark.kent@example.com.) We were able to link the following data: - User-id: 11231@facebook - Username:clarkkent@facebook - URL: [http://facebook.com/clarkkent](http://facebook.com/clarkkent) ```text "@id": "5d836a4acc55922e49fc709c7a39e233", "@category": "personal_profiles", "@name": "Facebook", "@origin_url": "**http://facebook.com/clarkkent**", "@domain": "facebook.com", "@person_id": "9182cf87-5fd8-499a-91e5-3bf876405da8", "@match": 1.0, "names": [ { "first": "Clark", "last": "Kent", "display": "Clark Kent" } ], "usernames": [ { "content": "clarkkent@facebook" } ], "user_ids": [ { "content": "11231@facebook" } ], "phones": [ { "@type": "home_phone", "country_code": 1, "number": 9785550145, "display": "978-555-0145", "display_international": "+1 978-555-0145" } ], "gender": { "content": "male" } "tags": [ { "@valid_since": "2020-10-06", "@last_seen": "2020-10-06", "@classification": "followers", "content": "1957" }, { "@valid_since": "2020-10-06", "@last_seen": "2020-10-06", "@classification": "following", "content": "1735" } ] ``` --- ## Q3 2022 - Index Update Guess what? We've added a new update to the Pipl Search Identity Index with hundreds of millions of new data elements. - 210 million new international phone numbers - 110 million new international email addresses - Over 90 million new U.S. addresses with homeowners' information - 118 million updated international career profiles - Also included in these numbers is a big bump in Brazil—30 million new Brazilian profiles, bringing us to 242 million updated profiles with 30 million new CPFs, over 140 million new phone numbers and over 60 million new email addresses. _July 17, 2022_ --- ## Q4 2022 - Index Update Drumroll, please! Introducing our latest Pipl Search Identity Index update with the following content: - 127 million new international phone numbers - 111 million updated career profiles - 89 million new U.S. addresses with an additional 14 million properties with homeowner data - 18 million new US email addresses - 49 million new unique Brazilian CPFs - NEW! 113 million records updated with indication of being deceased _Oct 23, 2022_ --- ## Q1 2023 - Index Update Take a look! The Pipl Search Identity Index has been updated with the following content: - 68 million new international phone numbers (7.8 million U.S.) - 70 million new international email addresses - 145 million updated international career information records, including 21 million new Profiles and 52 million new Jobs - Improved international name quality _Jan 11, 2023_ --- ## Q2 2023 - Index Update It's time to unveil our latest index update for Q2 2023. It will include the following content: - 57 million new phone numbers (1.6 million U.S.) - 20 million new email addresses (15 million U.S.) - 111 million updated career information records, including 30 million new records - NEW! 4.5 million marriage and divorce records in the U.S. - 76 million U.S. records with updated residential, deceased, and home owner information. - improved address quality and ordering _April 14, 2023_ --- ## Q3 2023 - Index Update Summer is here and so is our latest index update for Q3 2023. It will include the following content: - 54 million new phone numbers (~2.5 million in the U.S.) - 21 million new email addresses (~14 million in the U.S.) - 118 million updated career information records, including 40 million new records - 11 million new vehicle information records - 97 million U.S. records with updated residential, deceased, and homeowner information _July 4 2023_ --- ## Q3 2023 - New Features and SDK Update We're bursting with excitement to share some incredible news that's about to level up your Pipl Search API experience! 🚀 Introducing our latest feature release which includes a new vehicle field, a VoIP indicator for phone numbers, an expanded available data section, and new updates to our SDKs. ## New Vehicle Field [Vehicles](/reference/vehicle) are being added as a new field in the Search API response. Vehicles in the response can include the VIN, make, model, year and type. **Example Vehicle Object** ```json { "@valid_since": "2008-01-01", "vin": "1ftrx18wx2nb71717", "year": "2002", "make": "ford", "model": "f150", "type": "pickup", "display": "1ftrx18wx2nb71717-2002-ford-f150-pickup" } ``` The new field has a dedicated array in the response and is included in the available data section. ```json "available_data": { "premium": { "relationships": 22, "usernames": 4, "jobs": 19, "addresses": 15, "phones": 10, "mobile_phones": 1, "landline_phones": 9, "educations": 2, "languages": 1, "user_ids": 9, "social_profiles": 10, "vehicles": 2, // <----------- Here is the new field count "names": 2, "dobs": 1, "images": 4, "genders": 1, "emails": 6, "work_emails": 4, "personal_emails": 2 } ``` If you have already been getting vehicles from the tag layer, you can continue using this method. ### Searching by VIN Search using a VIN number by using the new `vin` query parameter. VIN can be included together with other query parameters or in a full person search. **Example VIN query** ``` https://api.pipl.com/search/?key=YOUR_KEY&vin=JNKBV61EX7M710824 ``` You can also continue using VIN search using the username parameter. ## Expanded Available Data Section The available data section of a response will now give you increased insight into the types and sub-types of fields in a response. We have added indicators for the following: - vehicles - work emails - personal emails - voip phones **Example available data** ```json "available_data": { "premium": { "usernames": 2, "jobs": 9, "addresses": 2, "emails": 3, "work_emails": 2, // New! "personal_emails": 1, // New! "educations": 3, "user_ids": 3, "phones": 4, "mobile_phones": 1, "voip_phones": 1, // New! "landline_phones": 2, "vehicles": 1, // New! "social_profiles": 2, "names": 1, "genders": 1 } } ``` ## VoIP Phones Indicator Phone numbers that are VoIP (voice-over-IP) will now include an indicator in the metadata using the field `@voip`. **Example VoIP phone** ```json { "country_code": 1, "number": 9785550145, "@voip": true, "display": "(512) 555-0123", "display_international": "+1 512-555-0123" } ``` ### VoIP Match Requirements You can add VoIP phones as a match requirement for your API queries. You can combine this with other criteria or use it on its own: - `match_requirements=phone.voip` - `match_requirements=phone.voip OR social_profiles` ## SDK/Code Library Updates The Search API SDKs have been updated. In addition to adding support for new features, we have also updated our software version supports. ### New Features - Added support for the new `vehicle` field - Add option to search with VIN - Add option to search with match requirements of VoIP phones - `match_requirements=phone.voip` ### Updated Software Support The Search API Code Libraries have been updated to support new software versions: - Python from 3.7 and above - Ruby from 3.0 and above - PHP from 8.0 and above - DotNet (C#) from v6.0 and above - Java from 8 and above _Sept 27, 2023_ --- ## Q4 2023 - Index Update It's a great day to use Pipl! Gearing up for 2024 we've added a lot more data to the Pipl Identity Index. **Index Update:** - 220 million updated career information records, including 37 million new records - 80 million U.S. records with updated residential, deceased, marriage, divorce and homeowner information - 52 million new phone numbers (~1.5 million in the U.S.) - 18 million new email addresses (~14 million in the U.S.) - 11 million new U.S. vehicle information records --- ## Q1 2024 - Index Update New year, new data! We're excited to release a new index update with a lot of new data: - 70 Million new phone numbers (~7 million in the U.S.) - 55 Million new email addresses (~44 million in the U.S.) - 3 Million new vehicles - 170 Million New Career information - 160 Million US records with updated residential, deceased, marriage, divorce, and homeowner information --- ## Q2 2024 - Index Update We're excited to release a new index update with a lot of new data: - 110 Million new phone numbers (~4 million in the U.S.) - 15 Million new email addresses (~6 million in the U.S.) - 3 Million new vehicles - 220 Million Updated Career information - 40 Million US records with updated residential, deceased, marriage, divorce and homeowner information --- ## Q3 2024 - Index Update We're excited to release a new index update with a lot of new data: - +81 Million new phone numbers (~4 million in the U.S.) - +10 Million new email addresses (~3.8 million in the U.S.) - +1 Million new US vehicles - +207 Million Updated Career information - +12 Million US records with updated residential address, deceased, marriage, divorce, and homeowner information The current stats of the new index are: - Over 4.5 Billion Unique Phone numbers - Over 2.1 Billion Unique Email addresses --- ## Q4 2024 - Index Update We're excited to release a new index update with a lot of new data: - +150 Million new phone numbers (~4.6 million in the U.S.) - +16 Million new email addresses (~9 million in the U.S.) - +3 Million new US vehicles - +150 Million Updated Career information - +96 Million US records with updated residential address, deceased, marriage, divorce, and homeowner information The current stats of the new index are: - Over 4.7 Billion Unique Phone numbers - Over 2.2 Billion Unique Email addresses --- ## 2025 - Year-End Data Highlights In taking a moment to reflect on the incredible strides made in 2025 to strengthen your ability to uncover and trust identity information. This past year, we focused on one goal: giving you most accurate, complete, and current data to help you move faster and make better-informed decisions. That effort resulted in an incredible year of growth and coverage enhancements to Pipl Search, updates you're already benefiting from today. 2025 Data Enhancements: - 490 million NEW phone numbers (49 million in the U.S.) - 141 million NEW email addresses (63 million in the U.S.) - 110 million NEW career records - 54 million NEW U.S. vehicle records - 1.2 million NEW Brazilian CPF records - 238 million UPDATED career records - 194 million UPDATED U.S. records (residential, deceased, marriage, divorce, and homeowner data) Our current global index now includes: - over 5.3 billion phones, and - over 2.3 billion emails --- ## Q1 2025 - Index Update It's a new year, and we're excited to release a new index update with a lot of new data: - +151 Million new phone numbers (~4 million in the U.S.) - +98 Million new email addresses (~23 million in the U.S.) - +98 Million newly added U.S. vehicles - +264 Million updated career records - +18 Million U.S. records updated – including residential addresses, deceased status, marriage/divorce data, and homeowner information Our current index now includes: - Over 4.9 Billion unique phone numbers - Over 2.2 Billion unique email addresses --- ## Q2 2025 - Index Update We're excited to release a new index update with a lot of new data: - +158 million new phone numbers (~3.5M in the U.S.) - +40 million new email addresses (~2.6M in the U.S.) - +30 million newly added U.S. vehicles - +133 million updated career records - +95 million refreshed U.S. identity records (including address, deceased status, marital, and homeowner details) Our current index now includes: - Over 5 Billion unique phone numbers - Over 2.2 Billion unique email addresses --- ## Q3 2025 - New Feature Update We're excited to release a new metadata feature to [phone numbers](/reference/phone). The @carrier component of a phone will return name of the telecommunications carrier or service provider associated with the phone number. This can be for example a mobile carrier (e.g. "AT&T", "T-Mobile"), a landline provider, or a VoIP service. --- ## H1 2026 - Index Update Here's a snapshot of what we've achieved in the first half of 2026: - +166 million new phone numbers (~11.5M in the U.S.) - +55 million new email addresses (~37M in the U.S.) - +20 million new and +621 million updated career records - +21 million U.S. records refreshed (residential address, deceased status, marriage, divorce, and homeowner details) - +1 million new Brazilian CPFs Our current index now includes: - Over 5.4 billion unique phone numbers - Over 2.4 billion unique email addresses ## New: Pipl Search API via MCP The Pipl Search API is now available through a Model Context Protocol (MCP) server, enabling AI assistants and agentic applications to access Pipl's identity search capabilities through a standardized integration framework. This makes it easier than ever to bring trusted identity data into AI-powered workflows. See [MCP Server](/docs/mcp-server) to get started. --- ## Q3 2026 - Index Update As we wrap up Q3, we're excited to share our latest data coverage enhancements, now live across the Pipl index. This release marks another step in our ongoing effort to provide accurate, comprehensive, and up-to-date identity data globally. Over the past quarter, we've continued to expand our coverage with new data while refreshing hundreds of millions of existing records to keep our results current and relevant. Here's a snapshot of the latest enhancements: - +97 million new phone numbers (~3M in the U.S.) - +62 million new email addresses (~23M in the U.S.) - +20 million new career records - +500 million updated career records - +16 million U.S. records refreshed, including updates to residential addresses, deceased status, marriage, divorce, and homeowner details - +500K new Brazilian CPFs With this release, the Pipl index now includes: - 📱 More than 5.6 billion unique phone numbers globally - 📧 More than 2.45 billion unique email addresses globally --- ## Using Tags # What are tags? [Tags](/reference/tag) hold additional information about a person and their attributes. Examples of tags associated with a given person include: - Information about a their holdings such as auto models (auto make, VIN) - Skills and interests - Domains they own - Number of Twitter followers / users they follow Tags returned in the Pipl API response contain data that do not fit into the [person object](/reference/person) model. Tags are classified based on the type of information they contain, and the content may be unstructured free text. # How to Enable Tags Tags may appear in individual source objects in the [source array](/reference/source). To see tags in the response, make sure that the sources layer is enabled by using the codeshow_sources/code parameter in the search request (with the relevant value for your use case). > 📘 NOTE > > You can't use tags as input into search queries, or with the **match requirement** field. # Popular tag classifications Use the following table to assist you in discovering popular tag classifications. | **Tag Data** | **Source Name(s)** | **Tag classification(s)** | **Sample value(s)** | | -------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------ | -------------------------------------------------------- | | Professional credentials and accomplishments | LinkedIn | skill, course, group, volunteering | `Microsoft Office``Python developers unite` | | Social media follower and following count | Twitter, Instagram, Pinterest, Tiktok, Soundcloud, Github, Vimeo, VK, Foursquare, Academia, Medium, Strava | following, followers | `212``44` | | Vehicle information | Auto Owner\* | auto year, auto make, auto model, auto vin | `2013``FORD``MONDEO``1ABC21Z39EF90123` | | Website ownership information | Domain Owner\* | associated domain | `[www.thiscoolwebsite.com](http://www.thiscoolwebsite.com)` | | Death information | Deceased Residents, FindAGrave | death_date, deceased, burial address | `2003-11-20``yes``Honolulu``Honolulu County``Hawaii``USA` | | Home ownership information | Residential Property, Trust Property | last_sale_date, apn, type | `2020-05-25``12-07980-00G-009-00-00``estate` | | NPI (National Provider Identifier) | NPPES NPI Registry | nppes_npi_license | `License Number: MD463765``Registered State: TN``Taxonomy Classification: Allopathic & Osteopathic Physicians``Taxonomy Specialization: Pediatrics` | | Marriage and divorce data | US Marriage Records, US Divorce Records | marriage_date, divorce_date | `2019-03` | > 📘 NOTE > > \* For certain sources, the source name may not be exactly as specified in the table above, but may be similarly named. Check that the string contains the content, and do a case insensitive comparison. # Example This example illustrates how tags may appear in a source object in the sources array. This includes different classifications of tags such as codeskill/code, codegroup/code and codeauto make/code. ```json "sources": [ { "@id": "4275e03c9c99953245c426dd74cd61c5", "@category": "professional_and_business", "@name": "LinkedIn", "@origin_url": "http://www.linkedin.com/in/theman", "@domain": "linkedin.com", "@person_id": "a0f13c3c-bcd9-4133-979c-9f2ba05decf8", "@match": 1.0, "names": [... ], "usernames": [... ], "tags": [ { "@valid_since": "2015-09-01", "@last_seen": "2016-08-26", "@classification": "skill", "content": "Microsoft Office" }, { "@valid_since": "2015-09-01", "@last_seen": "2016-08-26", "@classification": "skill", "content": "Python" }, { "@valid_since": "2015-09-01", "@last_seen": "2016-08-26", "@classification": "group", "content": "Python developers unite" }, { "@valid_since": "2016-01-22", "@last_seen": "2016-08-26", "@classification": "volunteering", "content": "Chef at Home for the Homeless" }, { "@valid_since": "2016-07-22", "@last_seen": "2016-08-26", "@classification": "course", "content": "Python for pros" }, { "@valid_since": "2017-06-01", "@last_seen": "2017-06-01", "@classification": "auto make", "content": "FORD" }, { "@valid_since": "2017-06-01", "@last_seen": "2017-06-01", "@classification": "auto model", "content": "MONDEO" }, { "@valid_since": "2017-06-01", "@last_seen": "2017-06-01", "@classification": "auto vin", "content": "1ABC21Z39EF90123" }, { "@valid_since": "2018-04-15", "@classification": "marriage_date", "content": "2018-04" } { "@valid_since": "2015-02-05", "@classification": "home_owner_lives_in_property", "content": "True" }, { "@valid_since": "2015-02-05", "@classification": "last_sale_date", "content": "2015-02-05" }, { "@valid_since": "2015-02-05", "@classification": "apn", "content": "0500667" } ] ``` --- ## Advanced Search Queries import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; Below are some examples for running some more advanced queries ### Multiple Phones, emails or Addresses Using multiple instances of a particular data field in a search query requires using a [full person search](/reference/full-person) ```text person= { "names": [ { "first": "Clark", "last": "Kent" } ], "addresses": [ { "city": "Metropolis", "state": "IL", "country": "US" }, { "city": "Wichita", "state": "KS", "country": "US" } ], "emails": [ { "address": "clark.kent@example.com" }, { "address": "ckent@hotmail.com" } ], "phones": [ { "raw": "+1(312) 684-5000" }, { "raw": "(312) 352-9327" } ] } ``` ```http https://api.pipl.com/search/?key=YOUR_KEY&show_sources=matching&person={ "names": [ { "first": "Clark", "last": "Kent" } ], "addresses": [ { "city": "Chicago", "state": "IL", "country": "US" }, { "city": "Wichita", "state": "KS", "country": "US" } ], "emails": [ { "address": "clark.kent@example.com" }, { "address": "ckent@hotmail.com" } ], "phones": [ { "raw": "+1(312) 684-5000" }, { "raw": "(312) 352-9327" } ] } ``` ```python from piplapis.data import Person, Name, Address, Email, Phone from piplapis.search import SearchAPIRequest fields = [ Name(first=u'Clark', last=u'Kent'), Address(city=u'Chicago', state=u'IL', country=u'US'), Address(city=u'Wichita', state=u'KS', country=u'US'), Email(address=u'clark.kent@example.com'), Email(address=u'ckent@hotmail.com'), Phone(raw=u'+1(312) 684-5000'), Phone(raw=u'(312) 352-9327') ] request = SearchAPIRequest(person=Person(fields=fields), api_key='YOUR_KEY', show_sources='matching') response = request.send() ``` ```ruby require 'pipl' person = Pipl::Person.new person.add_field Pipl::Name.new(first: 'Clark', last: 'Kent') person.add_field Pipl::Address.new(city: 'Chicago', state: 'IL', country: 'US') person.add_field Pipl::Address.new(city: 'Wichita', state: 'KS', country: 'US') person.add_field Pipl::Email.new(address: 'clark.kent@example.com') person.add_field Pipl::Email.new(address: 'ckent@hotmail.com') person.add_field Pipl::Phone.new(raw: '+1(312) 684-5000') person.add_field Pipl::Phone.new(raw: '(312) 352-9327') response = Pipl::client.search person: person, api_key: 'YOUR_KEY', show_sources: 'matching' ``` ```java import java.util.ArrayList; import java.util.List; import com.pipl.api.search.SearchAPIRequest; import com.pipl.api.data.containers.Person; import com.pipl.api.data.fields.*; import com.pipl.api.search.SearchConfiguration; SearchConfiguration configuration = new SearchConfiguration(); configuration.setProtocol("https"); configuration.apiKey = "YOUR_KEY"; configuration.showSources = "matching"; List fields = new ArrayList(); fields.add(new Name.Builder().first("Clark").last("Kent").build()); fields.add(new Address.Builder().city("Chicago").state("IL").country("US").build()); fields.add(new Address.Builder().city("Wichita").state("KS").country("US").build()); fields.add(new Email.Builder().address("clark.kent@example.com").build()); fields.add(new Email.Builder().address("ckent@hotmail.com").build()); fields.add(new Phone.Builder().raw("+1(312) 684-5000").build()); fields.add(new Phone.Builder().raw("(312) 352-9327").build()); Person person = new Person(fields); SearchAPIRequest request = new SearchAPIRequest(person, configuration); SearchAPIResponse response = request.send(); ``` ```php use_https = true; $configuration->api_key = 'YOUR_KEY'; $configuration->show_sources = 'matching'; $fields = array( new PiplApi_Name(array("first" => "Clark", "last" => "Kent")), new PiplApi_Address(array("city" => "Chicago", "state" => "IL", "country" => "US")), new PiplApi_Address(array("city" => "Wichita", "state" => "KS", "country" => "US")), new PiplApi_Email(array("address" => "clark.kent@example.com")), new PiplApi_Email(array("address" => "ckent@hotmail.com")), new PiplApi_Phone(array("raw" => "+1(312) 684-5000")), new PiplApi_Phone(array("raw" => "(312) 352-9327")) ); $person = new PiplApi_Person($fields); $request = new PiplApi_SearchAPIRequest(array('person' => $person), $configuration); $response = $request->send(); ?> ``` ```csharp using Pipl.APIs.Search; using System.Collections.Generic; SearchConfiguration searchConfiguration = new SearchConfiguration( apiKey: "YOUR_KEY", url: "api.pipl.com/search/", useHttps: true ); searchConfiguration.ShowSources = "matching"; List fields = new List() { new Name(first: "Clark", last: "Kent"), new Address(city: "Chicago", state: "IL", country: "US"), new Address(city: "Wichita", state: "KS", country: "US"), new Email(address: "clark.kent@example.com"), new Email(address: "ckent@hotmail.com"), new Phone(raw: "+1(312) 684-5000"), new Phone(raw: "(312) 352-9327") }; var person = new Person(fields); SearchAPIRequest request = new SearchAPIRequest( person: person, requestConfiguration: searchConfiguration ); var response = await request.SendAsync(); ``` ### Social Profiles (Facebook, LinkedIn and others) You can search Pipl by social services by the username, userID or even a profile URL. For the complete list of supported services, such as GitHub, Tiktok and others, please see [the list of supported services](/reference/user-id#list-of-supported-services) . ```text username=clark.kent@twitter OR userid=1234567@facebook OR url = https://linkedIn.com/in/ClarkKent ``` ```http https://api.pipl.com/search/?key=YOUR_KEY&show_sources=matching&username=clark.kent@linkedin ``` ```python from piplapis.search import SearchAPIRequest # Using username request = SearchAPIRequest(username=u'clark.kent@linkedin', api_key='YOUR_KEY', show_sources='matching') response = request.send() # Using userid request = SearchAPIRequest(userid=u'1234567@facebook', api_key='YOUR_KEY', show_sources='matching') response = request.send() # Using url request = SearchAPIRequest(url=u'https://linkedin.com/in/ClarkKent', api_key='YOUR_KEY', show_sources='matching') response = request.send() ``` ```ruby require 'pipl' # Using username response = Pipl::client.search username: 'clark.kent@linkedin', api_key: 'YOUR_KEY', show_sources: 'matching' # Using userid response = Pipl::client.search userid: '1234567@facebook', api_key: 'YOUR_KEY', show_sources: 'matching' # Using url response = Pipl::client.search url: 'https://linkedin.com/in/ClarkKent', api_key: 'YOUR_KEY', show_sources: 'matching' ``` ```java import com.pipl.api.search.SearchAPIRequest; import com.pipl.api.search.SearchAPIResponse; import com.pipl.api.search.SearchConfiguration; SearchConfiguration configuration = new SearchConfiguration(); configuration.setProtocol("https"); configuration.apiKey = "YOUR_KEY"; configuration.showSources = "matching"; // Using username SearchAPIRequest request = new SearchAPIRequest.Builder() .username("clark.kent@linkedin") .configuration(configuration) .build(); SearchAPIResponse response = request.send(); // Using userid request = new SearchAPIRequest.Builder() .userid("1234567@facebook") .configuration(configuration) .build(); response = request.send(); // Using url request = new SearchAPIRequest.Builder() .url("https://linkedin.com/in/ClarkKent") .configuration(configuration) .build(); response = request.send(); ``` ```php use_https = true; $configuration->api_key = 'YOUR_KEY'; $configuration->show_sources = 'matching'; // Using username $request = new PiplApi_SearchAPIRequest( array('username' => 'clark.kent@linkedin'), $configuration ); $response = $request->send(); // Using userid $request = new PiplApi_SearchAPIRequest( array('userid' => '1234567@facebook'), $configuration ); $response = $request->send(); // Using url $request = new PiplApi_SearchAPIRequest( array('url' => 'https://linkedin.com/in/ClarkKent'), $configuration ); $response = $request->send(); ?> ``` ```csharp using Pipl.APIs.Search; SearchConfiguration searchConfiguration = new SearchConfiguration( apiKey: "YOUR_KEY", url: "api.pipl.com/search/", useHttps: true ); searchConfiguration.ShowSources = "matching"; // Using username SearchAPIRequest request = new SearchAPIRequest( username: "clark.kent@linkedin", requestConfiguration: searchConfiguration ); var response = await request.SendAsync(); // Using userid request = new SearchAPIRequest( userid: "1234567@facebook", requestConfiguration: searchConfiguration ); response = await request.SendAsync(); // Using url request = new SearchAPIRequest( url: "https://linkedin.com/in/ClarkKent", requestConfiguration: searchConfiguration ); response = await request.SendAsync(); ``` ### US VIN (Vehicle Identification Number) You can use 'vin' query parameter to run a search using a vehicle's VIN. You can also use the codeusername/code parameter to search by a vehicle VIN using the format code########@vin/code ```text vin=JNKBV61EX7M710824 username=JNKBV61EX7M710824@vin ``` ```http https://api.pipl.com/search/?key=YOUR_KEY&show_sources=matching&vin=JNKBV61EX7M710824 https://api.pipl.com/search/?key=YOUR_KEY&show_sources=matching&username=JNKBV61EX7M710824@vin ``` ```python from piplapis.search import SearchAPIRequest # Using vin parameter request = SearchAPIRequest(vin=u'JNKBV61EX7M710824', api_key='YOUR_KEY', show_sources='matching') response = request.send() # Using username with @vin format request = SearchAPIRequest(username=u'JNKBV61EX7M710824@vin', api_key='YOUR_KEY', show_sources='matching') response = request.send() ``` ```ruby require 'pipl' # Using vin parameter response = Pipl::client.search vin: 'JNKBV61EX7M710824', api_key: 'YOUR_KEY', show_sources: 'matching' # Using username with @vin format response = Pipl::client.search username: 'JNKBV61EX7M710824@vin', api_key: 'YOUR_KEY', show_sources: 'matching' ``` ```java import com.pipl.api.search.SearchAPIRequest; import com.pipl.api.search.SearchAPIResponse; import com.pipl.api.search.SearchConfiguration; SearchConfiguration configuration = new SearchConfiguration(); configuration.setProtocol("https"); configuration.apiKey = "YOUR_KEY"; configuration.showSources = "matching"; // Using vin parameter SearchAPIRequest request = new SearchAPIRequest.Builder() .vin("JNKBV61EX7M710824") .configuration(configuration) .build(); SearchAPIResponse response = request.send(); // Using username with @vin format request = new SearchAPIRequest.Builder() .username("JNKBV61EX7M710824@vin") .configuration(configuration) .build(); response = request.send(); ``` ```php use_https = true; $configuration->api_key = 'YOUR_KEY'; $configuration->show_sources = 'matching'; // Using vin parameter $request = new PiplApi_SearchAPIRequest( array('vin' => 'JNKBV61EX7M710824'), $configuration ); $response = $request->send(); // Using username with @vin format $request = new PiplApi_SearchAPIRequest( array('username' => 'JNKBV61EX7M710824@vin'), $configuration ); $response = $request->send(); ?> ``` ```csharp using Pipl.APIs.Search; SearchConfiguration searchConfiguration = new SearchConfiguration( apiKey: "YOUR_KEY", url: "api.pipl.com/search/", useHttps: true ); searchConfiguration.ShowSources = "matching"; // Using vin parameter SearchAPIRequest request = new SearchAPIRequest( vin: "JNKBV61EX7M710824", requestConfiguration: searchConfiguration ); var response = await request.SendAsync(); // Using username with @vin format request = new SearchAPIRequest( username: "JNKBV61EX7M710824@vin", requestConfiguration: searchConfiguration ); response = await request.SendAsync(); ``` ### CPF (Brazilian Identification number) The codeusername/code parameter is used to search by a CPF using the following format "###########@cpf" ```text username=12345678901@cpf ``` ```http https://api.pipl.com/search/?key=YOUR_KEY&show_sources=matching&username=12345678901@cpf ``` ```python from piplapis.search import SearchAPIRequest request = SearchAPIRequest(username=u'12345678901@cpf', api_key='YOUR_KEY', show_sources='matching') response = request.send() ``` ```ruby require 'pipl' response = Pipl::client.search username: '12345678901@cpf', api_key: 'YOUR_KEY', show_sources: 'matching' ``` ```java import com.pipl.api.search.SearchAPIRequest; import com.pipl.api.search.SearchAPIResponse; import com.pipl.api.search.SearchConfiguration; SearchConfiguration configuration = new SearchConfiguration(); configuration.setProtocol("https"); configuration.apiKey = "YOUR_KEY"; configuration.showSources = "matching"; SearchAPIRequest request = new SearchAPIRequest.Builder() .username("12345678901@cpf") .configuration(configuration) .build(); SearchAPIResponse response = request.send(); ``` ```php use_https = true; $configuration->api_key = 'YOUR_KEY'; $configuration->show_sources = 'matching'; $request = new PiplApi_SearchAPIRequest( array('username' => '12345678901@cpf'), $configuration ); $response = $request->send(); ?> ``` ```csharp using Pipl.APIs.Search; SearchConfiguration searchConfiguration = new SearchConfiguration( apiKey: "YOUR_KEY", url: "api.pipl.com/search/", useHttps: true ); searchConfiguration.ShowSources = "matching"; SearchAPIRequest request = new SearchAPIRequest( username: "12345678901@cpf", requestConfiguration: searchConfiguration ); var response = await request.SendAsync(); ``` ### NPI (US National Provider identifier - medical professionals) The username parameter is used to search by an NPI using the following format "##########@npi" ```text username=1234567890@npi ``` ```http https://api.pipl.com/search/?key=YOUR_KEY&show_sources=matching&username=1234567890@npi ``` ```python from piplapis.search import SearchAPIRequest request = SearchAPIRequest(username=u'1234567890@npi', api_key='YOUR_KEY', show_sources='matching') response = request.send() ``` ```ruby require 'pipl' response = Pipl::client.search username: '1234567890@npi', api_key: 'YOUR_KEY', show_sources: 'matching' ``` ```java import com.pipl.api.search.SearchAPIRequest; import com.pipl.api.search.SearchAPIResponse; import com.pipl.api.search.SearchConfiguration; SearchConfiguration configuration = new SearchConfiguration(); configuration.setProtocol("https"); configuration.apiKey = "YOUR_KEY"; configuration.showSources = "matching"; SearchAPIRequest request = new SearchAPIRequest.Builder() .username("1234567890@npi") .configuration(configuration) .build(); SearchAPIResponse response = request.send(); ``` ```php use_https = true; $configuration->api_key = 'YOUR_KEY'; $configuration->show_sources = 'matching'; $request = new PiplApi_SearchAPIRequest( array('username' => '1234567890@npi'), $configuration ); $response = $request->send(); ?> ``` ```csharp using Pipl.APIs.Search; SearchConfiguration searchConfiguration = new SearchConfiguration( apiKey: "YOUR_KEY", url: "api.pipl.com/search/", useHttps: true ); searchConfiguration.ShowSources = "matching"; SearchAPIRequest request = new SearchAPIRequest( username: "1234567890@npi", requestConfiguration: searchConfiguration ); var response = await request.SendAsync(); ``` ### Job/Education Searching by job or education in a search query requires using a [full person search](/reference/full-person) ```text person= { "names": [{ "raw": "Clark Kent" }], "educations": [ {"school": "Metropolis University"} ], "jobs": [{"organization": "The Daily Planet"}, {"title": "Field Reporter"}] } ``` ```http https://api.pipl.com/search/?key=YOUR_KEY&show_sources=matching&person={ "names": [{ "raw": "Clark Kent" }], "educations": [ {"school": "University of Chicago"} ], "jobs": [{"organization": "The Wallstreet Journal"}, {"title": "Field Reporter"}] } ``` ```python from piplapis.data import Person, Name, Education, Job from piplapis.search import SearchAPIRequest fields = [ Name(raw=u'Clark Kent'), Education(school=u'Metropolis University'), Job(organization=u'The Daily Planet'), Job(title=u'Field Reporter') ] request = SearchAPIRequest(person=Person(fields=fields), api_key='YOUR_KEY', show_sources='matching') response = request.send() ``` ```ruby require 'pipl' person = Pipl::Person.new person.add_field Pipl::Name.new(raw: 'Clark Kent') person.add_field Pipl::Education.new(school: 'Metropolis University') person.add_field Pipl::Job.new(organization: 'The Daily Planet') person.add_field Pipl::Job.new(title: 'Field Reporter') response = Pipl::client.search person: person, api_key: 'YOUR_KEY', show_sources: 'matching' ``` ```java import java.util.ArrayList; import java.util.List; import com.pipl.api.search.SearchAPIRequest; import com.pipl.api.data.containers.Person; import com.pipl.api.data.fields.*; import com.pipl.api.search.SearchConfiguration; SearchConfiguration configuration = new SearchConfiguration(); configuration.setProtocol("https"); configuration.apiKey = "YOUR_KEY"; configuration.showSources = "matching"; List fields = new ArrayList(); fields.add(new Name.Builder().raw("Clark Kent").build()); fields.add(new Education.Builder().school("Metropolis University").build()); fields.add(new Job.Builder().organization("The Daily Planet").build()); fields.add(new Job.Builder().title("Field Reporter").build()); Person person = new Person(fields); SearchAPIRequest request = new SearchAPIRequest(person, configuration); SearchAPIResponse response = request.send(); ``` ```php use_https = true; $configuration->api_key = 'YOUR_KEY'; $configuration->show_sources = 'matching'; $fields = array( new PiplApi_Name(array("raw" => "Clark Kent")), new PiplApi_Education(array("school" => "Metropolis University")), new PiplApi_Job(array("organization" => "The Daily Planet")), new PiplApi_Job(array("title" => "Field Reporter")) ); $person = new PiplApi_Person($fields); $request = new PiplApi_SearchAPIRequest(array('person' => $person), $configuration); $response = $request->send(); ?> ``` ```csharp using Pipl.APIs.Search; using System.Collections.Generic; SearchConfiguration searchConfiguration = new SearchConfiguration( apiKey: "YOUR_KEY", url: "api.pipl.com/search/", useHttps: true ); searchConfiguration.ShowSources = "matching"; List fields = new List() { new Name(raw: "Clark Kent"), new Education(school: "Metropolis University"), new Job(organization: "The Daily Planet"), new Job(title: "Field Reporter") }; var person = new Person(fields); SearchAPIRequest request = new SearchAPIRequest( person: person, requestConfiguration: searchConfiguration ); var response = await request.SendAsync(); ``` ### Relationship You can search for a person that has a connection to another. Note that in the relationship object only the name part will be used in the search. ```text person= { "names": [ { "first": "Clark", "last": "Kent" } ], "relationships": [ { "names": [ { "first": "Lois", "last": "Lane" } ] } ] } ``` ```http https://api.pipl.com/search/?key=YOUR_KEY&show_sources=matching&person= { "names": [ { "first": "Clark", "last": "Kent" } ], "relationships": [ { "names": [ { "first": "Sam", "last": "Smith" } ] } ] } ``` ```python from piplapis.data import Person, Name, Relationship from piplapis.search import SearchAPIRequest fields = [ Name(first=u'Clark', last=u'Kent'), Relationship(names=[Name(first=u'Lois', last=u'Lane')]) ] request = SearchAPIRequest(person=Person(fields=fields), api_key='YOUR_KEY', show_sources='matching') response = request.send() ``` ```ruby require 'pipl' person = Pipl::Person.new person.add_field Pipl::Name.new(first: 'Clark', last: 'Kent') relationship = Pipl::Relationship.new relationship.add_field Pipl::Name.new(first: 'Lois', last: 'Lane') person.add_field relationship response = Pipl::client.search person: person, api_key: 'YOUR_KEY', show_sources: 'matching' ``` ```java import java.util.ArrayList; import java.util.List; import com.pipl.api.search.SearchAPIRequest; import com.pipl.api.data.containers.Person; import com.pipl.api.data.fields.*; import com.pipl.api.search.SearchConfiguration; SearchConfiguration configuration = new SearchConfiguration(); configuration.setProtocol("https"); configuration.apiKey = "YOUR_KEY"; configuration.showSources = "matching"; List fields = new ArrayList(); fields.add(new Name.Builder().first("Clark").last("Kent").build()); List relationshipFields = new ArrayList(); relationshipFields.add(new Name.Builder().first("Lois").last("Lane").build()); fields.add(new Relationship(relationshipFields)); Person person = new Person(fields); SearchAPIRequest request = new SearchAPIRequest(person, configuration); SearchAPIResponse response = request.send(); ``` ```php use_https = true; $configuration->api_key = 'YOUR_KEY'; $configuration->show_sources = 'matching'; $fields = array( new PiplApi_Name(array("first" => "Clark", "last" => "Kent")), new PiplApi_Relationship(array( "names" => array( new PiplApi_Name(array("first" => "Lois", "last" => "Lane")) ) )) ); $person = new PiplApi_Person($fields); $request = new PiplApi_SearchAPIRequest(array('person' => $person), $configuration); $response = $request->send(); ?> ``` ```csharp using Pipl.APIs.Search; using System.Collections.Generic; SearchConfiguration searchConfiguration = new SearchConfiguration( apiKey: "YOUR_KEY", url: "api.pipl.com/search/", useHttps: true ); searchConfiguration.ShowSources = "matching"; List fields = new List() { new Name(first: "Clark", last: "Kent"), new Relationship(names: new List() { new Name(first: "Lois", last: "Lane") }) }; var person = new Person(fields); SearchAPIRequest request = new SearchAPIRequest( person: person, requestConfiguration: searchConfiguration ); var response = await request.SendAsync(); ``` ### Email in MD5 format You can search for an MD5 as follows. Please be sure to normalize your email address following [the MD5 Calculation guidelines](/reference/email#md5-calculation-guidelines) before applying the MD5 hash. ```text person= { "emails": [ { "address_md5": "b095275aa233df8e857dbca662512ca4" } ] } ``` ```http https://api.pipl.com/search/?key=YOUR_KEY&show_sources=matching&person= { "emails": [ { "address_md5": "b095275aa233df8e857dbca662512ca4" } ] } ``` ```python from piplapis.data import Person, Email from piplapis.search import SearchAPIRequest fields = [ Email(address_md5=u'b095275aa233df8e857dbca662512ca4') ] request = SearchAPIRequest(person=Person(fields=fields), api_key='YOUR_KEY', show_sources='matching') response = request.send() ``` ```ruby require 'pipl' person = Pipl::Person.new person.add_field Pipl::Email.new(address_md5: 'b095275aa233df8e857dbca662512ca4') response = Pipl::client.search person: person, api_key: 'YOUR_KEY', show_sources: 'matching' ``` ```java import java.util.ArrayList; import java.util.List; import com.pipl.api.search.SearchAPIRequest; import com.pipl.api.data.containers.Person; import com.pipl.api.data.fields.*; import com.pipl.api.search.SearchConfiguration; SearchConfiguration configuration = new SearchConfiguration(); configuration.setProtocol("https"); configuration.apiKey = "YOUR_KEY"; configuration.showSources = "matching"; List fields = new ArrayList(); fields.add(new Email.Builder().addressMd5("b095275aa233df8e857dbca662512ca4").build()); Person person = new Person(fields); SearchAPIRequest request = new SearchAPIRequest(person, configuration); SearchAPIResponse response = request.send(); ``` ```php use_https = true; $configuration->api_key = 'YOUR_KEY'; $configuration->show_sources = 'matching'; $fields = array( new PiplApi_Email(array("address_md5" => "b095275aa233df8e857dbca662512ca4")) ); $person = new PiplApi_Person($fields); $request = new PiplApi_SearchAPIRequest(array('person' => $person), $configuration); $response = $request->send(); ?> ``` ```csharp using Pipl.APIs.Search; using System.Collections.Generic; SearchConfiguration searchConfiguration = new SearchConfiguration( apiKey: "YOUR_KEY", url: "api.pipl.com/search/", useHttps: true ); searchConfiguration.ShowSources = "matching"; List fields = new List() { new Email(addressMd5: "b095275aa233df8e857dbca662512ca4") }; var person = new Person(fields); SearchAPIRequest request = new SearchAPIRequest( person: person, requestConfiguration: searchConfiguration ); var response = await request.SendAsync(); ``` --- ## Pipl Thumbnails API import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Pipl Thumbnails API As an API subscriber, you also enjoy complimentary access to our Thumbnail API. The Thumbnail API saves you the hassle of dealing with profile pictures by providing built-in features for: - Cropping images to the right dimensions - Zooming in on faces with advanced face detection - Attributing sources by adding favicons to images - Image redundancy—specify a fallback image ![](../static/img/thumbnail_demo.png 'Thumbnail Demo.png') ## How does it work? Each image field in our API responses includes a special token that can be sent to our thumbnail servers. You can specify the exact parameters depending on your needs. ```json { "url": "http://vignette3.wikia.nocookie.net/smallville/images/5/55/S10E18-Booster21.jpg", "thumbnail_token": "AE2861B242686E7BD0CB4D9049298EB7D18FEF66D950E8AB78BCD3F484345CE74536C19A85D0BA3D32DC9E7D1878CD4D341254E7AD129255C6983E6E154C4530A0DAAF665EA325FC0206F8B1D7E0B6B7AD9EBF71FCF610D57D" } ``` ## Creating a thumbnail URL The base URL of our thumbnail server is: _[https://thumb.pipl.com/image](https://thumb.pipl.com/image)_. An example of a complete url would be: ``` http://thumb.pipl.com/image?height=250&width=250&favicon=true&zoom_face=true&tokens=AE2861B242686E7BD0CB4D9049298EB7D18FEF66D950E8AB78BCD3F484345CE74536C19A85D0BA3D32DC9E7D1878CD4D341254E7AD129255C6983E6E154C4530A0DAAF665EA325FC0206F8B1D7E0B6B7AD9EBF71FCF610D57D ``` ## A redundant thumbnail URL Sometimes, images will no longer be available on the web. To help you create robust thumbnail URLs, our thumbnail API allows specifying a fallback token. To use this option, send two tokens to the API separated by a comma, like this: ``` http://thumb.pipl.com/image?height=250&width=250&favicon=true&zoom_face=true&tokens=FIRST_TOKEN,SECOND_TOKEN ``` ## Allowed parameters: | **Parameter** | **Description** | | -------------- | ---------------- | | **tokens** _required_ | Required. One or two thumbnail tokens, separated by a comma. If the image referenced by the first thumbnail token is no longer available on the web, the second token will be used. | | **height** _required_ | Height in pixels. Integer between 100-500. | | **width** _required_ | Width in pixels. Integer between 100-500. | | **favicon** | Boolean. Whether to show favicon. | | **zoom_face** | Boolean. Whether to enable face zoom. | ## Using the client libraries If you use our client libraries, we’ll handle all of the boilerplate for you. ```python # Creating a thumbnail URL thumbnail_url = image.get_thumbnail_url(200, 100, zoom_face=True, favicon=True) # Creating a redundant image URL redundant_url = Image.generate_redundant_thumbnail_url(first_image, fallback_image, 100, 100) ``` ```ruby # Creating a thumbnail URL thumbnail_url = image.thumbnail_url width: 200, height: 100, favicon: true, zoom_face: true # Creating a redundant image URL image = Pipl::Image.new(thumbnail_token: 'TOKEN') fallback = Pipl::Image.new(thumbnail_token: 'FALLBACK_TOKEN') url = image.thumbnail_url width: 200, height: 100, favicon: true, zoom_face: true, fallback: fallback ``` ```java # Creating a thumbnail URL String thumbUrl = image.getThumbnailUrl(200, 100, true, true, false); # Creating a redundant image URL String url = Image.generateRedundantThumbnailUrl(250, 250, true, true, false, resp.person.images.get(0), resp.person.images.get(1)); ``` ```php # Creating a thumbnail URL $thumbUrl = $image->get_thumbnail_url(200, 100, true, true); # Creating a redundant image URL $thumbUrl = PiplApi_Image::generate_redundant_thumbnail_url($first_image, $second_image, 100, 100); ``` ```csharp # Creating a thumbnail image URL var thumbUrl = _image.GetThumbnailUrl(200, 100, true, true); # Creating a redundant image URL var thumbnail_url = Pipl.APIs.Data.Fields.Image.GenerateRedundantThumbnailUrl(image1, image2, 200, 100, true,true,true); ``` ## Special cases In some cases, both of your tokens will reference an image no longer available online, or they might contain a default placeholder image and not a real image of the person. In those cases, the thumbnail server will return 404. --- ## Working with Images ## Introduction Images are available with the SOCIAL key and up. You can display an image in your application by using the images in the API response. Simply utilize the free to use Pipl thumbnail API with the thumbnail token returned with the image. This tutorial is to help you to determine the source of an image from the Pipl API response, and address the case when an image is no longer accessible. ## Where is the image from? Some of Pipl Search users wish to only display images that originated from certain data sources. For example, they may want to display a professional Linkedin image over a personal Twitter image in their applications. The list of images returned from Pipl's API is vendor neutral. If you activate the sources layer with `show_sources=matching` (see configuration parameters), you will be able to see source attribution for data fields in a person's profile. For each image returned for a person, there is a corresponding source in the sources array, indicating the origin with the `@name` metadata tag (e.g. LinkedIn, Twitter, etc). By searching for the URL of the image in each source, you will be able to cross reference the origin of the image. For example, let's search for the email address: [email protected]. This is our query: `https://api.pipl.com/search/?email=[email protected]&key=YOURKEY&show_sources=matching` Note that we appended `show_sources=matching` which shows only sources that were used to build the Person profile. ## Working with the response There are three important sections to note from the JSON response in order to determine the source of each image: - available data - images array - sources array Below is an example from a Person response, showing only the information relevant to images. ```json { "@http_status_code": 200, ... "available_data": { "premium": { "images": 2, } }, "person": { ... "images": [ ], ... }, "sources": [ { , "@name": "xxx", "images": [ { "url": "", "thumbnail_token": "" } ], }, ... {...} ] } ``` From the `available_data` we determine the number of images returned in the response: ```json "available_data": { "premium": { "relationships": 6, ... "names": 2, "dobs": 1, "images": 2, "genders": 1, "emails": 4, "origin_countries": 1 } }, ``` From the images array in each person object, we can see the source URL for each image, and the `thumbnail_token` that can be used with Pipl's thumbnail API. ```json "images": [ { "url": "http://vignette1.wikia.nocookie.net/smallville/images/e/ea/Buddies_forever.jpg", "thumbnail_token": "AE2861B242686E7BD0CB4D9049298EB7D18FEF66D950E8AB78BCD3F484345CE74536C19A85D0BA3D32DC9E7D1878CD4D341254E7AD129255C6983E6E154C4530A0DAAF665EA325FC0206F8B1D7E0B6B7AD9EBF71FCF610D57D" }, { "url": "http://vignette3.wikia.nocookie.net/smallville/images/5/55/S10E18-Booster21.jpg", "thumbnail_token": "AE2861B242686E7BD0CB4D9049298EB5D18FEF66D950E8AB78BCD3F484345CE74536C19A85D0BA3D32DC9E7D1878CD4D341254E7AD12C25596CC3E7F51186468FD84B26F5EA234EF1546E7F5CDF7F7F5BA84B228F4F013DD7281" } ], ``` In the sources array we can see the origin of each image. To determine the origin of an image, search through the source array for a source that includes the URL of the image in the 'images' field. In the example below, we can determine the image is from the Facebook data source (please note that images from Facebook are no longer publicly available, and the below example is for illustrative purposes only). ```json "sources": [ ... { "@id": "5d836a4acc55922e49fc709c7a39e233", "@category": "personal_profiles", "@name": "Facebook", "@origin_url": "http://facebook.com/superman", "@domain": "facebook.com", "@person_id": "cdb74980-718a-4277-82bf-cdd2b30781c8", "@match": 1.0, ... "images": [ { "url": "http://vignette1.wikia.nocookie.net/smallville/images/e/ea/Buddies_forever.jpg", "thumbnail_token": "AE2861B242686E7BD0CB4D9049298EB7D18FEF66D950E8AB78BCD3F484345CE74536C19A85D0BA3D32DC9E7D1878CD4D341254E7AD129255C6983E6E154C4530A0DAAF665EA325FC0206F8B1D7E0B6B7AD9EBF71FCF610D57D" }, { "url": "http://vignette3.wikia.nocookie.net/smallville/images/5/55/S10E18-Booster21.jpg", "thumbnail_token": "AE2861B242686E7BD0CB4D9049298EB5D18FEF66D950E8AB78BCD3F484345CE74536C19A85D0BA3D32DC9E7D1878CD4D341254E7AD12C25596CC3E7F51186468FD84B26F5EA234EF1546E7F5CDF7F7F5BA84B228F4F013DD7281" } ], ... }, ... ] ``` When working with possible person responses, you will need to use `show_sources=all` in order to see the source layer for possible persons. Besides this change, the same approach is used as with a person response. ## Dealing with images that are no longer accessible Pipl aims to return only URLs to images that are active, however, sometimes due to issues with the image source, the image may no longer be accessible or even exist. These issues may include one or more of the following: * A profile may have been public at a certain stage, however a user changed their privacy settings, so the public profile image is no longer available * A person may have removed the image from their profile or closed down their profile * The website may have removed the image * The social network or URL no longer exists, the entire website is down or the profile was taken down * The social network no longer serves images as public, and requires a special access token to access the image * A website may have changed the way they internally reference images, and the image URL Pipl has a record of becomes invalidated If the image is no longer accessible when directly using the image URL to retrieve the image, you could get a 403, 404 or 400 HTTP status error response. The Pipl thumbnail API allows you to select a fallback API token that is used if the first token is not available. If none of the tokens provided to the Pipl thumbnail API are accessible, then a 404 HTTP status code will be returned, and a default Pipl avatar image will be returned. It is recommended to retrieve the HEAD of the image in your server side application to check if the image is available before displaying this to the user. To improve your application's user experience, you may choose to replace Pipl's thumbnail default avatar with one of your own. --- ## Don't log my query data import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Do not log API queries with Pipl ## What is the no_log feature? By using the no_log parameter in your Pipl API queries, no input query information will be stored by Pipl servers. Query data will only be used to perform a search, and a record of the transaction will be logged for billing purposes with no query data being stored. Please note that when using the no_log feature, your Customer Success expert will not have visibility of your queries to help you debug and optimize. For this reason, we recommend logging your own queries made to the Pipl API and including any [errors](/reference/errors) and [warnings](/reference/warnings) returned. ## Using the no_log feature with the Pipl API code libraries If you’re using one of [Pipl’s API code libraries]code-libraries), you can easily enable the no_log feature with your queries. (For **Ruby** please contact your Customer Success expert.) Instructions for activating this feature in Java, Python and PHP are shown below. ```java //Update the default configuration on init, which will be used. //Use the extraParams variable of the defaultConfiguration. See example below: SearchConfiguration defaultConfiguration = SearchAPIRequest.getDefaultConfiguration(); defaultConfiguration.extraParams = "&no_log=True"; ``` ```python # Extend the BASE_URL before making an API request. SearchAPIRequest.BASE_URL += "&no_log=true" request = SearchAPIRequest(email="clark.kent@example.com") ``` ```php /* Please see the source code on GitHub for the code library for reference (base_url definition - https://github.com/piplcom/piplapis-php/blob/master/src/piplapis/search.php#L84). Once you construct a PiplApi_SearchAPIRequest object, you will need to change the base_url from: */ public static $base_url = 'api.pipl.com/search/?'; /* to the following to execute a request */ $base_url = 'api.pipl.com/search/?no_log=true&'; ``` ```csharp #Use reflection to modify the Url property of your SearchAPIRequest object instance typeof(SearchAPIRequest).GetProperty("Url") .SetValue(yourSearchAPIRequest, "https://api.pipl.com/search/?no_log=true&"); ``` ## Using the no_log feature without the Pipl API code libraries Simply add &no_log=true to your API queries with the Pipl API to activate this feature. ## Disabling logging within the pipl.com portal In addition to server-side API logs, Pipl also maintains [1 week of transaction logs on the pipl.com portal](https://search.pipl.com/api/manage/queries) for customers with auditing needs they can't satisfy on their own. For customers who **do not** want this functionality, it can be disabled by setting the 'Errors Only' toggle on the same page.