├── .env.local.example ├── .eslintrc.cjs ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── dependabot.yml ├── pull_request_template.md └── workflows │ ├── publish.yaml │ └── test.yaml ├── .gitignore ├── .ncurc.json ├── LICENSE ├── README.md ├── example ├── index.js ├── package.json └── pnpm-lock.yaml ├── package.json ├── pnpm-lock.yaml ├── src ├── endpoints │ ├── autocomplete │ │ └── index.ts │ ├── bulkCompanyEnrichment │ │ └── index.ts │ ├── bulkEnrichment │ │ └── index.ts │ ├── bulkRetrieve │ │ └── index.ts │ ├── cleaner │ │ └── index.ts │ ├── enrichment │ │ └── index.ts │ ├── enrichmentPreview │ │ └── index.ts │ ├── identify │ │ └── index.ts │ ├── index.ts │ ├── ip │ │ └── index.ts │ ├── jobTitle │ │ └── index.ts │ ├── retrieve │ │ └── index.ts │ └── search │ │ └── index.ts ├── errors.ts ├── index.ts ├── types │ ├── api-types.ts │ ├── autocomplete-types.ts │ ├── bulk-retrieve-types.ts │ ├── bulk-types.ts │ ├── canonical-types.ts │ ├── cleaner-types.ts │ ├── common-types.ts │ ├── enrichment-types.ts │ ├── error-types.ts │ ├── identify-types.ts │ ├── ip-types.ts │ ├── jobTitle-types.ts │ ├── retrieve-types.ts │ ├── search-types.ts │ └── utility-types.ts └── utils │ └── api-utils.ts ├── tests └── index.test.js ├── tsconfig.eslint.json └── tsconfig.json /.env.local.example: -------------------------------------------------------------------------------- 1 | PDL_API_KEY=... 2 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es2021: true, 5 | }, 6 | extends: [ 7 | 'airbnb-base', 8 | 'airbnb-typescript/base', 9 | ], 10 | parser: '@typescript-eslint/parser', 11 | parserOptions: { 12 | ecmaVersion: 'latest', 13 | sourceType: 'module', 14 | project: './tsconfig.eslint.json', 15 | }, 16 | plugins: [ 17 | '@stylistic', 18 | '@typescript-eslint', 19 | 'simple-import-sort', 20 | 'sort-destructure-keys', 21 | 'typescript-sort-keys', 22 | 'import-newlines', 23 | ], 24 | rules: { 25 | 'max-len': 'off', 26 | 'simple-import-sort/imports': 'error', 27 | 'simple-import-sort/exports': 'error', 28 | 'object-curly-newline': 'off', 29 | 'typescript-sort-keys/interface': ['error', 'asc', { 30 | caseSensitive: false, 31 | natural: true, 32 | requiredFirst: false, 33 | }], 34 | 'typescript-sort-keys/string-enum': ['error', 'asc', { 35 | caseSensitive: false, 36 | natural: true, 37 | }], 38 | 'import-newlines/enforce': ['error', { 39 | items: 5000, 40 | multiline: false, 41 | }], 42 | '@stylistic/member-delimiter-style': ['error', { 43 | multiline: { 44 | delimiter: 'semi', 45 | requireLast: true, 46 | }, 47 | singleline: { 48 | delimiter: 'comma', 49 | requireLast: false, 50 | }, 51 | }], 52 | '@stylistic/type-annotation-spacing': 'error', 53 | '@stylistic/type-generic-spacing': ['error'], 54 | '@stylistic/type-named-tuple-spacing': ['error'], 55 | 'sort-destructure-keys/sort-destructure-keys': [2, { 56 | caseSensitive: false, 57 | }], 58 | }, 59 | }; 60 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Screenshots** 20 | If applicable, add screenshots to help explain your problem. 21 | - peopledatalabs Library Version 22 | - Node Version 23 | - NPM Version 24 | 25 | **Additional context** 26 | Add any other context about the problem here. 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "npm" 4 | open-pull-requests-limit: 10 5 | directory: "/" 6 | schedule: 7 | interval: "weekly" 8 | day: "sunday" 9 | time: "09:00" 10 | timezone: "America/Los_Angeles" 11 | labels: 12 | - "dependencies" 13 | ignore: 14 | - dependency-name: "@stylistic/eslint-plugin" 15 | - dependency-name: "@typescript-eslint/eslint-plugin" 16 | - dependency-name: "@typescript-eslint/parser" 17 | - dependency-name: "copy-anything" 18 | - dependency-name: "eslint" 19 | - dependency-name: "eslint-plugin-unused-imports" -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Description of the change 2 | 3 | - Description here 4 | 5 | ## Type of change 6 | 7 | - [ ] Bug fix (non-breaking change that fixes an issue) 8 | - [ ] Chore (cleanup or minor QOL tweak that has little to no impact on functionality) 9 | - [ ] New feature (non-breaking change that adds functionality) 10 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 11 | -------------------------------------------------------------------------------- /.github/workflows/publish.yaml: -------------------------------------------------------------------------------- 1 | name: Publish Package to NPM and GitHub 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | test: 9 | runs-on: ubuntu-latest 10 | permissions: 11 | contents: read 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: actions/setup-node@v4 15 | with: 16 | node-version: 22 17 | - run: npm install -g pnpm 18 | - run: pnpm install --frozen-lockfile 19 | - run: pnpm test 20 | env: 21 | PDL_API_KEY: ${{secrets.PDL_API_KEY}} 22 | 23 | publish-npm: 24 | needs: test 25 | runs-on: ubuntu-latest 26 | permissions: 27 | contents: read 28 | packages: write 29 | id-token: write 30 | steps: 31 | - uses: actions/checkout@v4 32 | - uses: actions/setup-node@v4 33 | with: 34 | node-version: 22 35 | registry-url: https://registry.npmjs.org/ 36 | - run: npm install -g pnpm 37 | - run: pnpm install --frozen-lockfile 38 | - run: pnpm pub 39 | env: 40 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: Test Package 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | permissions: 13 | contents: read 14 | steps: 15 | - uses: actions/checkout@v4 16 | - uses: actions/setup-node@v4 17 | with: 18 | node-version: 22 19 | - run: npm install -g pnpm 20 | - run: pnpm install --frozen-lockfile 21 | - run: pnpm test 22 | env: 23 | PDL_API_KEY: ${{secrets.PDL_API_KEY}} 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional stylelint cache 58 | .stylelintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variable files 76 | .env 77 | .env.development.local 78 | .env.test.local 79 | .env.production.local 80 | .env.local 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | .parcel-cache 85 | 86 | # Next.js build output 87 | .next 88 | out 89 | 90 | # Nuxt.js build / generate output 91 | .nuxt 92 | dist 93 | 94 | # Gatsby files 95 | .cache/ 96 | # Comment in the public line in if your project uses Gatsby and not Next.js 97 | # https://nextjs.org/blog/next-9-1#public-directory-support 98 | # public 99 | 100 | # vuepress build output 101 | .vuepress/dist 102 | 103 | # vuepress v2.x temp and cache directory 104 | .temp 105 | .cache 106 | 107 | # Docusaurus cache and generated files 108 | .docusaurus 109 | 110 | # Serverless directories 111 | .serverless/ 112 | 113 | # FuseBox cache 114 | .fusebox/ 115 | 116 | # DynamoDB Local files 117 | .dynamodb/ 118 | 119 | # TernJS port file 120 | .tern-port 121 | 122 | # Stores VSCode versions used for testing VSCode extensions 123 | .vscode-test 124 | 125 | # yarn v2 126 | .yarn/cache 127 | .yarn/unplugged 128 | .yarn/build-state.yml 129 | .yarn/install-state.gz 130 | .pnp.* 131 | 132 | # Mac OS 133 | .DS_Store 134 | 135 | # Cache Files 136 | .rpt2_cache 137 | .rts2_cache_cjs 138 | .rts2_cache_es 139 | .rts2_cache_umd 140 | 141 | # VS Code 142 | .vscode 143 | 144 | # pnpm 145 | .pnpm/ 146 | .pnp.cjs 147 | .pnp.loader.mjs 148 | .pnpm-store/ 149 | pnpm-debug.log* -------------------------------------------------------------------------------- /.ncurc.json: -------------------------------------------------------------------------------- 1 | { 2 | "interactive": true, 3 | "packageManager": "pnpm", 4 | "reject": [ 5 | "@stylistic/eslint-plugin", 6 | "@typescript-eslint/eslint-plugin", 7 | "@typescript-eslint/parser", 8 | "copy-anything", 9 | "eslint", 10 | "eslint-plugin-unused-imports" 11 | ], 12 | "root": true 13 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 People Data Labs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | People Data Labs Logo 3 |

4 |

People Data Labs JavaScript Library

5 |

6 | JavaScript client with TypeScript support for the People Data Labs API. 7 |

8 | 9 |

10 | 11 | Repo Status 12 |   13 | 14 | People Data Labs on NPM 15 |   16 | 17 | Tests Status 18 | 19 |

20 | 21 | # 22 | 23 | This is a simple JavaScript client library to access the various API endpoints provided by [People Data Labs](https://www.peopledatalabs.com/). 24 | 25 | This library bundles up PDL API requests into simple function calls, making it easy to integrate into your projects. You can use the various [API endpoints](#endpoints) to access up-to-date, real-world data from our massive [Person](https://docs.peopledatalabs.com/docs/stats) and [Company](https://docs.peopledatalabs.com/docs/company-stats) Datasets. 26 | 27 | ## ✨ Features 28 | 29 | - Supports all People Data Labs API endpoints 30 | - Built-in Typescript support 31 | 32 | ## Table of Contents 33 | 34 | - [🔧 Installation](#installation) 35 | - [🚀 Usage](#usage) 36 | - [🌐 Endpoints](#endpoints) 37 | - [📘 Documentation](#documentation) 38 | - [Special Note about Search API Support](#special-note) 39 | - [Upgrading to v6.X.X](#upgrading-to-v6) 40 | - [Upgrading to v5.X.X](#upgrading-to-v5) 41 | 42 | ## 🔧 Installation 43 | 44 | 1. Pull the package from the npm repository: 45 | 46 | ```bash 47 | yarn add peopledatalabs 48 | ``` 49 | 50 | or 51 | 52 | ```bash 53 | npm i peopledatalabs 54 | ``` 55 | 56 | 2. If you get a error while running a typescript project, add `"esModuleInterop": true` to your tsconfig 57 | 58 | 3. Sign up for a [free PDL API key](https://www.peopledatalabs.com/signup) 59 | 60 | ## 🚀 Usage 61 | 62 | First, create the PDLJS client: 63 | 64 | ```js 65 | import PDLJS from 'peopledatalabs'; 66 | 67 | const PDLJSClient = new PDLJS({ apiKey: 'YOUR API KEY' }) 68 | ``` 69 | 70 | Then, send requests to any PDL API Endpoint: 71 | 72 | **Using Person APIs** 73 | 74 | ```js 75 | // By Enrichment 76 | try { 77 | const response = await PDLJSClient.person.enrichment({ phone: '4155688415' }); 78 | 79 | console.log(response); 80 | } catch (error) { 81 | console.log(error); 82 | } 83 | 84 | // By Preview Enrichment 85 | try { 86 | const response = await PDLJSClient.person.enrichmentPreview({ phone: '4155688415' }); 87 | 88 | console.log(response); 89 | } catch (error) { 90 | console.log(error); 91 | } 92 | 93 | // By Bulk Enrichment 94 | const bulkEnrichmentRecords = { 95 | requests: [ 96 | { 97 | params: { 98 | profile: ['linkedin.com/in/seanthorne'], 99 | }, 100 | }, 101 | { 102 | params: { 103 | profile: ['linkedin.com/in/randrewn'], 104 | }, 105 | }, 106 | ], 107 | }; 108 | 109 | try { 110 | const response = await PDLJSClient.person.bulk.enrichment(bulkEnrichmentRecords); 111 | 112 | console.log(response.items); 113 | } catch (error) { 114 | console.log(error); 115 | } 116 | 117 | // By Search (SQL) 118 | const sqlQuery = "SELECT * FROM person WHERE location_country='mexico' AND job_title_role='health'AND phone_numbers IS NOT NULL;" 119 | 120 | try { 121 | const response = await PDLJSClient.person.search.sql({ searchQuery: sqlQuery, size: 10 }); 122 | 123 | console.log(response.total); 124 | } catch (error) { 125 | console.log(error); 126 | } 127 | 128 | // By Search (Elasticsearch) 129 | const esQuery = { 130 | query: { 131 | bool: { 132 | must:[ 133 | { term: { location_country: 'mexico' } }, 134 | { term: { job_title_role: 'health' } }, 135 | { exists: { field: 'phone_numbers' } } 136 | ] 137 | } 138 | } 139 | } 140 | 141 | try { 142 | const response = await PDLJSClient.person.search.elastic({ searchQuery: esQuery, size: 10 }); 143 | 144 | console.log(response.total); 145 | } catch (error) { 146 | console.log(error); 147 | } 148 | 149 | // By Fuzzy Enrichment 150 | try { 151 | const response = await PDLJSClient.person.identify({ name: 'sean thorne' }); 152 | 153 | console.log(response); 154 | } catch (error) { 155 | console.log(error); 156 | } 157 | ``` 158 | 159 | **Using Company APIs** 160 | 161 | ```js 162 | // By Enrichment 163 | try { 164 | const response = await PDLJSClient.company.enrichment({ website: 'peopledatalabs.com' }); 165 | 166 | console.log(response); 167 | } catch (error) { 168 | console.log(error); 169 | } 170 | 171 | // By Bulk Enrichment 172 | const bulkEnrichmentRecords = { 173 | requests: [ 174 | { 175 | params: { 176 | profile: ['linkedin.com/in/peopledatalabs'], 177 | }, 178 | }, 179 | { 180 | params: { 181 | profile: ['linkedin.com/in/apple'], 182 | }, 183 | }, 184 | ], 185 | }; 186 | 187 | try { 188 | const response = await PDLJSClient.company.bulk.enrichment(bulkEnrichmentRecords); 189 | 190 | console.log(response.items); 191 | } catch (error) { 192 | console.log(error); 193 | } 194 | 195 | // By Search (SQL) 196 | const sqlQuery = "SELECT * FROM company WHERE tags='big data' AND industry='financial services' AND location.country='united states';" 197 | 198 | try { 199 | const response = await PDLJSClient.company.search.sql({ searchQuery: sqlQuery, size: 10 }); 200 | 201 | console.log(response.total); 202 | } catch (error) { 203 | console.log(error); 204 | } 205 | 206 | // By Search (Elasticsearch) 207 | const esQuery = { 208 | query: { 209 | bool: { 210 | must:[ 211 | { term: { tags: 'big data' } }, 212 | { term: { industry: 'financial services' } }, 213 | { term: { location_country: 'united states' } } 214 | ] 215 | } 216 | } 217 | } 218 | 219 | try { 220 | const response = await PDLJSClient.company.search.elastic({ searchQuery: esQuery, size: 10 }); 221 | 222 | console.log(response.total); 223 | } catch (error) { 224 | console.log(error); 225 | } 226 | 227 | ``` 228 | 229 | **Using Autocomplete API** 230 | 231 | ```js 232 | // Get Autocomplete Suggestions 233 | try { 234 | const response = await PDLJSClient.autocomplete({ field: 'title', text: 'full', size: 10 }); 235 | 236 | console.log(response); 237 | } catch (error) { 238 | console.log(error); 239 | } 240 | ``` 241 | 242 | **Using Cleaner APIs** 243 | 244 | ```js 245 | // Clean Raw Company Strings 246 | try { 247 | const response = await PDLJSClient.company.cleaner({ name: 'peOple DaTa LabS' }); 248 | 249 | console.log(response); 250 | } catch (error) { 251 | console.log(error); 252 | } 253 | 254 | // Clean Raw Location Strings 255 | try { 256 | const response = await PDLJSClient.location.cleaner({ location: '455 Market Street, San Francisco, California 94105, US' }); 257 | 258 | console.log(response); 259 | } catch (error) { 260 | console.log(error); 261 | } 262 | 263 | // Clean Raw School Strings 264 | try { 265 | const response = await PDLJSClient.school.cleaner({ name: 'university of oregon' }); 266 | 267 | console.log(response); 268 | } catch (error) { 269 | console.log(error); 270 | } 271 | ``` 272 | 273 | **Using Job Title Enrichment API** 274 | 275 | ```js 276 | // Enrich a Job Title 277 | try { 278 | const response = await PDLJSClient.jobTitle({ jobTitle: 'software engineer' }); 279 | 280 | console.log(response); 281 | } catch (error) { 282 | console.log(error); 283 | } 284 | ``` 285 | 286 | **Using IP Enrichment API** 287 | 288 | ```js 289 | // Enrich an IP Address 290 | try { 291 | const response = await PDLJSClient.ip({ ip: '72.212.42.228' }); 292 | 293 | console.log(response); 294 | } catch (error) { 295 | console.log(error); 296 | } 297 | ``` 298 | 299 | **Using Sandbox APIs** 300 | 301 | ```js 302 | // By Person Enrichment 303 | try { 304 | const response = await PDLJSClient.person.enrichment({ 305 | email: 'reneewillis74@aol.com', 306 | sandbox: true, 307 | }); 308 | 309 | console.log(response); 310 | } catch (error) { 311 | console.log(error); 312 | } 313 | 314 | // By Person Search (SQL) 315 | try { 316 | const response = await PDLJSClient.person.search.sql({ 317 | searchQuery: "SELECT * FROM person WHERE location_country='united states';", 318 | size: 10, 319 | sandbox: true, 320 | }); 321 | 322 | console.log(response.total); 323 | } catch (error) { 324 | console.log(error); 325 | } 326 | 327 | // By Person Search (Elasticsearch) 328 | const esQuery = { 329 | query: { 330 | bool: { 331 | must:[ 332 | { term: { location_country: 'united states' } } 333 | ] 334 | } 335 | } 336 | } 337 | 338 | try { 339 | const response = await PDLJSClient.person.search.elastic({ searchQuery: esQuery, size: 10, sandbox: true }); 340 | 341 | console.log(response.total); 342 | } catch (error) { 343 | console.log(error); 344 | } 345 | 346 | // By Person Fuzzy Enrichment 347 | try { 348 | const response = PDLJSClient.person.identify({ email: 'reneewillis74@aol.com', sandbox: true }); 349 | 350 | console.log(response); 351 | } catch (error) { 352 | console.log(error); 353 | } 354 | 355 | // By Company Enrichment 356 | try { 357 | const response = await PDLJSClient.company.enrichment({ website: 'kohlerinteriors.com', sandbox: true }); 358 | 359 | console.log(response); 360 | } catch (error) { 361 | console.log(error); 362 | } 363 | 364 | // By Company Search (SQL) 365 | const sqlQuery = "SELECT * FROM company WHERE tags='hotel consultant' AND industry='hospitality';" 366 | 367 | try { 368 | const response = await PDLJSClient.company.search.sql({ searchQuery: sqlQuery, size: 10, sandbox: true }); 369 | 370 | console.log(response.total); 371 | } catch (error) { 372 | console.log(error); 373 | } 374 | 375 | // By Company Search (Elasticsearch) 376 | const esQuery = { 377 | query: { 378 | bool: { 379 | must:[ 380 | { term: { tags: 'hotel consultant' } }, 381 | { term: { industry: 'hospitality' } } 382 | ] 383 | } 384 | } 385 | } 386 | 387 | try { 388 | const response = await PDLJSClient.company.search.elastic({ searchQuery: esQuery, size: 10, sandbox: true }); 389 | 390 | console.log(response.total); 391 | } catch (error) { 392 | console.log(error); 393 | } 394 | ``` 395 | 396 | ## 🌐 Endpoints 397 | 398 | **Person Endpoints** 399 | | API Endpoint | PDLJS Function | 400 | |-|-| 401 | | [Person Enrichment API](https://docs.peopledatalabs.com/docs/enrichment-api) | `PDLJS.person.enrichment({ ...params })` | 402 | | [Person Preview Enrichment API](https://docs.peopledatalabs.com/docs/preview-enrichment-api) | `PDLJS.person.enrichmentPreview({ ...params })` | 403 | | [Person Bulk Person Enrichment API](https://docs.peopledatalabs.com/docs/bulk-enrichment-api) | `PDLJS.person.bulk.enrichment({ ...records })` | 404 | | [Person Search API](https://docs.peopledatalabs.com/docs/search-api) | SQL: `PDLJS.person.search.sql({ ...params })`
Elasticsearch: `PDLJS.person.search.elastic({ ...params })`| 405 | | [Person Identify API](https://docs.peopledatalabs.com/docs/identify-api) | `PDLJS.person.identify({ ...params })` | 406 | 407 | **Company Endpoints** 408 | | API Endpoint | PDLJS Function | 409 | |-|-| 410 | | [Company Enrichment API](https://docs.peopledatalabs.com/docs/company-enrichment-api) | `PDLJS.company.enrichment({ ...params })` | 411 | | [Company Bulk Enrichment API](https://docs.peopledatalabs.com/docs/bulk-company-enrichment-api) | `PDLJS.company.bulk.enrichment({ ...records })` | 412 | | [Company Search API](https://docs.peopledatalabs.com/docs/company-search-api) | SQL: `PDLJS.company.search.sql({ ...params })`
Elasticsearch: `PDLJS.company.search.elastic({ ...params })`| 413 | 414 | **Supporting Endpoints** 415 | | API Endpoint | PDLJS Function | 416 | |-|-| 417 | | [Autocomplete API](https://docs.peopledatalabs.com/docs/autocomplete-api) | `PDLJS.autocomplete({ ...params })` | 418 | | [Company Cleaner API](https://docs.peopledatalabs.com/docs/cleaner-apis#companyclean) | `PDLJS.company.cleaner({ ...params })` | 419 | | [Location Cleaner API](https://docs.peopledatalabs.com/docs/cleaner-apis#locationclean) | `PDLJS.location.cleaner({ ...params })` | 420 | | [School Cleaner API](https://docs.peopledatalabs.com/docs/cleaner-apis#schoolclean) | `PDLJS.school.cleaner({ ...params })` | 421 | | [Job Title Enrichment API](https://docs.peopledatalabs.com/docs/job-title-enrichment-api) | `PDLJS.jobTitle({ ...params })` | 422 | | [IP Enrichment API](https://docs.peopledatalabs.com/docs/ip-enrichment-api) | `PDLJS.ip({ ...params })` | 423 | 424 | **Sandbox Endpoints** 425 | | API Endpoint | PDLJS Function | 426 | |-|-| 427 | | [Person Enrichment Sandbox API](https://docs.peopledatalabs.com/docs/sandbox-apis) | `PDLJS.person.enrichment({ ...params, sandbox: true })` | 428 | | [Person Search Sandbox API](https://docs.peopledatalabs.com/docs/sandbox-apis) | SQL: `PDLJS.person.search.sql({ ...params, sandbox: true })`
Elasticsearch: `PDLJS.person.search.elastic({ ...params, sandbox: true })`| 429 | | [Person Identify Sandbox API](https://docs.peopledatalabs.com/docs/sandbox-apis) | `PDLJS.person.identify({ ...params, sandbox: true })` | 430 | | [Company Enrichment Sandbox API](https://docs.peopledatalabs.com/docs/sandbox-apis) | `PDLJS.company.enrichment({ ...params, sandbox: true })` | 431 | | [Company Search Sandbox API](https://docs.peopledatalabs.com/docs/sandbox-apis) | SQL: `PDLJS.company.search.sql({ ...params, sandbox: true })`
Elasticsearch: `PDLJS.company.search.elastic({ ...params, sandbox: true })`| 432 | 433 | ## 📘 Documentation 434 | 435 | All of our API endpoints are documented at: 436 | 437 | These docs describe the supported input parameters, output responses and also provide additional technical context. 438 | 439 | As illustrated in the [Endpoints](#endpoints) section above, each of our API endpoints is mapped to a specific method in the PDLJS class. For each of these class methods, **all function inputs are mapped as input parameters to the respective API endpoint**, meaning that you can use the API documentation linked above to determine the input parameters for each endpoint. 440 | 441 | As an example: 442 | 443 | The following is **valid** because `name` is a [supported input parameter to the Person Identify API](https://docs.peopledatalabs.com/docs/identify-api-reference#input-parameters): 444 | 445 | ```js 446 | PDLJS.person.identify({ name: 'sean thorne' }) 447 | ``` 448 | 449 | Conversely, this would be **invalid** because `fake_parameter` is not an input parameter to the Person Identify API: 450 | 451 | ```js 452 | PDLJS.person.identify({ fake_parameter: 'anything' }) 453 | ``` 454 | 455 | #### Special Note about Search API Support 456 | 457 | Our Person Search API and Company Search API endpoints both support two types of query syntax: you can construct search queries using either `SQL` or `Elasticsearch` syntax. 458 | 459 | In the PDLJS class, the person and company search functions are broken out into two syntax-specific methods as follows: 460 | | Data Type | Search Query Syntax | Function | 461 | | -- | -- | -- | 462 | | Person | SQL | `PDLJS.person.search.sql({ ...params })` | 463 | | Person | Elasticsearch | `PDLJS.person.search.elastic({ ...params })` | 464 | | Company | SQL | `PDLJS.company.search.sql({ ...params })` | 465 | | Company | Elasticsearch | `PDLJS.company.search.elastic({ ...params })` | 466 | 467 | You can pass your query to these methods using the special `searchQuery` function argument, as shown in the following example: 468 | 469 | ```js 470 | const sqlQuery = "SELECT * FROM company WHERE website='peopledatalabs.com';" 471 | 472 | try { 473 | const response = await PDLJS.company.search.sql({ searchQuery: sqlQuery, size: 10 }); 474 | 475 | console.log(response.total) 476 | } catch (error) { 477 | console.log(error) 478 | } 479 | ``` 480 | 481 | #### Upgrading to v6.X.X 482 | 483 | NOTE: When upgrading to v6.X.X from vX.X.X and below, Retrieve and Bulk Retrieve were both changed to make the `pretty`, `titlecase` and `filter_updated` to be siblings of the `requests` parameter. 484 | 485 | #### Upgrading to v5.X.X 486 | 487 | NOTE: When upgrading to v5.X.X from v4.X.X and below, Bulk Enrichment was moved from `PDLJS.person.bulk({ ...records })` to `PDLJS.person.bulk.enrichment({ ...records })` 488 | -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console: "off" */ 2 | 3 | import dotenv from 'dotenv'; 4 | import PDLJS from 'peopledatalabs'; 5 | 6 | dotenv.config({ path: '../.env.local' }); 7 | 8 | const PDLJSClient = new PDLJS({ apiKey: process.env.PDL_API_KEY }); 9 | 10 | // Person APIs 11 | 12 | PDLJSClient.person.enrichment({ phone: '4155688415' }).then((data) => { 13 | console.log('Person Enrichment API'); 14 | console.log(data); 15 | }).catch((error) => { 16 | console.log('Person Enrichment API'); 17 | console.log(error); 18 | }); 19 | 20 | PDLJSClient.person.enrichmentPreview({ phone: '4155688415' }).then((data) => { 21 | console.log('Person Preview Enrichment API'); 22 | console.log(data); 23 | }).catch((error) => { 24 | console.log('Person Preview Enrichment API'); 25 | console.log(error); 26 | }); 27 | 28 | PDLJSClient.person.identify({ phone: '4155688415' }).then((data) => { 29 | console.log('Person Identify API'); 30 | console.log(data); 31 | }).catch((error) => { 32 | console.log('Person Identify API'); 33 | console.log(error); 34 | }); 35 | 36 | const bulkEnrichmentRecords = { 37 | requests: [ 38 | { params: { profile: ['linkedin.com/in/seanthorne'] } }, 39 | { params: { profile: ['linkedin.com/in/randrewn'] } }, 40 | ], 41 | }; 42 | 43 | PDLJSClient.person.bulk.enrichment(bulkEnrichmentRecords).then((data) => { 44 | console.log('Person Bulk Enrichment API'); 45 | console.log(data); 46 | }).catch((error) => { 47 | console.log('Person Bulk Enrichment API'); 48 | console.log(error); 49 | }); 50 | 51 | PDLJSClient.person.search.sql({ 52 | searchQuery: "SELECT * FROM person WHERE location_country='mexico' AND job_title_role='health'AND phone_numbers IS NOT NULL;", 53 | size: 10, 54 | }).then((data) => { 55 | console.log('Person Search API - SQL'); 56 | console.log(data); 57 | }).catch((error) => { 58 | console.log('Person Search API - SQL'); 59 | console.log(error); 60 | }); 61 | 62 | PDLJSClient.person.search.elastic({ 63 | searchQuery: { 64 | query: { 65 | bool: { 66 | must: [{ term: { job_company_website: 'peopledatalabs.com' } }], 67 | }, 68 | }, 69 | }, 70 | size: 10, 71 | }).then((data) => { 72 | console.log('Person Search API - Elastic'); 73 | console.log(data); 74 | }).catch((error) => { 75 | console.log('Person Search API - Elastic'); 76 | console.log(error); 77 | }); 78 | 79 | // Company APIs 80 | 81 | PDLJSClient.company.enrichment({ website: 'peopledatalabs.com' }).then((data) => { 82 | console.log('Company Enrichment API'); 83 | console.log(data); 84 | }).catch((error) => { 85 | console.log('Company Enrichment API'); 86 | console.log(error); 87 | }); 88 | 89 | const bulkCompanyEnrichmentRecords = { 90 | requests: [ 91 | { params: { profile: ['linkedin.com/company/peopledatalabs'] } }, 92 | { params: { profile: ['linkedin.com/company/apple'] } }, 93 | ], 94 | }; 95 | 96 | PDLJSClient.company.bulk.enrichment(bulkCompanyEnrichmentRecords).then((data) => { 97 | console.log('Company Bulk Enrichment API'); 98 | console.log(data); 99 | }).catch((error) => { 100 | console.log('Company Bulk Enrichment API'); 101 | console.log(error); 102 | }); 103 | 104 | PDLJSClient.company.search.sql({ 105 | searchQuery: "SELECT * FROM company WHERE website = 'peopledatalabs.com';", 106 | size: 10, 107 | }).then((data) => { 108 | console.log('Company Search API - SQL'); 109 | console.log(data); 110 | }).catch((error) => { 111 | console.log('Company Search API - SQL'); 112 | console.log(error); 113 | }); 114 | 115 | PDLJSClient.company.search.elastic({ 116 | searchQuery: { 117 | query: { 118 | bool: { 119 | must: [{ term: { website: 'peopledatalabs.com' } }], 120 | }, 121 | }, 122 | }, 123 | size: 10, 124 | }).then((data) => { 125 | console.log('Company Search API - Elastic'); 126 | console.log(data); 127 | }).catch((error) => { 128 | console.log('Company Search API - Elastic'); 129 | console.log(error); 130 | }); 131 | 132 | // IP APIs 133 | 134 | PDLJSClient.ip({ ip: '72.212.42.228' }).then((data) => { 135 | console.log('IP Enrichment API'); 136 | console.log(data); 137 | }).catch((error) => { 138 | console.log('IP Enrichment API'); 139 | console.log(error); 140 | }); 141 | 142 | // Supporting APIs 143 | 144 | PDLJSClient.autocomplete({ 145 | field: 'skill', 146 | text: 'c++', 147 | size: 10, 148 | }).then((data) => { 149 | console.log('Autocomplete API'); 150 | console.log(data); 151 | }).catch((error) => { 152 | console.log('Autocomplete API'); 153 | console.log(error); 154 | }); 155 | 156 | PDLJSClient.company.cleaner({ name: 'peopledatalabs' }).then((data) => { 157 | console.log('Company Cleaner API'); 158 | console.log(data); 159 | }).catch((error) => { 160 | console.log('Company Cleaner API'); 161 | console.log(error); 162 | }); 163 | 164 | PDLJSClient.location.cleaner({ location: '455 Market Street, San Francisco, California 94105, US' }).then((data) => { 165 | console.log('Location Cleaner API'); 166 | console.log(data); 167 | }).catch((error) => { 168 | console.log('Location Cleaner API'); 169 | console.log(error); 170 | }); 171 | 172 | PDLJSClient.school.cleaner({ name: 'university of oregon' }).then((data) => { 173 | console.log('School Cleaner API'); 174 | console.log(data); 175 | }).catch((error) => { 176 | console.log('School Cleaner API'); 177 | console.log(error); 178 | }); 179 | 180 | PDLJSClient.jobTitle({ jobTitle: 'software engineer' }).then((data) => { 181 | console.log('Job Title API'); 182 | console.log(data); 183 | }).catch((error) => { 184 | console.log('Job Title API'); 185 | console.log(error); 186 | }); 187 | 188 | // Sandbox APIs 189 | 190 | PDLJSClient.person.enrichment({ email: 'chad_taylor@carroll-inc.com', sandbox: true }).then((data) => { 191 | console.log('Person Enrichment Sandbox API'); 192 | console.log(data); 193 | }).catch((error) => { 194 | console.log('Person Enrichment Sandbox API'); 195 | console.log(error); 196 | }); 197 | 198 | PDLJSClient.person.search.sql({ 199 | searchQuery: "SELECT * FROM person WHERE location_country='united states';", 200 | size: 10, 201 | sandbox: true, 202 | }).then((data) => { 203 | console.log('Person Search Sandbox API - SQL'); 204 | console.log(data.rateLimit); 205 | }).catch((error) => { 206 | console.log('Person Search Sandbox API - SQL'); 207 | console.log(error); 208 | }); 209 | 210 | PDLJSClient.person.identify({ company: 'carroll inc', sandbox: true }).then((data) => { 211 | console.log('Person Identify Sandbox API'); 212 | console.log(data); 213 | }).catch((error) => { 214 | console.log('Person Identify Sandbox API'); 215 | console.log(error); 216 | }); 217 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "peopledatalabs-example", 3 | "version": "1.0.0", 4 | "description": "Example project with People Data Labs API library", 5 | "packageManager": "pnpm@10.9.0", 6 | "main": "index.js", 7 | "type": "module", 8 | "scripts": { 9 | "start": "node index.js", 10 | "clean": "rm -rf node_modules && rm -rf pnpm-lock.yaml", 11 | "check-packages": "pnpm dlx npm-check-updates" 12 | }, 13 | "author": "People Data Labs", 14 | "license": "MIT", 15 | "dependencies": { 16 | "dotenv": "^16.5.0", 17 | "peopledatalabs": "*" 18 | } 19 | } -------------------------------------------------------------------------------- /example/pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | dependencies: 11 | dotenv: 12 | specifier: ^16.5.0 13 | version: 16.5.0 14 | peopledatalabs: 15 | specifier: '*' 16 | version: 10.0.1 17 | 18 | packages: 19 | 20 | asynckit@0.4.0: 21 | resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} 22 | 23 | axios@1.8.3: 24 | resolution: {integrity: sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==} 25 | 26 | call-bind-apply-helpers@1.0.2: 27 | resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} 28 | engines: {node: '>= 0.4'} 29 | 30 | combined-stream@1.0.8: 31 | resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} 32 | engines: {node: '>= 0.8'} 33 | 34 | copy-anything@3.0.5: 35 | resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} 36 | engines: {node: '>=12.13'} 37 | 38 | delayed-stream@1.0.0: 39 | resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} 40 | engines: {node: '>=0.4.0'} 41 | 42 | dotenv@16.5.0: 43 | resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==} 44 | engines: {node: '>=12'} 45 | 46 | dunder-proto@1.0.1: 47 | resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} 48 | engines: {node: '>= 0.4'} 49 | 50 | es-define-property@1.0.1: 51 | resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} 52 | engines: {node: '>= 0.4'} 53 | 54 | es-errors@1.3.0: 55 | resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} 56 | engines: {node: '>= 0.4'} 57 | 58 | es-object-atoms@1.1.1: 59 | resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} 60 | engines: {node: '>= 0.4'} 61 | 62 | es-set-tostringtag@2.1.0: 63 | resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} 64 | engines: {node: '>= 0.4'} 65 | 66 | follow-redirects@1.15.9: 67 | resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} 68 | engines: {node: '>=4.0'} 69 | peerDependencies: 70 | debug: '*' 71 | peerDependenciesMeta: 72 | debug: 73 | optional: true 74 | 75 | form-data@4.0.2: 76 | resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} 77 | engines: {node: '>= 6'} 78 | 79 | function-bind@1.1.2: 80 | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 81 | 82 | get-intrinsic@1.3.0: 83 | resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} 84 | engines: {node: '>= 0.4'} 85 | 86 | get-proto@1.0.1: 87 | resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} 88 | engines: {node: '>= 0.4'} 89 | 90 | gopd@1.2.0: 91 | resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} 92 | engines: {node: '>= 0.4'} 93 | 94 | has-symbols@1.1.0: 95 | resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} 96 | engines: {node: '>= 0.4'} 97 | 98 | has-tostringtag@1.0.2: 99 | resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} 100 | engines: {node: '>= 0.4'} 101 | 102 | hasown@2.0.2: 103 | resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} 104 | engines: {node: '>= 0.4'} 105 | 106 | is-what@4.1.16: 107 | resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} 108 | engines: {node: '>=12.13'} 109 | 110 | math-intrinsics@1.1.0: 111 | resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} 112 | engines: {node: '>= 0.4'} 113 | 114 | mime-db@1.52.0: 115 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} 116 | engines: {node: '>= 0.6'} 117 | 118 | mime-types@2.1.35: 119 | resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} 120 | engines: {node: '>= 0.6'} 121 | 122 | peopledatalabs@10.0.1: 123 | resolution: {integrity: sha512-r/fBFLABLE+hJS+6dSvBFiaD4RQao1rdjzDjdwzRBAdJkQJ5Rd5YLsylp6kpVosPdRkqCj4nW/OIA6ufUEgZAQ==} 124 | 125 | proxy-from-env@1.1.0: 126 | resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} 127 | 128 | snapshots: 129 | 130 | asynckit@0.4.0: {} 131 | 132 | axios@1.8.3: 133 | dependencies: 134 | follow-redirects: 1.15.9 135 | form-data: 4.0.2 136 | proxy-from-env: 1.1.0 137 | transitivePeerDependencies: 138 | - debug 139 | 140 | call-bind-apply-helpers@1.0.2: 141 | dependencies: 142 | es-errors: 1.3.0 143 | function-bind: 1.1.2 144 | 145 | combined-stream@1.0.8: 146 | dependencies: 147 | delayed-stream: 1.0.0 148 | 149 | copy-anything@3.0.5: 150 | dependencies: 151 | is-what: 4.1.16 152 | 153 | delayed-stream@1.0.0: {} 154 | 155 | dotenv@16.5.0: {} 156 | 157 | dunder-proto@1.0.1: 158 | dependencies: 159 | call-bind-apply-helpers: 1.0.2 160 | es-errors: 1.3.0 161 | gopd: 1.2.0 162 | 163 | es-define-property@1.0.1: {} 164 | 165 | es-errors@1.3.0: {} 166 | 167 | es-object-atoms@1.1.1: 168 | dependencies: 169 | es-errors: 1.3.0 170 | 171 | es-set-tostringtag@2.1.0: 172 | dependencies: 173 | es-errors: 1.3.0 174 | get-intrinsic: 1.3.0 175 | has-tostringtag: 1.0.2 176 | hasown: 2.0.2 177 | 178 | follow-redirects@1.15.9: {} 179 | 180 | form-data@4.0.2: 181 | dependencies: 182 | asynckit: 0.4.0 183 | combined-stream: 1.0.8 184 | es-set-tostringtag: 2.1.0 185 | mime-types: 2.1.35 186 | 187 | function-bind@1.1.2: {} 188 | 189 | get-intrinsic@1.3.0: 190 | dependencies: 191 | call-bind-apply-helpers: 1.0.2 192 | es-define-property: 1.0.1 193 | es-errors: 1.3.0 194 | es-object-atoms: 1.1.1 195 | function-bind: 1.1.2 196 | get-proto: 1.0.1 197 | gopd: 1.2.0 198 | has-symbols: 1.1.0 199 | hasown: 2.0.2 200 | math-intrinsics: 1.1.0 201 | 202 | get-proto@1.0.1: 203 | dependencies: 204 | dunder-proto: 1.0.1 205 | es-object-atoms: 1.1.1 206 | 207 | gopd@1.2.0: {} 208 | 209 | has-symbols@1.1.0: {} 210 | 211 | has-tostringtag@1.0.2: 212 | dependencies: 213 | has-symbols: 1.1.0 214 | 215 | hasown@2.0.2: 216 | dependencies: 217 | function-bind: 1.1.2 218 | 219 | is-what@4.1.16: {} 220 | 221 | math-intrinsics@1.1.0: {} 222 | 223 | mime-db@1.52.0: {} 224 | 225 | mime-types@2.1.35: 226 | dependencies: 227 | mime-db: 1.52.0 228 | 229 | peopledatalabs@10.0.1: 230 | dependencies: 231 | axios: 1.8.3 232 | copy-anything: 3.0.5 233 | transitivePeerDependencies: 234 | - debug 235 | 236 | proxy-from-env@1.1.0: {} 237 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "peopledatalabs", 3 | "version": "12.1.0", 4 | "description": "JavaScript client with TypeScript support for the People Data Labs API", 5 | "packageManager": "pnpm@10.11.0", 6 | "type": "module", 7 | "main": "dist/index.cjs", 8 | "module": "dist/index.m.js", 9 | "umd:main": "dist/index.umd.js", 10 | "types": "dist/index.d.ts", 11 | "source": "src/index.ts", 12 | "files": [ 13 | "dist/**" 14 | ], 15 | "scripts": { 16 | "build": "rm -rf dist && microbundle", 17 | "dev": "microbundle watch -p 6008", 18 | "test": "pnpm run build && pnpm run mocha", 19 | "mocha": "mocha --recursive 'tests/**/*.js' --timeout 5000", 20 | "pub": "pnpm run build && pnpm publish --no-git-checks --provenance --access public", 21 | "lint": "eslint ./src --fix", 22 | "clean": "rm -rf node_modules && rm -rf pnpm-lock.yaml", 23 | "check-packages": "pnpm dlx npm-check-updates" 24 | }, 25 | "repository": { 26 | "type": "git", 27 | "url": "git+https://github.com/peopledatalabs/peopledatalabs-js.git" 28 | }, 29 | "keywords": [ 30 | "peopledatalabs", 31 | "People Data Labs", 32 | "data enrichment", 33 | "person enrichment", 34 | "person search", 35 | "company enrichment", 36 | "company search", 37 | "javascript", 38 | "api", 39 | "client", 40 | "sdk" 41 | ], 42 | "author": "People Data Labs", 43 | "license": "MIT", 44 | "bugs": { 45 | "url": "https://github.com/peopledatalabs/peopledatalabs-js/issues" 46 | }, 47 | "homepage": "https://docs.peopledatalabs.com/docs/javascript-sdk", 48 | "devDependencies": { 49 | "@stylistic/eslint-plugin": "^3.1.0", 50 | "@typescript-eslint/eslint-plugin": "7.18.0", 51 | "@typescript-eslint/parser": "7.18.0", 52 | "chai": "^5.2.0", 53 | "dotenv": "^16.5.0", 54 | "eslint": "^8.57.1", 55 | "eslint-config-airbnb": "^19.0.4", 56 | "eslint-config-airbnb-base": "^15.0.0", 57 | "eslint-config-airbnb-typescript": "^18.0.0", 58 | "eslint-plugin-import": "^2.31.0", 59 | "eslint-plugin-import-newlines": "^1.4.0", 60 | "eslint-plugin-jsx-a11y": "^6.10.2", 61 | "eslint-plugin-react": "^7.37.5", 62 | "eslint-plugin-react-hooks": "^5.2.0", 63 | "eslint-plugin-simple-import-sort": "^12.1.1", 64 | "eslint-plugin-sort-destructure-keys": "^2.0.0", 65 | "eslint-plugin-sort-keys-fix": "^1.1.2", 66 | "eslint-plugin-typescript-sort-keys": "^3.3.0", 67 | "eslint-plugin-unused-imports": "^3.2.0", 68 | "esm": "^3.2.25", 69 | "microbundle": "^0.15.1", 70 | "mocha": "^11.5.0", 71 | "typescript": "^5.8.3" 72 | }, 73 | "dependencies": { 74 | "axios": "^1.9.0", 75 | "copy-anything": "3.0.5" 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/endpoints/autocomplete/index.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | import { check, errorHandler } from '../../errors.js'; 4 | import type { AutoCompleteParams, AutoCompleteResponse } from '../../types/autocomplete-types.js'; 5 | import { parseRateLimitingResponse } from '../../utils/api-utils.js'; 6 | 7 | export default ( 8 | basePath: string, 9 | apiKey: string, 10 | params: AutoCompleteParams, 11 | ) => new Promise((resolve, reject) => { 12 | check(params, basePath, apiKey, null, 'autocomplete').then(() => { 13 | const { field, pretty, size, text, titlecase } = params; 14 | 15 | const autocompleteParams = { 16 | field, 17 | text: text || '', 18 | size: size || 10, 19 | pretty: pretty || false, 20 | titlecase: titlecase || false, 21 | }; 22 | 23 | const headers = { 24 | 'Accept-Encoding': 'gzip', 25 | 'User-Agent': 'PDL-JS-SDK', 26 | }; 27 | 28 | axios.get(`${basePath}/autocomplete`, { 29 | params: { 30 | api_key: apiKey, 31 | ...autocompleteParams, 32 | }, 33 | headers, 34 | }).then((response) => { 35 | if (response?.data?.status === 200) { 36 | resolve(parseRateLimitingResponse(response)); 37 | } 38 | }).catch((error) => { 39 | reject(errorHandler(error)); 40 | }); 41 | }).catch((error) => { 42 | reject(error); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /src/endpoints/bulkCompanyEnrichment/index.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | import { check, errorHandler } from '../../errors.js'; 4 | import { BulkCompanyEnrichmentParams, BulkCompanyEnrichmentResponse } from '../../types/bulk-types.js'; 5 | import { parseRateLimitingResponse } from '../../utils/api-utils.js'; 6 | 7 | export default (basePath: string, apiKey: string, records: BulkCompanyEnrichmentParams) => { 8 | const headers = { 9 | 'Content-Type': 'application/json', 10 | 'Accept-Encoding': 'gzip', 11 | 'X-Api-Key': apiKey, 12 | 'User-Agent': 'PDL-JS-SDK', 13 | }; 14 | 15 | return new Promise((resolve, reject) => { 16 | check(records, basePath, apiKey, 'Records', 'bulk').then(() => { 17 | axios.post(`${basePath}/company/enrich/bulk`, records, { 18 | headers, 19 | }).then((response) => { 20 | resolve(parseRateLimitingResponse(response)); 21 | }).catch((error) => { 22 | reject(errorHandler(error)); 23 | }); 24 | }).catch((error) => { 25 | reject(error); 26 | }); 27 | }); 28 | }; 29 | -------------------------------------------------------------------------------- /src/endpoints/bulkEnrichment/index.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | import { check, errorHandler } from '../../errors.js'; 4 | import { BulkPersonEnrichmentParams, BulkPersonEnrichmentResponse } from '../../types/bulk-types.js'; 5 | import { parseRateLimitingResponse } from '../../utils/api-utils.js'; 6 | 7 | export default (basePath: string, apiKey: string, records: BulkPersonEnrichmentParams) => { 8 | const headers = { 9 | 'Content-Type': 'application/json', 10 | 'Accept-Encoding': 'gzip', 11 | 'X-Api-Key': apiKey, 12 | 'User-Agent': 'PDL-JS-SDK', 13 | }; 14 | 15 | return new Promise((resolve, reject) => { 16 | check(records, basePath, apiKey, 'Records', 'bulk').then(() => { 17 | axios.post(`${basePath}/person/bulk`, records, { 18 | headers, 19 | }).then((response) => { 20 | resolve(parseRateLimitingResponse(response)); 21 | }).catch((error) => { 22 | reject(errorHandler(error)); 23 | }); 24 | }).catch((error) => { 25 | reject(error); 26 | }); 27 | }); 28 | }; 29 | -------------------------------------------------------------------------------- /src/endpoints/bulkRetrieve/index.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | import { check, errorHandler } from '../../errors.js'; 4 | import { ApiBulkPersonRetrieveParams, BulkPersonRetrieveParams, BulkPersonRetrieveResponse } from '../../types/bulk-retrieve-types.js'; 5 | import { parseRateLimitingResponse } from '../../utils/api-utils.js'; 6 | 7 | const transformBulkRetrieveParams = (params: BulkPersonRetrieveParams): ApiBulkPersonRetrieveParams => { 8 | const filter = params.filter_updated; 9 | if (filter == null) { 10 | return { 11 | ...params, 12 | filter_updated: undefined, 13 | }; 14 | } 15 | const filtersArray = Array.isArray(filter) ? filter : [filter]; 16 | const filterUpdated = filtersArray.join(','); 17 | return { 18 | ...params, 19 | filter_updated: filterUpdated, 20 | }; 21 | }; 22 | 23 | export default (basePath: string, apiKey: string, records: BulkPersonRetrieveParams) => { 24 | const headers = { 25 | 'Content-Type': 'application/json', 26 | 'Accept-Encoding': 'gzip', 27 | 'X-Api-Key': apiKey, 28 | 'User-Agent': 'PDL-JS-SDK', 29 | }; 30 | 31 | return new Promise((resolve, reject) => { 32 | check(records, basePath, apiKey, 'Records', 'bulk').then(() => { 33 | const apiParams = transformBulkRetrieveParams(records); 34 | axios.post(`${basePath}/person/retrieve/bulk`, apiParams, { 35 | headers, 36 | }).then((response) => { 37 | resolve(parseRateLimitingResponse(response)); 38 | }).catch((error) => { 39 | reject(errorHandler(error)); 40 | }); 41 | }).catch((error) => { 42 | reject(error); 43 | }); 44 | }); 45 | }; 46 | -------------------------------------------------------------------------------- /src/endpoints/cleaner/index.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | import { check, errorHandler } from '../../errors.js'; 4 | import { BaseResponse } from '../../types/api-types.js'; 5 | import { CleanerType } from '../../types/cleaner-types.js'; 6 | import { parseRateLimitingResponse } from '../../utils/api-utils.js'; 7 | 8 | export default ( 9 | basePath: string, 10 | apiKey: string, 11 | params: T, 12 | type: CleanerType, 13 | ) => new Promise((resolve, reject) => { 14 | check(params, basePath, apiKey, null, 'cleaner').then(() => { 15 | const headers = { 16 | 'Accept-Encoding': 'gzip', 17 | 'User-Agent': 'PDL-JS-SDK', 18 | }; 19 | 20 | axios.get(`${basePath}/${type}/clean`, { 21 | params: { 22 | api_key: apiKey, 23 | ...params, 24 | }, 25 | headers, 26 | }).then((response) => { 27 | if (response?.data?.status === 200) { 28 | resolve(parseRateLimitingResponse(response)); 29 | } 30 | }).catch((error) => { 31 | reject(errorHandler(error)); 32 | }); 33 | }).catch((error) => { 34 | reject(error); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /src/endpoints/enrichment/index.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { copy } from 'copy-anything'; 3 | 4 | import { check, errorHandler } from '../../errors.js'; 5 | import { CompanyEnrichmentParams, CompanyEnrichmentResponse, EnrichmentType, PersonEnrichmentParams, PersonEnrichmentResponse } from '../../types/enrichment-types.js'; 6 | import { parseRateLimitingResponse } from '../../utils/api-utils.js'; 7 | 8 | export default ( 9 | basePath: string, 10 | sandboxBasePath: string, 11 | apiKey: string, 12 | params: T, 13 | type: EnrichmentType, 14 | ) => new Promise((resolve, reject) => { 15 | check(params, basePath, apiKey, null, 'enrichment').then(() => { 16 | const headers = { 17 | 'Accept-Encoding': 'gzip', 18 | 'User-Agent': 'PDL-JS-SDK', 19 | }; 20 | 21 | const url = params.sandbox && type === 'person' ? `${sandboxBasePath}/${type}/enrich` : `${basePath}/${type}/enrich`; 22 | 23 | const newParams = copy(params); 24 | const p = new URLSearchParams(); 25 | delete newParams.sandbox; 26 | 27 | Object.entries(newParams).forEach(([key, value]: [string, any]) => { 28 | if (key === 'profile') { 29 | if (Array.isArray(value)) { 30 | p.append(key, JSON.stringify(value)); 31 | } else if (value) { 32 | p.append(key, value); 33 | } 34 | } else if (typeof value === 'object') { 35 | if (Array.isArray(value)) { 36 | value.forEach((member) => { 37 | if (member) { 38 | p.append(key, (member)); 39 | } 40 | }); 41 | } else if (value) { 42 | p.append(key, JSON.stringify(value)); 43 | } 44 | } else if (value) { 45 | p.append(key, (value)); 46 | } 47 | }); 48 | 49 | p.append('api_key', apiKey); 50 | 51 | axios.get(url, { 52 | params: p, 53 | headers, 54 | }).then((response) => { 55 | if (response?.data?.status === 200) { 56 | resolve(parseRateLimitingResponse(response)); 57 | } 58 | }).catch((error) => { 59 | reject(errorHandler(error)); 60 | }); 61 | }).catch((error) => { 62 | reject(error); 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /src/endpoints/enrichmentPreview/index.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { copy } from 'copy-anything'; 3 | 4 | import { check, errorHandler } from '../../errors.js'; 5 | import { PersonEnrichmentPreviewParams, PersonEnrichmentPreviewResponse } from '../../types/enrichment-types.js'; 6 | import { parseRateLimitingResponse } from '../../utils/api-utils.js'; 7 | 8 | export default ( 9 | basePath: string, 10 | sandboxBasePath: string, 11 | apiKey: string, 12 | params: PersonEnrichmentPreviewParams, 13 | ) => new Promise((resolve, reject) => { 14 | check(params, basePath, apiKey, null, 'enrichment').then(() => { 15 | const headers = { 16 | 'Accept-Encoding': 'gzip', 17 | 'User-Agent': 'PDL-JS-SDK', 18 | }; 19 | 20 | const url = params.sandbox ? `${sandboxBasePath}/person/enrich/preview` : `${basePath}/person/enrich/preview`; 21 | 22 | const newParams = copy(params); 23 | const p = new URLSearchParams(); 24 | delete newParams.sandbox; 25 | 26 | Object.entries(newParams).forEach(([key, value]: [string, any]) => { 27 | if (key === 'profile') { 28 | if (Array.isArray(value)) { 29 | p.append(key, JSON.stringify(value)); 30 | } else if (value) { 31 | p.append(key, value); 32 | } 33 | } else if (typeof value === 'object') { 34 | if (Array.isArray(value)) { 35 | value.forEach((member) => { 36 | if (member) { 37 | p.append(key, (member)); 38 | } 39 | }); 40 | } else if (value) { 41 | p.append(key, JSON.stringify(value)); 42 | } 43 | } else if (value) { 44 | p.append(key, (value)); 45 | } 46 | }); 47 | 48 | p.append('api_key', apiKey); 49 | 50 | axios.get(url, { 51 | params: p, 52 | headers, 53 | }).then((response) => { 54 | if (response?.data?.status === 200) { 55 | resolve(parseRateLimitingResponse(response)); 56 | } 57 | }).catch((error) => { 58 | reject(errorHandler(error)); 59 | }); 60 | }).catch((error) => { 61 | reject(error); 62 | }); 63 | }); 64 | -------------------------------------------------------------------------------- /src/endpoints/identify/index.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { copy } from 'copy-anything'; 3 | 4 | import { check, errorHandler } from '../../errors.js'; 5 | import { IdentifyParams, IdentifyResponse } from '../../types/identify-types.js'; 6 | import { parseRateLimitingResponse } from '../../utils/api-utils.js'; 7 | 8 | export default ( 9 | basePath: string, 10 | sandboxBasePath: string, 11 | apiKey: string, 12 | params: IdentifyParams, 13 | ) => new Promise((resolve, reject) => { 14 | check(params, basePath, apiKey, null, 'identify').then(() => { 15 | const headers = { 16 | 'Accept-Encoding': 'gzip', 17 | 'User-Agent': 'PDL-JS-SDK', 18 | }; 19 | 20 | const url = params.sandbox ? `${sandboxBasePath}/person/identify` : `${basePath}/person/identify`; 21 | 22 | const newParams = copy(params); 23 | const p = new URLSearchParams(); 24 | delete newParams.sandbox; 25 | 26 | Object.entries(newParams).forEach(([key, value]: [string, any]) => { 27 | if (key === 'profile') { 28 | if (Array.isArray(value)) { 29 | p.append(key, JSON.stringify(value)); 30 | } else if (value) { 31 | p.append(key, value); 32 | } 33 | } else if (typeof value === 'object') { 34 | if (Array.isArray(value)) { 35 | value.forEach((member) => { 36 | if (member) { 37 | p.append(key, (member)); 38 | } 39 | }); 40 | } else if (value) { 41 | p.append(key, JSON.stringify(value)); 42 | } 43 | } else if (value) { 44 | p.append(key, (value)); 45 | } 46 | }); 47 | 48 | p.append('api_key', apiKey); 49 | 50 | axios.get(url, { 51 | params: p, 52 | headers, 53 | }).then((response) => { 54 | if (response?.data?.status === 200) { 55 | resolve(parseRateLimitingResponse(response)); 56 | } 57 | }).catch((error) => { 58 | reject(errorHandler(error)); 59 | }); 60 | }).catch((error) => { 61 | reject(error); 62 | }); 63 | }); 64 | -------------------------------------------------------------------------------- /src/endpoints/index.ts: -------------------------------------------------------------------------------- 1 | import autocomplete from './autocomplete/index.js'; 2 | import bulkCompanyEnrichment from './bulkCompanyEnrichment/index.js'; 3 | import bulkEnrichment from './bulkEnrichment/index.js'; 4 | import bulkRetrieve from './bulkRetrieve/index.js'; 5 | import cleaner from './cleaner/index.js'; 6 | import enrichment from './enrichment/index.js'; 7 | import enrichmentPreview from './enrichmentPreview/index.js'; 8 | import identify from './identify/index.js'; 9 | import jobTitle from './jobTitle/index.js'; 10 | import retrieve from './retrieve/index.js'; 11 | import search from './search/index.js'; 12 | 13 | export { autocomplete, bulkCompanyEnrichment, bulkEnrichment, bulkRetrieve, cleaner, enrichment, enrichmentPreview, identify, jobTitle, retrieve, search }; 14 | -------------------------------------------------------------------------------- /src/endpoints/ip/index.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | import { check, errorHandler } from '../../errors.js'; 4 | import { IPParams, IPResponse } from '../../types/ip-types.js'; 5 | import { parseRateLimitingResponse } from '../../utils/api-utils.js'; 6 | 7 | export default ( 8 | basePath: string, 9 | apiKey: string, 10 | params: IPParams, 11 | ) => new Promise((resolve, reject) => { 12 | check(params, basePath, apiKey, null, 'ip').then(() => { 13 | const headers = { 14 | 'Accept-Encoding': 'gzip', 15 | 'User-Agent': 'PDL-JS-SDK', 16 | }; 17 | 18 | axios.get(`${basePath}/ip/enrich`, { 19 | params: { 20 | api_key: apiKey, 21 | ...params, 22 | }, 23 | headers, 24 | }).then((response) => { 25 | if (response?.data?.status === 200) { 26 | resolve(parseRateLimitingResponse(response)); 27 | } 28 | }).catch((error) => { 29 | reject(errorHandler(error)); 30 | }); 31 | }).catch((error) => { 32 | reject(error); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /src/endpoints/jobTitle/index.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | import { check, errorHandler } from '../../errors.js'; 4 | import { JobTitleParams, JobTitleResponse } from '../../types/jobTitle-types.js'; 5 | import { parseRateLimitingResponse } from '../../utils/api-utils.js'; 6 | 7 | export default ( 8 | basePath: string, 9 | apiKey: string, 10 | params: JobTitleParams, 11 | ) => new Promise((resolve, reject) => { 12 | check(params, basePath, apiKey, null, 'jobTitle').then(() => { 13 | const { 14 | jobTitle, pretty, 15 | } = params; 16 | 17 | const jobTitleParams = { 18 | job_title: jobTitle, 19 | pretty: pretty || false, 20 | }; 21 | 22 | const headers = { 23 | 'Accept-Encoding': 'gzip', 24 | 'User-Agent': 'PDL-JS-SDK', 25 | }; 26 | 27 | axios.get(`${basePath}/job_title/enrich`, { 28 | params: { 29 | api_key: apiKey, 30 | ...jobTitleParams, 31 | }, 32 | headers, 33 | }).then((response) => { 34 | if (response?.data?.status === 200) { 35 | resolve(parseRateLimitingResponse(response)); 36 | } 37 | }).catch((error) => { 38 | reject(errorHandler(error)); 39 | }); 40 | }).catch((error) => { 41 | reject(error); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /src/endpoints/retrieve/index.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | import { check, errorHandler } from '../../errors.js'; 4 | import { ApiRetrieveParams, RetrieveParams, RetrieveResponse } from '../../types/retrieve-types.js'; 5 | import { parseRateLimitingResponse } from '../../utils/api-utils.js'; 6 | 7 | const transformRetrieveParams = (params: RetrieveParams): ApiRetrieveParams => { 8 | const filter = params.filter_updated; 9 | if (filter == null) { 10 | return { 11 | ...params, 12 | filter_updated: undefined, 13 | }; 14 | } 15 | const filtersArray = Array.isArray(filter) ? filter : [filter]; 16 | const filterUpdated = filtersArray.join(','); 17 | return { 18 | ...params, 19 | filter_updated: filterUpdated, 20 | }; 21 | }; 22 | 23 | export default ( 24 | basePath: string, 25 | apiKey: string, 26 | params: RetrieveParams, 27 | ) => new Promise((resolve, reject) => { 28 | check(params, basePath, apiKey, 'ID', 'retrieve').then(() => { 29 | const headers = { 30 | 'Accept-Encoding': 'gzip', 31 | 'User-Agent': 'PDL-JS-SDK', 32 | }; 33 | const apiParams = transformRetrieveParams(params); 34 | 35 | axios.get(`${basePath}/person/retrieve/${params.id}`, { 36 | params: { 37 | api_key: apiKey, 38 | ...apiParams, 39 | }, 40 | headers, 41 | }).then((response) => { 42 | if (response?.data?.status === 200) { 43 | resolve(parseRateLimitingResponse(response)); 44 | } 45 | }).catch((error) => { 46 | reject(errorHandler(error)); 47 | }); 48 | }).catch((error) => { 49 | reject(error); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /src/endpoints/search/index.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | import { check, errorHandler } from '../../errors.js'; 4 | import { BaseResponse } from '../../types/api-types.js'; 5 | import { BaseSearchParams, SearchType } from '../../types/search-types.js'; 6 | import { parseRateLimitingResponse } from '../../utils/api-utils.js'; 7 | 8 | export default ( 9 | basePath: string, 10 | sandboxBasePath: string, 11 | apiKey: string, 12 | searchType: SearchType, 13 | params: T, 14 | type: string, 15 | ) => new Promise((resolve, reject) => { 16 | check(params, basePath, apiKey, null, 'search').then(() => { 17 | const { 18 | // eslint-disable-next-line @typescript-eslint/naming-convention 19 | data_include, dataset, pretty, sandbox, scroll_token, searchQuery, size, titlecase, 20 | } = params; 21 | 22 | const searchParams = { 23 | titlecase: titlecase || false, 24 | dataset: dataset || 'all', 25 | scroll_token: scroll_token || null, 26 | size: size || 10, 27 | [`${searchType === 'sql' ? 'sql' : 'query'}`]: searchQuery, 28 | pretty: pretty || false, 29 | data_include: data_include || null, 30 | }; 31 | 32 | const headers = { 33 | 'Content-Type': 'application/json', 34 | 'Accept-Encoding': 'gzip', 35 | 'X-Api-Key': apiKey, 36 | 'User-Agent': 'PDL-JS-SDK', 37 | }; 38 | 39 | const url = sandbox && type === 'person' ? `${sandboxBasePath}/person/search` : `${basePath}/${type}/search`; 40 | 41 | axios.post(url, searchParams, { 42 | headers, 43 | }).then((response) => { 44 | if (response?.data?.status === 200) { 45 | resolve(parseRateLimitingResponse(response)); 46 | } 47 | }).catch((error) => { 48 | reject(errorHandler(error)); 49 | }); 50 | }).catch((error) => { 51 | reject(error); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /src/errors.ts: -------------------------------------------------------------------------------- 1 | import { AxiosError } from 'axios'; 2 | 3 | import { AutoCompleteParams } from './types/autocomplete-types.js'; 4 | import { ErrorEndpoint, PdlError } from './types/error-types.js'; 5 | import { IPParams } from './types/ip-types.js'; 6 | import { JobTitleParams } from './types/jobTitle-types.js'; 7 | import { RetrieveParams } from './types/retrieve-types.js'; 8 | import { BaseSearchParams } from './types/search-types.js'; 9 | import { parseRateLimitingResponse } from './utils/api-utils.js'; 10 | 11 | const check = ( 12 | params: unknown, 13 | basePath: string, 14 | apiKey: string, 15 | type: string | null, 16 | endpoint: ErrorEndpoint, 17 | ) => new Promise((resolve, reject) => { 18 | const error: { message?: string, status?: number } = { }; 19 | 20 | if (!params) { 21 | error.message = `Missing ${type || 'Params'}`; 22 | error.status = 400; 23 | reject(error); 24 | } 25 | 26 | if (endpoint === 'search') { 27 | const { searchQuery } = params as BaseSearchParams; 28 | if (!searchQuery) { 29 | error.message = 'Missing searchQuery'; 30 | error.status = 400; 31 | reject(error); 32 | } 33 | } 34 | 35 | if (endpoint === 'retrieve') { 36 | const { id } = params as RetrieveParams; 37 | if (!id) { 38 | error.message = 'Missing id'; 39 | error.status = 400; 40 | reject(error); 41 | } 42 | } 43 | 44 | if (endpoint === 'autocomplete') { 45 | const { field } = params as AutoCompleteParams; 46 | const validFields = ['all_location', 'class', 'company', 'country', 'industry', 'location', 'location_name', 'major', 'region', 'role', 'school', 'sub_role', 'skill', 'title']; 47 | if (!field) { 48 | error.message = 'Missing field'; 49 | error.status = 400; 50 | reject(error); 51 | } else if (validFields.indexOf(field) === -1) { 52 | error.message = `field should be one of: ${validFields}`; 53 | error.status = 400; 54 | reject(error); 55 | } 56 | } 57 | 58 | if (endpoint === 'jobTitle') { 59 | const { jobTitle } = params as JobTitleParams; 60 | if (!jobTitle) { 61 | error.message = 'Missing jobTitle'; 62 | error.status = 400; 63 | reject(error); 64 | } 65 | } 66 | 67 | if (endpoint === 'ip') { 68 | const { ip } = params as IPParams; 69 | if (!ip) { 70 | error.message = 'Missing ip'; 71 | error.status = 400; 72 | reject(error); 73 | } 74 | } 75 | 76 | if (!basePath) { 77 | error.message = 'Missing API Base Path'; 78 | error.status = 400; 79 | reject(error); 80 | } 81 | 82 | if (!apiKey || apiKey.length !== 64) { 83 | error.message = 'Invalid API Key'; 84 | error.status = 401; 85 | reject(error); 86 | } 87 | 88 | resolve(); 89 | }); 90 | 91 | const errorHandler = (error: AxiosError): PdlError => { 92 | const errorMessages = { 93 | 400: 'Request contained either missing or invalid parameters', 94 | 401: 'Request contained a missing or invalid key', 95 | 402: 'Payment Required, You have hit your account maximum (all matches used)', 96 | 404: 'No records were found matching your request', 97 | 405: 'Request method is not allowed on the requested resource', 98 | 429: 'An error occurred due to requests hitting the API too quick', 99 | 500: 'The server encountered an unexpected condition which prevented it from fulfilling the request', 100 | }; 101 | 102 | if (error.response) { 103 | const { status } = error.response; 104 | const statusCode = status >= 500 && status < 600 ? 500 : status; 105 | const { rateLimit } = parseRateLimitingResponse(error.response); 106 | 107 | return ({ 108 | status: statusCode, 109 | message: errorMessages[statusCode as keyof typeof errorMessages], 110 | rateLimit, 111 | }); 112 | } 113 | 114 | return ({ 115 | status: 500, 116 | message: errorMessages[500], 117 | }); 118 | }; 119 | 120 | export { check, errorHandler }; 121 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { autocomplete, bulkCompanyEnrichment, bulkEnrichment, bulkRetrieve, cleaner, enrichment, enrichmentPreview, identify, jobTitle, retrieve, search } from './endpoints/index.js'; 2 | import ip from './endpoints/ip/index.js'; 3 | import { APISettings } from './types/api-types.js'; 4 | import { AutoCompleteParams, AutoCompleteResponse } from './types/autocomplete-types.js'; 5 | import { BulkPersonRetrieveParams, BulkPersonRetrieveResponse } from './types/bulk-retrieve-types.js'; 6 | import { BulkCompanyEnrichmentParams, BulkCompanyEnrichmentResponse, BulkPersonEnrichmentParams, BulkPersonEnrichmentResponse } from './types/bulk-types.js'; 7 | import { CompanyCleanerParams, CompanyCleanerResponse, LocationCleanerParams, LocationCleanerResponse, SchoolCleanerParams, SchoolCleanerResponse } from './types/cleaner-types.js'; 8 | import { CompanyResponse, PersonResponse } from './types/common-types.js'; 9 | import { CompanyEnrichmentParams, CompanyEnrichmentResponse, PersonEnrichmentParams, PersonEnrichmentPreviewParams, PersonEnrichmentPreviewResponse, PersonEnrichmentResponse, PersonPreviewResponse } from './types/enrichment-types.js'; 10 | import { IdentifyParams, IdentifyResponse } from './types/identify-types.js'; 11 | import { IPParams, IPResponse } from './types/ip-types.js'; 12 | import { JobTitleParams, JobTitleResponse } from './types/jobTitle-types.js'; 13 | import { RetrieveParams, RetrieveResponse } from './types/retrieve-types.js'; 14 | import { CompanySearchParams, CompanySearchResponse, PersonSearchParams, PersonSearchResponse } from './types/search-types.js'; 15 | 16 | class PDLJS { 17 | private readonly apiKey: string; 18 | 19 | private readonly basePath: string; 20 | 21 | private readonly sandboxBasePath: string; 22 | 23 | public person: { 24 | bulk: { 25 | enrichment: (records: BulkPersonEnrichmentParams) => Promise; 26 | retrieve: (records: BulkPersonRetrieveParams) => Promise; 27 | }; 28 | enrichment: (params: PersonEnrichmentParams) => Promise; 29 | enrichmentPreview: (params: PersonEnrichmentPreviewParams) => Promise; 30 | identify: (params: IdentifyParams) => Promise; 31 | retrieve: (params: RetrieveParams) => Promise; 32 | search: { 33 | elastic: (params: PersonSearchParams) => Promise; 34 | sql: (params: PersonSearchParams) => Promise; 35 | }; 36 | }; 37 | 38 | public company: { 39 | bulk: { 40 | enrichment: (records: BulkCompanyEnrichmentParams) => Promise; 41 | }; 42 | cleaner: (params: CompanyCleanerParams) => Promise; 43 | enrichment: (params: CompanyEnrichmentParams) => Promise; 44 | search: { 45 | elastic: (params: CompanySearchParams) => Promise; 46 | sql: (params: CompanySearchParams) => Promise; 47 | }; 48 | }; 49 | 50 | public school: { cleaner: (params: SchoolCleanerParams) => Promise }; 51 | 52 | public location: { cleaner: (params: LocationCleanerParams) => Promise }; 53 | 54 | public autocomplete: (params: AutoCompleteParams) => Promise; 55 | 56 | public jobTitle: (params: JobTitleParams) => Promise; 57 | 58 | public ip: (params: IPParams) => Promise; 59 | 60 | constructor({ 61 | apiKey, 62 | basePath, 63 | sandboxBasePath, 64 | version, 65 | }: APISettings) { 66 | this.apiKey = apiKey; 67 | this.basePath = basePath || `https://api.peopledatalabs.com/${version || 'v5'}`; 68 | this.sandboxBasePath = sandboxBasePath || `https://sandbox.api.peopledatalabs.com/${version || 'v5'}`; 69 | 70 | this.person = { 71 | enrichment: (params) => enrichment(this.basePath, this.sandboxBasePath, this.apiKey, params, 'person'), 72 | enrichmentPreview: (params) => enrichmentPreview(this.basePath, this.sandboxBasePath, this.apiKey, params), 73 | search: { 74 | elastic: (params) => search(this.basePath, this.sandboxBasePath, this.apiKey, 'elastic', params, 'person'), 75 | sql: (params) => search(this.basePath, this.sandboxBasePath, this.apiKey, 'sql', params, 'person'), 76 | }, 77 | bulk: { 78 | enrichment: (records) => bulkEnrichment(this.basePath, this.apiKey, records), 79 | retrieve: (records) => bulkRetrieve(this.basePath, this.apiKey, records), 80 | }, 81 | identify: (params) => identify(this.basePath, this.sandboxBasePath, this.apiKey, params), 82 | retrieve: (params) => retrieve(this.basePath, this.apiKey, params), 83 | }; 84 | 85 | this.company = { 86 | enrichment: (params) => enrichment(this.basePath, this.sandboxBasePath, this.apiKey, params, 'company'), 87 | search: { 88 | elastic: (params) => search(this.basePath, this.sandboxBasePath, this.apiKey, 'elastic', params, 'company'), 89 | sql: (params) => search(this.basePath, this.sandboxBasePath, this.apiKey, 'sql', params, 'company'), 90 | }, 91 | bulk: { 92 | enrichment: (records) => bulkCompanyEnrichment(this.basePath, this.apiKey, records), 93 | }, 94 | cleaner: (params) => cleaner(this.basePath, this.apiKey, params, 'company'), 95 | }; 96 | 97 | this.school = { 98 | cleaner: (params) => cleaner(this.basePath, this.apiKey, params, 'school'), 99 | }; 100 | 101 | this.location = { 102 | cleaner: (params) => cleaner(this.basePath, this.apiKey, params, 'location'), 103 | }; 104 | 105 | this.autocomplete = (params: AutoCompleteParams) => autocomplete(this.basePath, this.apiKey, params); 106 | 107 | this.jobTitle = (params: JobTitleParams) => jobTitle(this.basePath, this.apiKey, params); 108 | 109 | this.ip = (params: IPParams) => ip(this.basePath, this.apiKey, params); 110 | } 111 | } 112 | 113 | export default PDLJS; 114 | 115 | export type { 116 | APISettings, 117 | AutoCompleteParams, 118 | AutoCompleteResponse, 119 | BulkCompanyEnrichmentParams, 120 | BulkCompanyEnrichmentResponse, 121 | BulkPersonEnrichmentParams, 122 | BulkPersonEnrichmentResponse, 123 | BulkPersonRetrieveParams, 124 | BulkPersonRetrieveResponse, 125 | CompanyCleanerParams, 126 | CompanyCleanerResponse, 127 | CompanyEnrichmentParams, 128 | CompanyEnrichmentResponse, 129 | CompanyResponse, 130 | CompanySearchParams, 131 | CompanySearchResponse, 132 | IdentifyParams, 133 | IdentifyResponse, 134 | IPParams, 135 | IPResponse, 136 | JobTitleParams, 137 | JobTitleResponse, 138 | LocationCleanerParams, 139 | LocationCleanerResponse, 140 | PersonEnrichmentParams, 141 | PersonEnrichmentPreviewParams, 142 | PersonEnrichmentPreviewResponse, 143 | PersonEnrichmentResponse, 144 | PersonPreviewResponse, 145 | PersonResponse, 146 | PersonSearchParams, 147 | PersonSearchResponse, 148 | RetrieveParams, 149 | RetrieveResponse, 150 | SchoolCleanerParams, 151 | SchoolCleanerResponse, 152 | }; 153 | -------------------------------------------------------------------------------- /src/types/api-types.ts: -------------------------------------------------------------------------------- 1 | export interface APISettings { 2 | apiKey: string; 3 | basePath?: string; 4 | sandboxBasePath?: string; 5 | version?: string; 6 | } 7 | 8 | export interface RateLimit { 9 | callCreditsSpent?: number | null; 10 | callCreditsType?: string | null; 11 | lifetimeUsed?: number | null; 12 | rateLimitLimit?: RateLimitLimit | null; 13 | rateLimitRemaining?: RateLimitRemaining | null; 14 | rateLimitReset?: string | null; 15 | totalLimitOveragesRemaining?: number | null; 16 | totalLimitPurchasedRemaining?: number | null; 17 | totalLimitRemaining?: number | null; 18 | } 19 | 20 | export interface BaseResponse { 21 | rateLimit: RateLimit; 22 | status: number; 23 | } 24 | 25 | export interface RateLimitRemaining { 26 | day?: number | null; 27 | minute?: number | null; 28 | month?: number | null; 29 | } 30 | 31 | export interface RateLimitLimit { 32 | day?: number | null; 33 | minute?: number | null; 34 | month?: number | null; 35 | } 36 | -------------------------------------------------------------------------------- /src/types/autocomplete-types.ts: -------------------------------------------------------------------------------- 1 | import { BaseResponse } from './api-types.js'; 2 | import { IndustryType, JobTitleRole } from './canonical-types.js'; 3 | 4 | export type AutoCompleteField = 'all_location' | 'class' | 'company' | 'country' | 'industry' | 'location' | 'location_name' | 'major' | 'region' | 'role' | 'school' | 'sub_role' | 'skill' | 'title' | 'website'; 5 | 6 | export interface AutoCompleteParams { 7 | field: AutoCompleteField; 8 | pretty?: boolean; 9 | size?: number; 10 | text?: string; 11 | titlecase?: boolean; 12 | } 13 | 14 | export interface AutoCompleteResponse extends BaseResponse { 15 | data?: Array<{ 16 | count: number | null; 17 | meta?: { 18 | alternative_names?: Array | null; 19 | country?: string | null; 20 | display_name?: string | null; 21 | display_name_history?: Array | null; 22 | fields?: Array | null; 23 | id?: string | null; 24 | industry?: IndustryType | null; 25 | locality?: string | null; 26 | location_name?: string | null; 27 | region?: string | null; 28 | role?: JobTitleRole | null; 29 | website?: string | null; 30 | } | null; 31 | name?: string | null; 32 | }>; 33 | fields?: Array | null; 34 | } 35 | -------------------------------------------------------------------------------- /src/types/bulk-retrieve-types.ts: -------------------------------------------------------------------------------- 1 | import { BaseResponse, RateLimit } from './api-types.js'; 2 | import { PersonResponse } from './common-types.js'; 3 | import { ApiRetrieveMetaParams, RetrieveMetaParams } from './retrieve-types.js'; 4 | 5 | export type BulkPersonRetrieveRequest = { 6 | id: string; 7 | metadata?: unknown; 8 | }; 9 | 10 | export interface BulkPersonRetrieveParams extends RetrieveMetaParams { 11 | requests: Array; 12 | } 13 | 14 | export interface ApiBulkPersonRetrieveParams extends ApiRetrieveMetaParams { 15 | requests: Array; 16 | } 17 | 18 | export interface BulkPersonRetrieveResponseItem extends BaseResponse { 19 | billed: boolean; 20 | data: PersonResponse; 21 | metadata?: unknown; 22 | } 23 | 24 | // This response does not extend from the BaseResponse since each item in the array has its own status 25 | // See https://docs.peopledatalabs.com/docs/bulk-requests 26 | export type BulkPersonRetrieveResponse = { 27 | items: Array; 28 | rateLimit: RateLimit; 29 | }; 30 | -------------------------------------------------------------------------------- /src/types/bulk-types.ts: -------------------------------------------------------------------------------- 1 | import { RateLimit } from './api-types.js'; 2 | import { CompanyEnrichmentParams, CompanyEnrichmentResponse, PersonEnrichmentParams, PersonEnrichmentResponse } from './enrichment-types.js'; 3 | 4 | export interface BulkPersonEnrichmentRequest { 5 | metadata?: unknown; 6 | params: PersonEnrichmentParams; // The user can define their own custom metadata 7 | } 8 | 9 | export interface BulkPersonEnrichmentParams { 10 | requests: Array & { 11 | include_if_matched?: boolean; 12 | pretty?: boolean; 13 | titlecase?: boolean; 14 | }; 15 | } 16 | 17 | export interface BulkPersonEnrichmentResponseItem extends PersonEnrichmentResponse { 18 | metadata?: unknown; 19 | } 20 | 21 | export type BulkPersonEnrichmentResponse = { 22 | items: Array; 23 | rateLimit: RateLimit; 24 | }; 25 | 26 | export interface BulkCompanyEnrichmentRequest { 27 | metadata?: unknown; 28 | params: CompanyEnrichmentParams; // The user can define their own custom metadata 29 | } 30 | 31 | export interface BulkCompanyEnrichmentParams { 32 | requests: Array & { 33 | include_if_matched?: boolean; 34 | pretty?: boolean; 35 | titlecase?: boolean; 36 | }; 37 | } 38 | 39 | export interface BulkCompanyEnrichmentResponseItem extends CompanyEnrichmentResponse { 40 | metadata?: unknown; 41 | } 42 | 43 | export type BulkCompanyEnrichmentResponse = { 44 | items: Array; 45 | rateLimit: RateLimit; 46 | }; 47 | -------------------------------------------------------------------------------- /src/types/canonical-types.ts: -------------------------------------------------------------------------------- 1 | export type EmailType = 'current_professional' | 'disposable' | 'personal' | 'professional'; 2 | 3 | export type CompanyType = 'educational' | 'government' | 'nonprofit' | 'private' | 'public' | 'public_subsidiary'; 4 | 5 | export type CompanySize = '1-10' | '11-50' | '51-200' | '201-500' | '501-1000' | '1001-5000' | '5001-10000' | '10001+'; 6 | 7 | export type Continent = 'africa' | 'antarctica' | 'asia' | 'europe' | 'north america' | 'oceania' | 'south america'; 8 | 9 | export type Currencies = 'aed' | 'afn' | 'all' | 'amd' | 'ang' | 'aoa' | 'ars' | 'aud' | 'awg' | 'azn' | 'bam' | 'bbd' | 'bdt' | 'bgn' | 'bhd' | 'bif' | 'bmd' | 'bnd' | 'bob' | 'brl' | 'bsd' | 'btn' | 'bwp' | 'byr' | 'bzd' | 'cad' | 'cdf' | 'cfa' | 'chf' | 'clp' | 'cny' | 'cop' | 'crc' | 'cup' | 'cve' | 'czk' | 'djf' | 'dkk' | 'dop' | 'dzd' | 'ecs' | 'egp' | 'ern' | 'etb' | 'eur' | 'fjd' | 'fkp' | 'gbp' | 'gel' | 'ghs' | 'gip' | 'gmd' | 'gnf' | 'gyd' | 'hkd' | 'hnl' | 'hrk' | 'htg' | 'huf' | 'idr' | 'ils' | 'inr' | 'iqd' | 'irr' | 'isk' | 'jmd' | 'jod' | 'jpy' | 'kes' | 'kgs' | 'khr' | 'kmf' | 'kpw' | 'krw' | 'kwd' | 'kyd' | 'kzt' | 'lak' | 'lbp' | 'lkr' | 'lrd' | 'lsl' | 'ltl' | 'lvl' | 'lyd' | 'mad' | 'mdl' | 'mgf' | 'mkd' | 'mmr' | 'mnt' | 'mop' | 'mro' | 'mur' | 'mvr' | 'mwk' | 'mxn' | 'myr' | 'mzn' | 'nad' | 'ngn' | 'nio' | 'nok' | 'npr' | 'nzd' | 'omr' | 'pab' | 'pen' | 'pgk' | 'php' | 'pkr' | 'pln' | 'pyg' | 'qar' | 'qtq' | 'ron' | 'rsd' | 'rub' | 'rwf' | 'sar' | 'sbd' | 'scr' | 'sdg' | 'sek' | 'sgd' | 'shp' | 'sll' | 'sos' | 'srd' | 'ssp' | 'std' | 'svc' | 'syp' | 'szl' | 'thb' | 'tjs' | 'tmt' | 'tnd' | 'top' | 'try' | 'ttd' | 'tzs' | 'uah' | 'ugx' | 'usd' | 'uyu' | 'uzs' | 'vef' | 'vnd' | 'vuv' | 'wst' | 'xaf' | 'xcd' | 'xof' | 'xpf' | 'yer' | 'zar' | 'zmw' | 'zwd'; 10 | 11 | export type FundingRoundType = 'angel' | 'convertible_note' | 'corporate_round' | 'debt_financing' | 'equity_crowdfunding' | 'funding_round' | 'grant' | 'initial_coin_offering' | 'non_equity_assistance' | 'post_ipo_debt' | 'post_ipo_equity' | 'post_ipo_secondary' | 'pre_seed' | 'private_equity' | 'product_crowdfunding' | 'secondary_market' | 'seed' | 'series_a' | 'series_b' | 'series_c' | 'series_d' | 'series_e' | 'series_f' | 'series_g' | 'series_h' | 'series_i' | 'series_j' | 'series_unknown' | 'undisclosed'; 12 | 13 | export type IndustryType = 'accounting' | 'airlines/aviation' | 'alternative dispute resolution' | 'alternative medicine' | 'animation' | 'apparel & fashion' | 'architecture & planning' | 'arts and crafts' | 'automotive' | 'aviation & aerospace' | 'banking' | 'biotechnology' | 'broadcast media' | 'building materials' | 'business supplies and equipment' | 'capital markets' | 'chemicals' | 'civic & social organization' | 'civil engineering' | 'commercial real estate' | 'computer & network security' | 'computer games' | 'computer hardware' | 'computer networking' | 'computer software' | 'construction' | 'consumer electronics' | 'consumer goods' | 'consumer services' | 'cosmetics' | 'dairy' | 'defense & space' | 'design' | 'e-learning' | 'education management' | 'electrical/electronic manufacturing' | 'entertainment' | 'environmental services' | 'events services' | 'executive office' | 'facilities services' | 'farming' | 'financial services' | 'fine art' | 'fishery' | 'food & beverages' | 'food production' | 'fund-raising' | 'furniture' | 'gambling & casinos' | 'glass, ceramics & concrete' | 'government administration' | 'government relations' | 'graphic design' | 'health, wellness and fitness' | 'higher education' | 'hospital & health care' | 'hospitality' | 'human resources' | 'import and export' | 'individual & family services' | 'industrial automation' | 'information services' | 'information technology and services' | 'insurance' | 'international affairs' | 'international trade and development' | 'internet' | 'investment banking' | 'investment management' | 'judiciary' | 'law enforcement' | 'law practice' | 'legal services' | 'legislative office' | 'leisure, travel & tourism' | 'libraries' | 'logistics and supply chain' | 'luxury goods & jewelry' | 'machinery' | 'management consulting' | 'maritime' | 'market research' | 'marketing and advertising' | 'mechanical or industrial engineering' | 'media production' | 'medical devices' | 'medical practice' | 'mental health' | 'military' | 'mining & metals' | 'motion pictures and film' | 'museums and institutions' | 'music' | 'nanotechnology' | 'newspapers' | 'non-profit organization management' | 'oil & energy' | 'online media' | 'outsourcing/offshoring' | 'package/freight delivery' | 'packaging and containers' | 'paper & forest products' | 'performing arts' | 'pharmaceuticals' | 'philanthropy' | 'photography' | 'plastics' | 'political organization' | 'primary/secondary education' | 'printing' | 'professional training & coaching' | 'program development' | 'public policy' | 'public relations and communications' | 'public safety' | 'publishing' | 'railroad manufacture' | 'ranching' | 'real estate' | 'recreational facilities and services' | 'religious institutions' | 'renewables & environment' | 'research' | 'restaurants' | 'retail' | 'security and investigations' | 'semiconductors' | 'shipbuilding' | 'sporting goods' | 'sports' | 'staffing and recruiting' | 'supermarkets' | 'telecommunications' | 'textiles' | 'think tanks' | 'tobacco' | 'translation and localization' | 'transportation/trucking/railroad' | 'utilities' | 'venture capital & private equity' | 'veterinary' | 'warehousing' | 'wholesale' | 'wine and spirits' | 'wireless' | 'writing and editing'; 14 | 15 | export type InferredRevenue = '$0-$1M' | '$1M-$10M' | '$10M-$25M' | '$25M-$50M' | '$50M-$100M' | '$100M-$250M' | '$250M-$500M' | '$500M-$1B' | '$1B-$10B' | '$10B+'; 16 | 17 | export type InferredSalary = '<20,000' | '20,000-25,000' | '25,000-35,000' | '35,000-45,000' | '45,000-55,000' | '55,000-70,000' | '70,000-85,000' | '85,000-100,000' | '100,000-150,000' | '150,000-250,000' | '> 250,000'; 18 | 19 | export type JobTitleClass = 'general_and_administrative' | 'research_and_development' | 'sales_and_marketing' | 'services' | 'unemployed'; 20 | 21 | export type JobTitleLevel = 'cxo' | 'director' | 'entry' | 'manager' | 'owner' | 'partner' | 'senior' | 'training' | 'unpaid' | 'vp'; 22 | 23 | export type JobTitleRole = 'advisory' | 'analyst' | 'creative' | 'education' | 'engineering' | 'finance' | 'fulfillment' | 'health' | 'hospitality' | 'human_resources' | 'legal' | 'manufacturing' | 'marketing' | 'operations' | 'partnerships' | 'product' | 'professional_service' | 'public_service' | 'research' | 'sales' | 'sales_engineering' | 'support' | 'trade' | 'unemployed'; 24 | 25 | export type JobTitleSubRole = 'academic' | 'account_executive' | 'account_management' | 'accounting' | 'accounting_services' | 'administrative' | 'advisor' | 'agriculture' | 'aides' | 'architecture' | 'artist' | 'board_member' | 'bookkeeping' | 'brand' | 'building_and_grounds' | 'business_analyst' | 'business_development' | 'chemical' | 'compliance' | 'construction' | 'consulting' | 'content' | 'corporate_development' | 'curation' | 'customer_success' | 'customer_support' | 'data_analyst' | 'data_engineering' | 'data_science' | 'dental' | 'devops' | 'doctor' | 'electric' | 'electrical' | 'emergency_services' | 'entertainment' | 'executive' | 'fashion' | 'financial' | 'fitness' | 'fraud' | 'graphic_design' | 'growth' | 'hair_stylist' | 'hardware' | 'health_and_safety' | 'human_resources' | 'implementation' | 'industrial' | 'information_technology' | 'insurance' | 'investment_banking' | 'investor' | 'investor_relations' | 'journalism' | 'judicial' | 'legal' | 'legal_services' | 'logistics' | 'machinist' | 'marketing_design' | 'marketing_services' | 'mechanic' | 'mechanical' | 'military' | 'network' | 'nursing' | 'partnerships' | 'pharmacy' | 'planning_and_analysis' | 'plumbing' | 'political' | 'primary_and_secondary' | 'procurement' | 'product_design' | 'product_management' | 'professor' | 'project_management' | 'protective_service' | 'qa_engineering' | 'quality_assurance' | 'realtor' | 'recruiting' | 'restaurants' | 'retail' | 'revenue_operations' | 'risk' | 'sales_development' | 'scientific' | 'security' | 'social_service' | 'software' | 'solutions_engineer' | 'strategy' | 'student' | 'talent_analytics' | 'therapy' | 'tour_and_travel' | 'training' | 'translation' | 'transport' | 'unemployed' | 'veterinarian' | 'warehouse' | 'web' | 'wellness'; 26 | 27 | export type LanguageName = 'afrikaans' | 'akan' | 'albanian' | 'amazigh' | 'american sign language' | 'amharic' | 'arabic' | 'aramaic' | 'armenian' | 'assamese' | 'aymara' | 'azerbaijani' | 'balochi' | 'bambara' | 'banda' | 'bashkort' | 'basque' | 'belarusian' | 'bemba' | 'bengali' | 'bhojpuri' | 'bislama' | 'bosnian' | 'brahui' | 'bulgarian' | 'burmese' | 'cantonese' | 'catalan' | 'cebuano' | 'chechen' | 'cherokee' | 'chewa' | 'croatian' | 'czech' | 'dakota' | 'danish' | 'dari' | 'dholuo' | 'dinka' | 'dutch' | 'english' | 'esperanto' | 'estonian' | 'ewe' | 'farsi' | 'filipino' | 'finnish' | 'fon' | 'french' | 'fula' | 'galician' | 'georgian' | 'german' | 'gikuyu' | 'greek' | 'guarani' | 'gujarati' | 'haitian creole' | 'hausa' | 'hawaiian' | 'hawaiian creole' | 'hebrew' | 'hiligaynon' | 'hindi' | 'hungarian' | 'icelandic' | 'igbo' | 'ilocano' | 'indonesian' | 'inuit/inupiaq' | 'irish gaelic' | 'italian' | 'japanese' | 'jarai' | 'javanese' | 'k\'iche\'' | 'kabyle' | 'kannada' | 'kashmiri' | 'kazakh' | 'khmer' | 'khoekhoe' | 'kinyarwanda' | 'kongo' | 'konkani' | 'korean' | 'kurdish' | 'kyrgyz' | 'lao' | 'latin' | 'latvian' | 'lingala' | 'lithuanian' | 'macedonian' | 'maithili' | 'malagasy' | 'malay' | 'malayalam' | 'mandarin' | 'mandinka' | 'marathi' | 'mende' | 'mongolian' | 'nahuatl' | 'navajo' | 'nepali' | 'norwegian' | 'ojibwa' | 'oriya' | 'oromo' | 'pashto' | 'persian' | 'polish' | 'portuguese' | 'punjabi' | 'quechua' | 'romani' | 'romanian' | 'russian' | 'samoan' | 'sanskrit' | 'serbian' | 'shona' | 'sindhi' | 'sinhala' | 'sinhalese' | 'slovak' | 'slovene' | 'slovenian' | 'somali' | 'songhay' | 'spanish' | 'swahili' | 'swazi' | 'swedish' | 'tachelhit' | 'tagalog' | 'taiwanese' | 'tajiki' | 'tamil' | 'tatar' | 'telugu' | 'thai' | 'tibetic languages' | 'tigrigna' | 'tok pisin' | 'tonga' | 'tsonga' | 'tswana' | 'tuareg' | 'turkish' | 'turkmen' | 'ukrainian' | 'urdu' | 'uyghur' | 'uzbek' | 'vietnamese' | 'warlpiri' | 'welsh' | 'wolof' | 'xhosa' | 'yakut' | 'yiddish' | 'yoruba' | 'yucatec' | 'zapotec' | 'zulu'; 28 | 29 | export type MICCode = 'alxl' | 'asex' | 'bvca' | 'misx' | 'notc' | 'pinx' | 'xams' | 'xase' | 'xasx' | 'xber' | 'xbkk' | 'xbom' | 'xbru' | 'xbsp' | 'xbud' | 'xbue' | 'xcai' | 'xcnq' | 'xcol' | 'xcse' | 'xdub' | 'xdus' | 'xetr' | 'xfka' | 'xfra' | 'xham' | 'xhan' | 'xhkg' | 'xidx' | 'xist' | 'xjse' | 'xkls' | 'xkos' | 'xkrx' | 'xlon' | 'xmce' | 'xmex' | 'xmil' | 'xmun' | 'xnas' | 'xngm' | 'xnms' | 'xnse' | 'xnys' | 'xnys' | 'xnze' | 'xosl' | 'xpar' | 'xpra' | 'xsap' | 'xsau' | 'xses' | 'xsgo' | 'xshe' | 'xshg' | 'xsto' | 'xstu' | 'xtae' | 'xtai' | 'xtse' | 'xwbo'; 30 | 31 | export type ProfileNetwork = 'aboutme' | 'angellist' | 'behance' | 'crunchbase' | 'dribbble' | 'ello' | 'facebook' | 'flickr' | 'foursquare' | 'github' | 'gitlab' | 'google' | 'gravatar' | 'indeed' | 'instagram' | 'klout' | 'linkedin' | 'medium' | 'meetup' | 'myspace' | 'pinterest' | 'quora' | 'reddit' | 'soundcloud' | 'stackoverflow' | 'twitter' | 'vimeo' | 'wordpress' | 'xing' | 'youtube'; 32 | -------------------------------------------------------------------------------- /src/types/cleaner-types.ts: -------------------------------------------------------------------------------- 1 | import { BaseResponse } from './api-types.js'; 2 | import { LocationResponse } from './common-types.js'; 3 | import { RequireAtLeastOne } from './utility-types.js'; 4 | 5 | export type CleanerType = 'company' | 'school' | 'location'; 6 | 7 | /* ---------------------------------------------------------- */ 8 | /* ------------------------- Company ------------------------ */ 9 | /* ---------------------------------------------------------- */ 10 | 11 | export type CompanyCleanerParams = RequireAtLeastOne<{ 12 | name: string; 13 | profile: string; 14 | website: string; 15 | }> & { 16 | pretty?: boolean; 17 | }; 18 | 19 | export interface CompanyCleanerResponse extends BaseResponse { 20 | facebook_url: string | null; 21 | founded?: number | null; 22 | fuzzy_match: boolean | null; 23 | id?: string | null; 24 | industry?: string | null; 25 | linkedin_id: string | null; 26 | linkedin_url: string | null; 27 | location?: Omit | null; 28 | name?: string | null; 29 | score?: number | null; 30 | size?: string | null; 31 | ticker?: string | null; 32 | twitter_url: string | null; 33 | type?: string | null; 34 | website: string | null; 35 | } 36 | 37 | /* ---------------------------------------------------------- */ 38 | /* ------------------------- School ------------------------- */ 39 | /* ---------------------------------------------------------- */ 40 | 41 | export type SchoolCleanerParams = RequireAtLeastOne<{ 42 | name: string; 43 | profile: string; 44 | website: string; 45 | }> & { 46 | pretty?: boolean; 47 | }; 48 | 49 | export interface SchoolCleanerResponse extends BaseResponse { 50 | domain?: string | null; 51 | facebook_url?: string | null; 52 | id?: string | null; 53 | linkedin_id?: string | null; 54 | linkedin_url?: string | null; 55 | location: { 56 | continent?: string | null; 57 | country?: string | null; 58 | locality?: string | null; 59 | name?: string | null; 60 | region?: string | null; 61 | } | null; 62 | name?: string | null; 63 | twitter_url?: string | null; 64 | type?: string | null; 65 | website?: string | null; 66 | } 67 | 68 | /* ---------------------------------------------------------- */ 69 | /* ------------------------ Location ------------------------ */ 70 | /* ---------------------------------------------------------- */ 71 | 72 | export interface LocationCleanerParams { 73 | location: string; 74 | pretty?: boolean; 75 | } 76 | 77 | export interface LocationCleanerResponse extends BaseResponse { 78 | continent?: string | null; 79 | country?: string | null; 80 | geo?: string | null; 81 | locality?: string | null; 82 | name?: string | null; 83 | region?: string | null; 84 | subregion?: string | null; 85 | type?: string | null; 86 | } 87 | -------------------------------------------------------------------------------- /src/types/common-types.ts: -------------------------------------------------------------------------------- 1 | import type { CompanySize, CompanyType, Continent, Currencies, EmailType, FundingRoundType, IndustryType, InferredRevenue, InferredSalary, JobTitleClass, JobTitleLevel, JobTitleRole, JobTitleSubRole, LanguageName, MICCode, ProfileNetwork } from './canonical-types.js'; 2 | 3 | export interface LocationResponse { 4 | address_line_2?: string | null; 5 | continent?: Continent | null; 6 | country?: string | null; 7 | geo?: string | null; 8 | locality?: string | null; 9 | metro?: string | null; 10 | name?: string | null; 11 | postal_code?: string | null; 12 | region?: string | null; 13 | street_address?: string | null; 14 | } 15 | 16 | export interface PersonEmailResponse { 17 | address?: string | null; 18 | first_seen?: string | null; 19 | last_seen?: string | null; 20 | num_sources?: number | null; 21 | type?: EmailType | null; 22 | } 23 | 24 | export interface PersonExperienceResponse { 25 | company?: { 26 | facebook_url?: string | null; 27 | founded?: number | null; 28 | fuzzy_match?: boolean | null; 29 | id?: string | null; 30 | industry?: IndustryType | null; 31 | linkedin_id?: string | null; 32 | linkedin_url?: string | null; 33 | location?: LocationResponse | null; 34 | name?: string | null; 35 | raw?: Array | null; 36 | size?: CompanySize | null; 37 | ticker?: string | null; 38 | twitter_url?: string | null; 39 | type?: CompanyType | null; 40 | website?: string | null; 41 | } | null; 42 | end_date?: string | null; 43 | first_seen?: string | null; 44 | is_primary?: boolean | null; 45 | last_seen?: string | null; 46 | location_names?: Array | null; 47 | num_sources?: number | null; 48 | start_date?: string | null; 49 | summary?: string | null; 50 | title?: { 51 | class?: JobTitleClass | null; 52 | levels?: Array | null; 53 | name?: string | null; 54 | raw?: Array | null; 55 | role?: JobTitleRole | null; 56 | sub_role?: JobTitleSubRole | null; 57 | } | null; 58 | } 59 | 60 | export interface PersonEducationResponse { 61 | degrees?: Array | null; 62 | end_date?: string | null; 63 | gpa?: number | null; 64 | majors?: Array | null; 65 | minors?: Array | null; 66 | raw?: Array | null; 67 | school?: { 68 | domain?: string | null; 69 | facebook_url?: string | null; 70 | id?: string | null; 71 | linkedin_id?: string | null; 72 | linkedin_url?: string | null; 73 | location?: LocationResponse | null; 74 | name?: string | null; 75 | raw?: Array | null; 76 | twitter_url?: string | null; 77 | type?: string | null; 78 | website?: string | null; 79 | } | null; 80 | start_date?: string | null; 81 | summary?: string | null; 82 | } 83 | 84 | export interface PersonProfileResponse { 85 | first_seen?: string | null; 86 | id?: string | null; 87 | last_seen?: string | null; 88 | network?: ProfileNetwork | null; 89 | num_sources?: number | null; 90 | url?: string | null; 91 | username?: string | null; 92 | } 93 | 94 | export interface PersonPhoneResponse { 95 | first_seen?: string | null; 96 | last_seen?: string | null; 97 | num_sources?: number | null; 98 | number?: string | null; 99 | } 100 | 101 | export interface PersonStreetAddressResponse { 102 | address_line_2?: string | null; 103 | continent?: Continent | null; 104 | country?: string | null; 105 | first_seen?: string | null; 106 | full_address?: string | null; 107 | geo?: string | null; 108 | last_seen?: string | null; 109 | locality?: string | null; 110 | metro?: string | null; 111 | name?: string | null; 112 | num_sources?: number | null; 113 | postal_code?: string | null; 114 | region?: string | null; 115 | street_address?: string | null; 116 | } 117 | 118 | export interface PersonCertificateResponse { 119 | end_date?: string | null; 120 | name?: string | null; 121 | organization?: string | null; 122 | start_date?: string | null; 123 | } 124 | 125 | export interface PersonBirthdateResponse { 126 | day?: string | null; 127 | month?: string | null; 128 | year?: string | null; 129 | } 130 | 131 | export interface PersonLanguageResponse { 132 | name?: LanguageName | null; 133 | proficiency?: number | null; 134 | } 135 | 136 | export interface PersonJobHistoryResponse { 137 | company_id?: string | null; 138 | company_name?: string | null; 139 | first_seen?: string | null; 140 | last_seen?: string | null; 141 | num_sources?: number | null; 142 | title?: string | null; 143 | } 144 | 145 | export interface VersionStatus { 146 | contains?: Array | null; 147 | current_version?: string | null; 148 | previous_version?: string | null; 149 | status?: string | null; 150 | } 151 | 152 | export interface PersonResponse { 153 | birth_date?: string | boolean | null; 154 | birth_year?: number | boolean | null; 155 | certifications?: Array | null; 156 | countries?: Array | null; 157 | dataset_version?: string | null; 158 | education?: Array | null; 159 | emails?: Array | boolean | null; 160 | experience?: Array | null; 161 | facebook_friends?: number | null; 162 | facebook_id?: string | null; 163 | facebook_url?: string | null; 164 | facebook_username?: string | null; 165 | first_name?: string | null; 166 | first_seen?: string | null; 167 | full_name?: string | null; 168 | github_url?: string | null; 169 | github_username?: string | null; 170 | headline?: string | null; 171 | id?: string | null; 172 | industry?: IndustryType | null; 173 | inferred_salary?: InferredSalary | null; 174 | inferred_years_experience?: number | null; 175 | interests?: Array | null; 176 | job_company_12mo_employee_growth_rate?: number | null; 177 | job_company_employee_count?: number | null; 178 | job_company_facebook_url?: string | null; 179 | job_company_founded?: number | null; 180 | job_company_id?: string | null; 181 | job_company_industry?: IndustryType | null; 182 | job_company_inferred_revenue?: InferredRevenue | null; 183 | job_company_linkedin_id?: string | null; 184 | job_company_linkedin_url?: string | null; 185 | job_company_location_address_line_2?: string | null; 186 | job_company_location_continent?: Continent | null; 187 | job_company_location_country?: string | null; 188 | job_company_location_geo?: string | null; 189 | job_company_location_locality?: string | null; 190 | job_company_location_metro?: string | null; 191 | job_company_location_name?: string | null; 192 | job_company_location_postal_code?: string | null; 193 | job_company_location_region?: string | null; 194 | job_company_location_street_address?: string | null; 195 | job_company_name?: string | null; 196 | job_company_size?: CompanySize | null; 197 | job_company_ticker?: string | null; 198 | job_company_total_funding_raised?: number | null; 199 | job_company_twitter_url?: string | null; 200 | job_company_type?: CompanyType | null; 201 | job_company_website?: string | null; 202 | job_history?: Array | null; 203 | job_last_changed?: string | null; 204 | job_last_verified?: string | null; 205 | job_onet_broad_occupation?: string | null; 206 | job_onet_code?: string | null; 207 | job_onet_major_group?: string | null; 208 | job_onet_minor_group?: string | null; 209 | job_onet_specific_occupation?: string | null; 210 | job_onet_specific_occupation_detail?: string | null; 211 | job_start_date?: string | null; 212 | job_summary?: string | null; 213 | job_title?: string | null; 214 | job_title_class?: JobTitleClass | null; 215 | job_title_levels?: Array | null; 216 | job_title_role?: JobTitleRole | null; 217 | job_title_sub_role?: JobTitleSubRole | null; 218 | languages?: Array | null; 219 | last_initial?: string | null; 220 | last_name?: string | null; 221 | linkedin_connections?: number | null; 222 | linkedin_id?: string | null; 223 | linkedin_url?: string | null; 224 | linkedin_username?: string | null; 225 | location_address_line_2?: string | boolean | null; 226 | location_continent?: Continent | null; 227 | location_country?: string | null; 228 | location_geo?: string | boolean | null; 229 | location_last_updated?: string | null; 230 | location_locality?: string | boolean | null; 231 | location_metro?: string | boolean | null; 232 | location_name?: string | boolean | null; 233 | location_names?: Array | boolean | null; 234 | location_postal_code?: string | boolean | null; 235 | location_region?: string | boolean | null; 236 | location_street_address?: string | boolean | null; 237 | middle_initial?: string | null; 238 | middle_name?: string | null; 239 | mobile_phone?: string | boolean | null; 240 | name_aliases?: Array | null; 241 | num_records?: number | null; 242 | num_sources?: number | null; 243 | personal_emails?: Array | boolean | null; 244 | phone_numbers?: Array | boolean | null; 245 | phones?: Array | null; 246 | possible_birth_dates?: Array | null; 247 | possible_emails?: Array | null; 248 | possible_location_names?: Array | null; 249 | possible_phones?: Array | null; 250 | possible_profiles?: Array | null; 251 | possible_street_addresses?: Array | null; 252 | profiles?: Array | null; 253 | recommended_personal_email?: string | boolean | null; 254 | regions?: Array | boolean | null; 255 | sex?: 'female' | 'male' | null; 256 | skills?: Array | null; 257 | street_addresses?: Array | boolean | null; 258 | summary?: string | null; 259 | twitter_url?: string | null; 260 | twitter_username?: string | null; 261 | version_status?: VersionStatus | null; 262 | work_email?: string | boolean | null; 263 | } 264 | 265 | interface NaicsResponse { 266 | industry_group?: string | null; 267 | naics_code?: string | null; 268 | naics_industry?: string | null; 269 | national_industry?: string | null; 270 | sector?: string | null; 271 | sub_sector?: string | null; 272 | } 273 | 274 | export interface SicResponse { 275 | industry_group?: string | null; 276 | industry_sector?: string | null; 277 | major_group?: string | null; 278 | sic_code?: string | null; 279 | } 280 | 281 | export interface CompanyResponse { 282 | affiliated_profiles?: Array | null; 283 | all_subsidiaries?: Array | null; 284 | alternative_domains?: Array | null; 285 | alternative_names?: Array | null; 286 | average_employee_tenure?: number | null; 287 | average_tenure_by_level?: { 288 | cxo?: number | null; 289 | director?: number | null; 290 | entry?: number | null; 291 | manager?: number | null; 292 | owner?: number | null; 293 | partner?: number | null; 294 | senior?: number | null; 295 | training?: number | null; 296 | unpaid?: number | null; 297 | vp?: number | null; 298 | } | null; 299 | average_tenure_by_role?: { 300 | advisory?: number | null; 301 | analyst?: number | null; 302 | creative?: number | null; 303 | education?: number | null; 304 | engineering?: number | null; 305 | finance?: number | null; 306 | fulfillment?: number | null; 307 | health?: number | null; 308 | hospitality?: number | null; 309 | human_resources?: number | null; 310 | legal?: number | null; 311 | manufacturing?: number | null; 312 | marketing?: number | null; 313 | operations?: number | null; 314 | partnerships?: number | null; 315 | product?: number | null; 316 | professional_service?: number | null; 317 | public_service?: number | null; 318 | research?: number | null; 319 | sales?: number | null; 320 | sales_engineering?: number | null; 321 | support?: number | null; 322 | trade?: number | null; 323 | unemployed?: number | null; 324 | } | null; 325 | dataset_version?: string | null; 326 | direct_subsidiaries?: Array | null; 327 | display_name?: string | null; 328 | employee_churn_rate: { 329 | '3_month'?: number | null; 330 | '6_month'?: number | null; 331 | '12_month'?: number | null; 332 | '24_month'?: number | null; 333 | } | null; 334 | employee_count?: number | null; 335 | employee_count_by_country?: object | null; 336 | employee_count_by_month?: object | null; 337 | employee_count_by_month_by_level?: object | null; 338 | employee_count_by_month_by_role?: object | null; 339 | employee_count_by_role?: { 340 | advisory?: number | null; 341 | analyst?: number | null; 342 | creative?: number | null; 343 | education?: number | null; 344 | engineering?: number | null; 345 | finance?: number | null; 346 | fulfillment?: number | null; 347 | health?: number | null; 348 | hospitality?: number | null; 349 | human_resources?: number | null; 350 | legal?: number | null; 351 | manufacturing?: number | null; 352 | marketing?: number | null; 353 | operations?: number | null; 354 | partnerships?: number | null; 355 | product?: number | null; 356 | professional_service?: number | null; 357 | public_service?: number | null; 358 | research?: number | null; 359 | sales?: number | null; 360 | sales_engineering?: number | null; 361 | support?: number | null; 362 | trade?: number | null; 363 | unemployed?: number | null; 364 | } | null; 365 | employee_growth_rate?: { 366 | '3_month'?: number | null; 367 | '6_month'?: number | null; 368 | '12_month'?: number | null; 369 | '24_month'?: number | null; 370 | } | null; 371 | employee_growth_rate_12_month_by_role?: { 372 | advisory?: number | null; 373 | analyst?: number | null; 374 | creative?: number | null; 375 | education?: number | null; 376 | engineering?: number | null; 377 | finance?: number | null; 378 | fulfillment?: number | null; 379 | health?: number | null; 380 | hospitality?: number | null; 381 | human_resources?: number | null; 382 | legal?: number | null; 383 | manufacturing?: number | null; 384 | marketing?: number | null; 385 | operations?: number | null; 386 | partnerships?: number | null; 387 | product?: number | null; 388 | professional_service?: number | null; 389 | public_service?: number | null; 390 | research?: number | null; 391 | sales?: number | null; 392 | sales_engineering?: number | null; 393 | support?: number | null; 394 | trade?: number | null; 395 | unemployed?: number | null; 396 | } | null; 397 | facebook_url?: string | null; 398 | founded?: number | null; 399 | funding_details?: Array<{ 400 | funding_currency?: Currencies | null; 401 | funding_raised?: number | null; 402 | funding_round_date?: string | null; 403 | funding_type?: FundingRoundType | null; 404 | investing_companies?: Array | null; 405 | investing_individuals?: Array | null; 406 | }> | null; 407 | funding_stages?: Array | null; 408 | gics_sector?: string | null; 409 | gross_additions_by_month?: object | null; 410 | gross_departures_by_month?: object | null; 411 | headline?: string | null; 412 | id?: string | null; 413 | immediate_parent?: string | null; 414 | industry?: IndustryType | null; 415 | inferred_revenue?: InferredRevenue | null; 416 | last_funding_date?: string | null; 417 | latest_funding_stage?: string | null; 418 | likelihood?: number | null; 419 | linkedin_employee_count?: number | null; 420 | linkedin_follower_count?: number | null; 421 | linkedin_id?: string | null; 422 | linkedin_slug?: string | null; 423 | linkedin_url?: string | null; 424 | location?: LocationResponse | null; 425 | matched?: Array | null; 426 | mic_exchange?: MICCode | null; 427 | naics?: Array | null; 428 | name?: string | null; 429 | number_funding_rounds?: number | null; 430 | profiles?: Array | null; 431 | recent_exec_departures?: Array<{ 432 | departed_date?: string | null; 433 | job_title?: string | null; 434 | job_title_class?: JobTitleClass | null; 435 | job_title_levels?: Array | null; 436 | job_title_role?: JobTitleRole | null; 437 | job_title_sub_role?: JobTitleSubRole | null; 438 | new_company_id?: string | null; 439 | new_company_job_title?: string | null; 440 | new_company_job_title_class?: JobTitleClass | null; 441 | new_company_job_title_levels?: Array | null; 442 | new_company_job_title_role?: JobTitleRole | null; 443 | new_company_job_title_sub_role?: JobTitleSubRole | null; 444 | pdl_id?: string | null; 445 | }> | null; 446 | recent_exec_hires?: Array<{ 447 | job_title?: string | null; 448 | job_title_class?: JobTitleClass | null; 449 | job_title_levels?: Array | null; 450 | job_title_role?: JobTitleRole | null; 451 | job_title_sub_role?: JobTitleSubRole | null; 452 | joined_date?: string | null; 453 | pdl_id?: string | null; 454 | previous_company_id?: string | null; 455 | previous_company_job_title?: string | null; 456 | previous_company_job_title_class?: JobTitleClass | null; 457 | previous_company_job_title_levels?: Array | null; 458 | previous_company_job_title_role?: JobTitleRole | null; 459 | previous_company_job_title_sub_role?: JobTitleSubRole | null; 460 | }> | null; 461 | sic?: Array | null; 462 | size?: CompanySize | null; 463 | summary?: string | null; 464 | tags?: Array | null; 465 | ticker?: string | null; 466 | top_next_employers_by_role?: { 467 | advisory?: number | null; 468 | all?: object | null; 469 | analyst?: number | null; 470 | creative?: number | null; 471 | education?: number | null; 472 | engineering?: number | null; 473 | finance?: number | null; 474 | fulfillment?: number | null; 475 | health?: number | null; 476 | hospitality?: number | null; 477 | human_resources?: number | null; 478 | legal?: number | null; 479 | manufacturing?: number | null; 480 | marketing?: number | null; 481 | operations?: number | null; 482 | partnerships?: number | null; 483 | product?: number | null; 484 | professional_service?: number | null; 485 | public_service?: number | null; 486 | research?: number | null; 487 | sales?: number | null; 488 | sales_engineering?: number | null; 489 | support?: number | null; 490 | trade?: number | null; 491 | unemployed?: number | null; 492 | } | null; 493 | top_previous_employers_by_role?: { 494 | advisory?: number | null; 495 | all?: object | null; 496 | analyst?: number | null; 497 | creative?: number | null; 498 | education?: number | null; 499 | engineering?: number | null; 500 | finance?: number | null; 501 | fulfillment?: number | null; 502 | health?: number | null; 503 | hospitality?: number | null; 504 | human_resources?: number | null; 505 | legal?: number | null; 506 | manufacturing?: number | null; 507 | marketing?: number | null; 508 | operations?: number | null; 509 | partnerships?: number | null; 510 | product?: number | null; 511 | professional_service?: number | null; 512 | public_service?: number | null; 513 | research?: number | null; 514 | sales?: number | null; 515 | sales_engineering?: number | null; 516 | support?: number | null; 517 | trade?: number | null; 518 | unemployed?: number | null; 519 | } | null; 520 | top_us_employee_metros: object | null; 521 | total_funding_raised?: number | null; 522 | twitter_url?: string | null; 523 | type?: CompanyType | null; 524 | ultimate_parent?: string | null; 525 | ultimate_parent_mic_exchange?: MICCode | null; 526 | ultimate_parent_ticker?: string | null; 527 | website?: string | null; 528 | } 529 | 530 | export interface ErrorResponse { 531 | message: string | null; 532 | status?: number | null; 533 | } 534 | -------------------------------------------------------------------------------- /src/types/enrichment-types.ts: -------------------------------------------------------------------------------- 1 | import { BaseResponse } from './api-types.js'; 2 | import { CompanyResponse, PersonResponse } from './common-types.js'; 3 | import { RequireAtLeastOne } from './utility-types.js'; 4 | 5 | export type EnrichmentType = 'company' | 'person'; 6 | 7 | export interface EnrichmentAdditionalParams { 8 | include_if_matched?: boolean; 9 | min_likelihood?: number; 10 | pretty?: boolean; 11 | required?: string; 12 | sandbox?: boolean; 13 | size?: number; 14 | titlecase?: boolean; 15 | } 16 | 17 | /* ---------------------------------------------------------- */ 18 | /* ------------------------- Person ------------------------- */ 19 | /* ---------------------------------------------------------- */ 20 | 21 | export type PersonEnrichmentParams = EnrichmentAdditionalParams & Partial<{ 22 | birth_date: Array | string; 23 | company: Array | string; 24 | country: string; 25 | data_include: string; 26 | email: Array | string; 27 | email_hash: Array | string; 28 | first_name: Array | string; 29 | last_name: Array | string; 30 | lid: number; 31 | locality: string; 32 | location: Array | string; 33 | middle_name: Array | string; 34 | name: Array | string; 35 | pdl_id: string; 36 | phone: Array | string; 37 | postal_code: string; 38 | profile: Array | string; 39 | region: string; 40 | school: Array | string; 41 | street_address: string; 42 | }>; 43 | 44 | export interface PersonEnrichmentResponse extends BaseResponse { 45 | data: PersonResponse; 46 | likelihood: number; 47 | matched?: Array; 48 | } 49 | 50 | export type PersonEnrichmentPreviewParams = PersonEnrichmentParams; 51 | 52 | type PersonPreviewResponseVisibleKeys = 'id' | 'full_name' | 'sex' | 'linkedin_url' | 'industry' | 'job_title' | 'job_title_class' | 'job_title_role' | 'job_title_sub_role' | 'job_title_levels' | 'job_company_name' | 'job_company_website' | 'location_name'; 53 | 54 | type PersonPreviewResponseType = { 55 | [K in keyof PersonResponse]: K extends PersonPreviewResponseVisibleKeys ? PersonResponse[K] : boolean; 56 | }; 57 | 58 | export interface PersonPreviewResponse extends PersonPreviewResponseType {} 59 | 60 | export interface PersonEnrichmentPreviewResponse extends BaseResponse { 61 | data: PersonPreviewResponse; 62 | likelihood: number; 63 | matched?: Array; 64 | } 65 | 66 | /* ---------------------------------------------------------- */ 67 | /* ------------------------- Company ------------------------ */ 68 | /* ---------------------------------------------------------- */ 69 | 70 | export interface CompanyEnrichmentRequiredParams { 71 | name: string; 72 | pdl_id: string; 73 | profile: string; 74 | ticker: string; 75 | website: string; 76 | } 77 | 78 | // eslint-disable-next-line max-len 79 | export type CompanyEnrichmentParams = RequireAtLeastOne & EnrichmentAdditionalParams & { 80 | country?: string; 81 | locality?: string; 82 | location?: string; 83 | postal_code?: string; 84 | region?: string; 85 | street_address?: string; 86 | }; 87 | 88 | export interface CompanyEnrichmentResponse extends BaseResponse, CompanyResponse {} 89 | -------------------------------------------------------------------------------- /src/types/error-types.ts: -------------------------------------------------------------------------------- 1 | import { RateLimit } from './api-types.js'; 2 | 3 | export type ErrorEndpoint = 'enrichment' | 'autocomplete' | 'search' | 'identify' | 'bulk' | 'cleaner' | 'retrieve' | 'jobTitle' | 'ip'; 4 | 5 | export type PdlError = { 6 | message: string; 7 | rateLimit?: RateLimit; 8 | status: number; 9 | }; 10 | -------------------------------------------------------------------------------- /src/types/identify-types.ts: -------------------------------------------------------------------------------- 1 | import { BaseResponse } from './api-types.js'; 2 | import { PersonResponse } from './common-types.js'; 3 | import { RequireAtLeastOne } from './utility-types.js'; 4 | 5 | export type IdentifyRequiredParams = RequireAtLeastOne<{ 6 | company: string; 7 | email: string; 8 | email_hash: string; 9 | first_name: string; 10 | last_name: string; 11 | lid: number; 12 | locality: string; 13 | location: string; 14 | name: string; 15 | phone: string; 16 | postal_code: string; 17 | profile: string; 18 | region: string; 19 | school: string; 20 | street_address: string; 21 | }>; 22 | 23 | export type IdentifyParams = IdentifyRequiredParams & Partial<{ 24 | birth_date: string; 25 | country: string; 26 | data_include: string; 27 | include_if_matched: boolean; 28 | middle_name: string; 29 | pretty: boolean; 30 | required: string; 31 | sandbox: boolean; 32 | titlecase: boolean; 33 | }>; 34 | 35 | export interface IdentifyResponse extends BaseResponse { 36 | matches: Array<{ 37 | data: PersonResponse; 38 | match_score: number; 39 | matched_on: Array; 40 | }>; 41 | } 42 | -------------------------------------------------------------------------------- /src/types/ip-types.ts: -------------------------------------------------------------------------------- 1 | import { BaseResponse } from './api-types.js'; 2 | import type { CompanySize, IndustryType, InferredRevenue, JobTitleClass, JobTitleLevel, JobTitleRole, JobTitleSubRole } from './canonical-types.js'; 3 | 4 | export interface IPParams { 5 | ip: string; 6 | min_confidence?: 'very high' | 'high' | 'moderate' | 'low' | 'very low'; 7 | pretty?: boolean; 8 | return_if_unmatched?: boolean; 9 | return_ip_location?: boolean; 10 | return_ip_metadata?: boolean; 11 | return_person?: boolean; 12 | titlecase?: boolean; 13 | } 14 | 15 | export interface IPResponse extends BaseResponse { 16 | data?: { 17 | company?: { 18 | confidence?: 'very high' | 'high' | 'moderate' | 'low' | 'very low'; 19 | display_name?: string | null; 20 | employee_count?: number | null; 21 | id?: string | null; 22 | industry?: IndustryType | null; 23 | inferred_revenue?: InferredRevenue | null; 24 | location?: { 25 | address_line_2?: string | null; 26 | continent?: string | null; 27 | country?: string | null; 28 | geo?: string | null; 29 | locality?: string | null; 30 | metro?: string | null; 31 | name?: string | null; 32 | postal_code?: string | null; 33 | region?: string | null; 34 | street_address?: string; 35 | } | null; 36 | name?: string | null; 37 | size?: CompanySize | null; 38 | tags?: Array | null; 39 | website?: string | null; 40 | } | null; 41 | dataset_version?: string | null; 42 | ip?: { 43 | address?: string | null; 44 | location?: { 45 | continent?: string | null; 46 | country?: string | null; 47 | geo?: string | null; 48 | locality?: string | null; 49 | metro?: string | null; 50 | name?: string | null; 51 | postal_code?: string | null; 52 | region?: string | null; 53 | timezone?: string | null; 54 | } | null; 55 | metadata?: { 56 | asn_domain?: string | null; 57 | hosting?: boolean | null; 58 | mobile?: boolean | null; 59 | proxy?: boolean | null; 60 | relay?: boolean | null; 61 | service?: string | null; 62 | tor?: boolean | null; 63 | version?: 4 | 6 | null; 64 | vpn?: boolean | null; 65 | }; 66 | } | null; 67 | person?: { 68 | confidence?: 'very high' | 'high' | 'moderate' | 'low' | 'very low'; 69 | job_title_class?: JobTitleClass | null; 70 | job_title_levels?: Array | null; 71 | job_title_role?: JobTitleRole | null; 72 | job_title_sub_role?: JobTitleSubRole | null; 73 | } | null; 74 | } | null; 75 | } 76 | -------------------------------------------------------------------------------- /src/types/jobTitle-types.ts: -------------------------------------------------------------------------------- 1 | import { BaseResponse } from './api-types.js'; 2 | 3 | export interface JobTitleParams { 4 | jobTitle: string; 5 | pretty?: boolean; 6 | titlecase?: boolean; 7 | } 8 | 9 | export interface JobTitleResponse extends BaseResponse { 10 | data?: { 11 | cleaned_job_title?: string | null; 12 | relevant_skills?: Array | null; 13 | similar_job_titles?: Array | null; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /src/types/retrieve-types.ts: -------------------------------------------------------------------------------- 1 | import { BaseResponse } from './api-types.js'; 2 | import { PersonResponse } from './common-types.js'; 3 | 4 | export type RetrieveFilter = 'job_change' | 'education' | 'location' | 'personal_emails' | 'phone_number' | 'social_profile' | 'work_email'; 5 | 6 | export type RetrieveMetaParams = { 7 | filter_updated?: RetrieveFilter | RetrieveFilter[]; 8 | pretty?: boolean; 9 | titlecase?: boolean; 10 | }; 11 | 12 | export type ApiRetrieveMetaParams = { 13 | filter_updated?: string; 14 | pretty?: boolean; 15 | titlecase?: boolean; 16 | }; 17 | 18 | export type RetrieveParams = { 19 | id: string; 20 | } & RetrieveMetaParams; 21 | 22 | export type ApiRetrieveParams = { 23 | id: string; 24 | } & ApiRetrieveMetaParams; 25 | 26 | export interface RetrieveResponse extends BaseResponse { 27 | billed: boolean; 28 | data: PersonResponse; 29 | } 30 | -------------------------------------------------------------------------------- /src/types/search-types.ts: -------------------------------------------------------------------------------- 1 | import { BaseResponse } from './api-types.js'; 2 | import { CompanyResponse, PersonResponse } from './common-types.js'; 3 | 4 | export interface BaseSearchParams { 5 | data_include?: string; 6 | dataset?: string; 7 | from?: number; 8 | pretty?: boolean; 9 | sandbox?: boolean; 10 | scroll_token?: string; 11 | searchQuery?: string | object; 12 | size?: number; 13 | titlecase?: boolean; 14 | } 15 | 16 | export interface BaseSearchResponse extends BaseResponse { 17 | data: Array; 18 | scroll_token: string; 19 | total: number; 20 | } 21 | 22 | export type SearchType = 'sql' | 'elastic'; 23 | 24 | /* ---------------------------------------------------------- */ 25 | /* ------------------------- Person ------------------------- */ 26 | /* ---------------------------------------------------------- */ 27 | 28 | export interface PersonSearchParams extends BaseSearchParams { 29 | } 30 | 31 | export interface PersonSearchResponse extends BaseSearchResponse {} 32 | 33 | /* ---------------------------------------------------------- */ 34 | /* ------------------------- Company ------------------------ */ 35 | /* ---------------------------------------------------------- */ 36 | 37 | export interface CompanySearchParams extends BaseSearchParams {} 38 | 39 | export interface CompanySearchResponse extends BaseSearchResponse {} 40 | -------------------------------------------------------------------------------- /src/types/utility-types.ts: -------------------------------------------------------------------------------- 1 | // Marks all the properties of a type as optional except for one 2 | // See https://docs.microsoft.com/en-us/javascript/api/@azure/keyvault-certificates/requireatleastone?view=azure-node-latest 3 | export type RequireAtLeastOne = { 4 | [K in keyof T]-?: Required> & Partial>>; 5 | }[keyof T]; 6 | -------------------------------------------------------------------------------- /src/utils/api-utils.ts: -------------------------------------------------------------------------------- 1 | import { AxiosResponse } from 'axios'; 2 | 3 | import { RateLimit } from '../types/api-types.js'; 4 | 5 | // eslint-disable-next-line import/prefer-default-export 6 | export const parseRateLimitingResponse = (response: AxiosResponse) => { 7 | const rateLimit = { 8 | rateLimitRemaining: response.headers['x-ratelimit-remaining'] ? JSON.parse(response.headers['x-ratelimit-remaining'].replace(/'/g, '"')) : undefined, 9 | rateLimitReset: response.headers['x-ratelimit-reset'] || undefined, 10 | rateLimitLimit: response.headers['x-ratelimit-limit'] ? JSON.parse(response.headers['x-ratelimit-limit'].replace(/'/g, '"')) : undefined, 11 | totalLimitOveragesRemaining: response.headers['x-totallimit-overages-remaining'] ? Number(response.headers['x-totallimit-overages-remaining']) : undefined, 12 | totalLimitPurchasedRemaining: response.headers['x-totallimit-purchased-remaining'] ? Number(response.headers['x-totallimit-purchased-remaining']) : undefined, 13 | totalLimitRemaining: response.headers['x-totallimit-remaining'] ? Number(response.headers['x-totallimit-remaining']) : undefined, 14 | callCreditsType: response.headers['x-call-credits-type'] || undefined, 15 | callCreditsSpent: response.headers['x-call-credits-spent'] ? Number(response.headers['x-call-credits-spent']) : undefined, 16 | lifetimeUsed: response.headers['x-lifetime-used'] ? Number(response.headers['x-lifetime-used']) : undefined, 17 | } as RateLimit; 18 | 19 | if (Array.isArray(response.data)) { 20 | return { 21 | items: response.data, 22 | rateLimit, 23 | }; 24 | } 25 | 26 | return { 27 | ...response.data, 28 | rateLimit, 29 | }; 30 | }; 31 | -------------------------------------------------------------------------------- /tests/index.test.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 3 | import { expect } from 'chai'; 4 | import dotenv from 'dotenv'; 5 | 6 | // eslint-disable-next-line import/extensions 7 | import PDLJS from '../dist/index.m.js'; 8 | 9 | dotenv.config({ path: './.env.local' }); 10 | 11 | const PDLJSClient = new PDLJS({ apiKey: process.env.PDL_API_KEY }); 12 | 13 | const email = 'varun@peopledatalabs.com'; 14 | 15 | const records = { 16 | requests: [ 17 | { 18 | params: { 19 | profile: ['linkedin.com/in/seanthorne'], 20 | }, 21 | }, 22 | { 23 | params: { 24 | profile: ['linkedin.com/in/randrewn'], 25 | }, 26 | }, 27 | ], 28 | }; 29 | 30 | const personSQL = "SELECT * FROM person WHERE location_country='mexico' AND job_title_role='health'AND phone_numbers IS NOT NULL;"; 31 | 32 | const personElastic = { 33 | query: { 34 | bool: { 35 | must: [ 36 | { term: { location_country: 'mexico' } }, 37 | { term: { job_title_role: 'health' } }, 38 | { exists: { field: 'phone_numbers' } }, 39 | ], 40 | }, 41 | }, 42 | }; 43 | 44 | const personID = 'qEnOZ5Oh0poWnQ1luFBfVw_0000'; 45 | 46 | const bulkRecords = { 47 | requests: [ 48 | { id: 'qEnOZ5Oh0poWnQ1luFBfVw_0000' }, 49 | { id: 'PzFD15NINdBWNULBBkwlig_0000' }, 50 | ], 51 | }; 52 | 53 | const website = 'peopledatalabs.com'; 54 | 55 | const companySQL = "SELECT * FROM company WHERE tags='big data' AND industry='financial services' AND location.country='united states';"; 56 | 57 | const companyElastic = { 58 | query: { 59 | bool: { 60 | must: [ 61 | { term: { website: 'peopledatalabs.com' } }, 62 | ], 63 | }, 64 | }, 65 | }; 66 | 67 | const autocomplete = { 68 | field: 'company', 69 | text: 'facebook', 70 | size: 10, 71 | }; 72 | 73 | const company = { name: 'peopledatalabs' }; 74 | 75 | const companyRecords = { 76 | requests: [ 77 | { 78 | params: { 79 | profile: ['linkedin.com/company/peopledatalabs'], 80 | }, 81 | }, 82 | { 83 | params: { 84 | profile: ['linkedin.com/company/apple'], 85 | }, 86 | }, 87 | ], 88 | }; 89 | 90 | const location = { location: '455 Market Street, San Francisco, California 94105, US' }; 91 | 92 | const school = { name: 'university of oregon' }; 93 | 94 | const jobTitle = { jobTitle: 'software engineer' }; 95 | 96 | const ip = { ip: '72.212.42.228' }; 97 | 98 | describe('Person Enrichment', () => { 99 | it(`Should Return Person Record for ${email}`, async () => { 100 | try { 101 | const response = await PDLJSClient.person.enrichment({ email }); 102 | 103 | expect(response.status).to.equal(200); 104 | expect(response).to.be.a('object'); 105 | expect(response.data.job_title_class).to.be.a('string'); 106 | } catch (error) { 107 | expect(error).to.be.null(); 108 | } 109 | }); 110 | 111 | it('Should Error for Person Enrichment', async () => { 112 | try { 113 | const response = await PDLJSClient.person.enrichment(); 114 | 115 | expect(response).to.be.null(); 116 | } catch (error) { 117 | expect(error).to.be.a('object'); 118 | } 119 | }); 120 | }); 121 | 122 | describe('Person Preview Enrichment', () => { 123 | it(`Should Return Person Preview Record for ${email}`, async () => { 124 | try { 125 | const response = await PDLJSClient.person.enrichmentPreview({ email }); 126 | 127 | expect(response.status).to.equal(200); 128 | expect(response).to.be.a('object'); 129 | } catch (error) { 130 | expect(error).to.be.null(); 131 | } 132 | }); 133 | 134 | it('Should Error for Person Preview Enrichment', async () => { 135 | try { 136 | const response = await PDLJSClient.person.enrichmentPreview(); 137 | 138 | expect(response).to.be.null(); 139 | } catch (error) { 140 | expect(error).to.be.a('object'); 141 | } 142 | }); 143 | }); 144 | 145 | describe('Person Bulk Enrichment', () => { 146 | it(`Should Return Person Records for ${JSON.stringify(records)}`, async () => { 147 | try { 148 | const response = await PDLJSClient.person.bulk.enrichment(records); 149 | 150 | expect(response.items.length).to.equal(2); 151 | expect(response.items).to.be.a('array'); 152 | } catch (error) { 153 | expect(error).to.be.null(); 154 | } 155 | }); 156 | 157 | it('Should Error for Person Bulk Enrichment', async () => { 158 | try { 159 | const response = await PDLJSClient.person.bulk.enrichment(); 160 | 161 | expect(response).to.be.null(); 162 | } catch (error) { 163 | expect(error).to.be.a('object'); 164 | } 165 | }); 166 | }); 167 | 168 | describe('Person Identify', () => { 169 | it(`Should Return Person Record for ${email}`, async () => { 170 | try { 171 | const response = await PDLJSClient.person.identify({ email }); 172 | 173 | expect(response.status).to.equal(200); 174 | expect(response).to.be.a('object'); 175 | } catch (error) { 176 | expect(error).to.be.null(); 177 | } 178 | }); 179 | 180 | it('Should Error for Person Identify', async () => { 181 | try { 182 | const response = await PDLJSClient.person.identify(); 183 | 184 | expect(response).to.be.null(); 185 | } catch (error) { 186 | expect(error).to.be.a('object'); 187 | } 188 | }); 189 | }); 190 | 191 | describe('Person Search', () => { 192 | it(`Should Return Person Records for ${personSQL}`, async () => { 193 | try { 194 | const response = await PDLJSClient.person.search.sql({ searchQuery: personSQL, size: 10 }); 195 | 196 | expect(response.status).to.equal(200); 197 | expect(response).to.be.a('object'); 198 | } catch (error) { 199 | expect(error).to.be.null(); 200 | } 201 | }); 202 | 203 | it('Should Error for Person Search (sql)', async () => { 204 | try { 205 | const response = await PDLJSClient.person.search.sql(); 206 | 207 | expect(response).to.be.null(); 208 | } catch (error) { 209 | expect(error).to.be.a('object'); 210 | } 211 | }); 212 | 213 | it(`Should Return Person Records for ${JSON.stringify(personElastic)}`, async () => { 214 | try { 215 | const response = await PDLJSClient.person.search.elastic({ searchQuery: personElastic, size: 10 }); 216 | 217 | expect(response.status).to.equal(200); 218 | expect(response).to.be.a('object'); 219 | } catch (error) { 220 | expect(error).to.be.null(); 221 | } 222 | }); 223 | 224 | it('Should Error for Person Search (elastic)', async () => { 225 | try { 226 | const response = await PDLJSClient.person.search.elastic(); 227 | 228 | expect(response).to.be.null(); 229 | } catch (error) { 230 | expect(error).to.be.a('object'); 231 | } 232 | }); 233 | }); 234 | 235 | describe('Person Retrieve', () => { 236 | it(`Should Return Person Record for ${personID}`, async () => { 237 | try { 238 | const response = await PDLJSClient.person.retrieve({ id: personID }); 239 | 240 | expect(response.status).to.equal(200); 241 | expect(response).to.be.a('object'); 242 | } catch (error) { 243 | expect(error).to.be.null(); 244 | } 245 | }); 246 | 247 | it('Should Error for Person Retrieve', async () => { 248 | try { 249 | const response = await PDLJSClient.person.retrieve(); 250 | 251 | expect(response).to.be.null(); 252 | } catch (error) { 253 | expect(error).to.be.a('object'); 254 | } 255 | }); 256 | }); 257 | 258 | describe('Bulk Person Retrieve', () => { 259 | it(`Should Return Person Records for ${JSON.stringify(bulkRecords)}`, async () => { 260 | try { 261 | const response = await PDLJSClient.person.bulk.retrieve(bulkRecords); 262 | 263 | expect(response).to.be.a('object'); 264 | } catch (error) { 265 | expect(error).to.be.null(); 266 | } 267 | }); 268 | 269 | it('Should Error for Bulk Person Retrieve', async () => { 270 | try { 271 | const response = await PDLJSClient.person.bulk.retrieve(); 272 | 273 | expect(response).to.be.null(); 274 | } catch (error) { 275 | expect(error).to.be.a('object'); 276 | } 277 | }); 278 | }); 279 | 280 | describe('Company Enrichment', () => { 281 | it(`Should Return Company Record for ${website}`, async () => { 282 | try { 283 | const response = await PDLJSClient.company.enrichment({ website }); 284 | 285 | expect(response.status).to.equal(200); 286 | expect(response).to.be.a('object'); 287 | } catch (error) { 288 | expect(error).to.be.null(); 289 | } 290 | }); 291 | 292 | it('Should Return Multiple Company Records for MRI', async () => { 293 | try { 294 | const response = await PDLJSClient.company.enrichment({ name: 'MRI', size: 2 }); 295 | 296 | expect(response.status).to.equal(200); 297 | expect(response).to.be.a('object'); 298 | } catch (error) { 299 | expect(error).to.be.null(); 300 | } 301 | }); 302 | 303 | it('Should Error for Company Enrichment', async () => { 304 | try { 305 | const response = await PDLJSClient.company.enrichment(); 306 | 307 | expect(response).to.be.null(); 308 | } catch (error) { 309 | expect(error).to.be.a('object'); 310 | } 311 | }); 312 | }); 313 | 314 | describe('Company Bulk Enrichment', () => { 315 | it(`Should Return Company Records for ${JSON.stringify(companyRecords)}`, async () => { 316 | try { 317 | const response = await PDLJSClient.company.bulk.enrichment(companyRecords); 318 | 319 | expect(response.items.length).to.equal(2); 320 | expect(response.items).to.be.a('array'); 321 | } catch (error) { 322 | expect(error).to.be.null(); 323 | } 324 | }); 325 | 326 | it('Should Error for Company Bulk Enrichment', async () => { 327 | try { 328 | const response = await PDLJSClient.company.bulk.enrichment(); 329 | 330 | expect(response).to.be.null(); 331 | } catch (error) { 332 | expect(error).to.be.a('object'); 333 | } 334 | }); 335 | }); 336 | 337 | describe('Company Search', () => { 338 | it(`Should Return Company Records for ${companySQL}`, async () => { 339 | try { 340 | const response = await PDLJSClient.company.search.sql({ searchQuery: companySQL, size: 10 }); 341 | 342 | expect(response.status).to.equal(200); 343 | expect(response).to.be.a('object'); 344 | } catch (error) { 345 | expect(error).to.be.null(); 346 | } 347 | }); 348 | 349 | it('Should Error for Company Search (sql)', async () => { 350 | try { 351 | const response = await PDLJSClient.company.search.sql(); 352 | 353 | expect(response).to.be.null(); 354 | } catch (error) { 355 | expect(error).to.be.a('object'); 356 | } 357 | }); 358 | 359 | it(`Should Return Company Records for ${JSON.stringify(companyElastic)}`, async () => { 360 | try { 361 | const response = await PDLJSClient.company.search.elastic({ searchQuery: companyElastic, size: 10 }); 362 | 363 | expect(response.status).to.equal(200); 364 | expect(response).to.be.a('object'); 365 | } catch (error) { 366 | expect(error).to.be.null(); 367 | } 368 | }); 369 | 370 | it('Should Error for Company Search (elastic)', async () => { 371 | try { 372 | const response = await PDLJSClient.company.search.elastic(); 373 | 374 | expect(response).to.be.null(); 375 | } catch (error) { 376 | expect(error).to.be.a('object'); 377 | } 378 | }); 379 | }); 380 | 381 | describe('Autocomplete', () => { 382 | it(`Should Return Autocomplete Records for ${JSON.stringify(autocomplete)}`, async () => { 383 | try { 384 | const response = await PDLJSClient.autocomplete(autocomplete); 385 | 386 | expect(response.status).to.equal(200); 387 | expect(response).to.be.a('object'); 388 | } catch (error) { 389 | expect(error).to.be.null(); 390 | } 391 | }); 392 | 393 | it('Should Return Autocomplete for `class` field', async () => { 394 | const autocompleteClassParams = { 395 | field: 'class', 396 | text: 'sales', 397 | }; 398 | 399 | try { 400 | const response = await PDLJSClient.autocomplete(autocompleteClassParams); 401 | 402 | expect(response.status).to.equal(200); 403 | expect(response).to.be.a('object'); 404 | } catch (error) { 405 | expect(error).to.be.null(); 406 | } 407 | }); 408 | 409 | it('Should Return Autocomplete for `all_location` field', async () => { 410 | const autocompleteClassParams = { 411 | field: 'all_location', 412 | text: 'miami', 413 | }; 414 | 415 | try { 416 | const response = await PDLJSClient.autocomplete(autocompleteClassParams); 417 | 418 | expect(response.status).to.equal(200); 419 | expect(response).to.be.a('object'); 420 | } catch (error) { 421 | expect(error).to.be.null(); 422 | } 423 | }); 424 | 425 | it('Should Error for Autocomplete', async () => { 426 | try { 427 | const response = await PDLJSClient.autocomplete(); 428 | 429 | expect(response).to.be.null(); 430 | } catch (error) { 431 | expect(error).to.be.a('object'); 432 | } 433 | }); 434 | }); 435 | 436 | describe('Cleaner APIs', () => { 437 | it(`Should Return Company Cleaner Records for ${JSON.stringify(company)}`, async () => { 438 | try { 439 | const response = await PDLJSClient.company.cleaner(company); 440 | 441 | expect(response.status).to.equal(200); 442 | expect(response).to.be.a('object'); 443 | } catch (error) { 444 | expect(error).to.be.null(); 445 | } 446 | }); 447 | 448 | it('Should Error for Company Cleaner', async () => { 449 | try { 450 | const response = await PDLJSClient.company.cleaner(); 451 | 452 | expect(response).to.be.null(); 453 | } catch (error) { 454 | expect(error).to.be.a('object'); 455 | } 456 | }); 457 | 458 | it(`Should Return Location Cleaner Records for ${JSON.stringify(location)}`, async () => { 459 | try { 460 | const response = await PDLJSClient.location.cleaner(location); 461 | 462 | expect(response.status).to.equal(200); 463 | expect(response).to.be.a('object'); 464 | } catch (error) { 465 | expect(error).to.be.null(); 466 | } 467 | }); 468 | 469 | it('Should Error for Location Cleaner', async () => { 470 | try { 471 | const response = await PDLJSClient.location.cleaner(); 472 | 473 | expect(response).to.be.null(); 474 | } catch (error) { 475 | expect(error).to.be.a('object'); 476 | } 477 | }); 478 | 479 | it(`Should Return School Cleaner Records for ${JSON.stringify(school)}`, async () => { 480 | try { 481 | const response = await PDLJSClient.school.cleaner(school); 482 | 483 | expect(response.status).to.equal(200); 484 | expect(response).to.be.a('object'); 485 | } catch (error) { 486 | expect(error).to.be.null(); 487 | } 488 | }); 489 | 490 | it('Should Error for School Cleaner', async () => { 491 | try { 492 | const response = await PDLJSClient.school.cleaner(); 493 | 494 | expect(response).to.be.null(); 495 | } catch (error) { 496 | expect(error).to.be.a('object'); 497 | } 498 | }); 499 | }); 500 | 501 | describe('Job Title API', () => { 502 | it(`Should Return Job Title Records for ${JSON.stringify(jobTitle)}`, async () => { 503 | try { 504 | const response = await PDLJSClient.jobTitle(jobTitle); 505 | 506 | expect(response.status).to.equal(200); 507 | expect(response).to.be.a('object'); 508 | } catch (error) { 509 | expect(error).to.be.null(); 510 | } 511 | }); 512 | 513 | it('Should Error for Job Title', async () => { 514 | try { 515 | const response = await PDLJSClient.jobTitle(); 516 | 517 | expect(response).to.be.null(); 518 | } catch (error) { 519 | expect(error).to.be.a('object'); 520 | } 521 | }); 522 | }); 523 | 524 | describe('IP Enrichment API', () => { 525 | it(`Should Return IP Records for ${JSON.stringify(ip)}`, async () => { 526 | try { 527 | const response = await PDLJSClient.ip(ip); 528 | 529 | expect(response.status).to.equal(200); 530 | expect(response).to.be.a('object'); 531 | } catch (error) { 532 | expect(error).to.be.null(); 533 | } 534 | }); 535 | 536 | it(`Should Return IP Records for ${JSON.stringify(ip)} with very high confidence`, async () => { 537 | try { 538 | const object = { 539 | ...ip, 540 | min_confidence: 'very high', 541 | }; 542 | 543 | const response = await PDLJSClient.ip(object); 544 | 545 | expect(response.status).to.equal(200); 546 | expect(response).to.be.a('object'); 547 | } catch (error) { 548 | expect(error).to.be.null(); 549 | } 550 | }); 551 | 552 | it('Should Error for IP Enrichment', async () => { 553 | try { 554 | const response = await PDLJSClient.ip(); 555 | 556 | expect(response).to.be.null(); 557 | } catch (error) { 558 | expect(error).to.be.a('object'); 559 | } 560 | }); 561 | }); 562 | 563 | describe('Sandbox APIs', () => { 564 | it('Should Return Sandbox Person Record for { email: \'reneewillis74@aol.com\' }', async () => { 565 | try { 566 | const response = await PDLJSClient.person.enrichment({ email: 'reneewillis74@aol.com', sandbox: true }); 567 | 568 | expect(response.status).to.equal(200); 569 | expect(response).to.be.a('object'); 570 | } catch (error) { 571 | expect(error).to.be.null(); 572 | } 573 | }); 574 | 575 | it('Should Error for Sandbox Person Enrichment', async () => { 576 | try { 577 | const response = await PDLJSClient.person.enrichment(); 578 | 579 | expect(response).to.be.null(); 580 | } catch (error) { 581 | expect(error).to.be.a('object'); 582 | } 583 | }); 584 | 585 | it('Should Return Sandbox Person Records for "SELECT * FROM person WHERE location_country=\'united states\';"', async () => { 586 | try { 587 | const response = await PDLJSClient.person.search.sql({ searchQuery: 'SELECT * FROM person WHERE location_country=\'united states\';', size: 10, sandbox: true }); 588 | 589 | expect(response.status).to.equal(200); 590 | expect(response).to.be.a('object'); 591 | } catch (error) { 592 | expect(error).to.be.null(); 593 | } 594 | }); 595 | 596 | it('Should Error for Sandbox Person Search (sql)', async () => { 597 | try { 598 | const response = await PDLJSClient.person.search.sql({ sandbox: true }); 599 | 600 | expect(response).to.be.null(); 601 | } catch (error) { 602 | expect(error).to.be.a('object'); 603 | } 604 | }); 605 | 606 | it('Should Return Sandbox Person Records for { query: { bool: { must: [{term: {location_country: "united states"}}] } } }', async () => { 607 | try { 608 | const response = await PDLJSClient.person.search.elastic({ searchQuery: { query: { bool: { must: [{ term: { location_country: 'united states' } }] } } }, size: 10, sandbox: true }); 609 | 610 | expect(response.status).to.equal(200); 611 | expect(response).to.be.a('object'); 612 | } catch (error) { 613 | expect(error).to.be.null(); 614 | } 615 | }); 616 | 617 | it('Should Error for Sandbox Person Search (elastic)', async () => { 618 | try { 619 | const response = await PDLJSClient.person.search.elastic({ sandbox: true }); 620 | 621 | expect(response).to.be.null(); 622 | } catch (error) { 623 | expect(error).to.be.a('object'); 624 | } 625 | }); 626 | 627 | it('Should Return Sandbox Identify Person Records for { email: \'reneewillis74@aol.com\' }', async () => { 628 | try { 629 | const response = await PDLJSClient.person.identify({ email: 'reneewillis74@aol.com', sandbox: true }); 630 | 631 | expect(response.status).to.equal(200); 632 | expect(response).to.be.a('object'); 633 | } catch (error) { 634 | expect(error).to.be.null(); 635 | } 636 | }); 637 | 638 | it('Should Error for Sandbox Person Identify', async () => { 639 | try { 640 | const response = await PDLJSClient.person.identify({ sandbox: true }); 641 | 642 | expect(response).to.be.null(); 643 | } catch (error) { 644 | expect(error).to.be.a('object'); 645 | } 646 | }); 647 | }); 648 | -------------------------------------------------------------------------------- /tsconfig.eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["src/**/*", "tests", "example", ".eslintrc.cjs"], 4 | "exclude": ["node_modules", "dist",] 5 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Default", 4 | "compilerOptions": { 5 | "composite": false, 6 | "declaration": true, 7 | "declarationMap": true, 8 | "esModuleInterop": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "inlineSources": false, 11 | "isolatedModules": true, 12 | "moduleResolution": "Node16", 13 | "noUnusedLocals": false, 14 | "noUnusedParameters": false, 15 | "preserveWatchOutput": true, 16 | "skipLibCheck": true, 17 | "strict": true, 18 | "lib": ["dom", "ES2017"], 19 | "module": "Node16", 20 | "target": "ESNext" 21 | }, 22 | "include": ["src/**/*"], 23 | "exclude": ["dist", "node_modules", "tests", "example"] 24 | } 25 | --------------------------------------------------------------------------------