[{"data":1,"prerenderedAt":503},["ShallowReactive",2],{"docs-navigation":3,"docs-\u002Fsdk\u002Fjavascript":204},[4,11,16,21,29,35,42,48,54,59,64,69,74,79,86,92,98,103,108,113,118,123,127,132,137,141,145,148,152,157,160,163,167,170,174,178,181,185,189,193,197,201],{"path":5,"title":6,"category":7,"order":8,"family":9,"subfamily":9,"status":10,"endpointId":9},"\u002Fagents","Agent brief","mcp",40,null,"new",{"path":12,"title":13,"category":14,"order":15,"family":9,"subfamily":9,"status":9,"endpointId":9},"\u002Fapi-reference","API reference","introduction",30,{"path":17,"title":18,"category":14,"order":19,"family":9,"subfamily":9,"status":20,"endpointId":9},"\u002Fauthentication","Authentication",20,"updated",{"path":22,"title":23,"category":24,"order":25,"family":26,"subfamily":27,"status":20,"endpointId":28},"\u002Fendpoints\u002Fcheck-company","Company profile status","endpoints",220,"Fetch","Company","check-company",{"path":30,"title":31,"category":24,"order":32,"family":26,"subfamily":33,"status":20,"endpointId":34},"\u002Fendpoints\u002Fcheck-person","Person profile status",120,"Person","check-person",{"path":36,"title":37,"category":24,"order":38,"family":39,"subfamily":40,"status":9,"endpointId":41},"\u002Fendpoints\u002Fcontact-email","Find Email",600,"Contact","Email","contact-email",{"path":43,"title":44,"category":24,"order":45,"family":39,"subfamily":46,"status":9,"endpointId":47},"\u002Fendpoints\u002Fcontact-phone","Find Phone",610,"Phone","contact-phone",{"path":49,"title":50,"category":24,"order":51,"family":52,"subfamily":27,"status":20,"endpointId":53},"\u002Fendpoints\u002Fenrich-company","Enrich company",90,"Enrichment","enrich-company",{"path":55,"title":56,"category":24,"order":57,"family":52,"subfamily":33,"status":20,"endpointId":58},"\u002Fendpoints\u002Fenrich-person","Enrich profile",80,"enrich-person",{"path":60,"title":61,"category":24,"order":62,"family":26,"subfamily":27,"status":20,"endpointId":63},"\u002Fendpoints\u002Ffetch-company","Company profile",200,"fetch-company",{"path":65,"title":66,"category":24,"order":67,"family":26,"subfamily":27,"status":20,"endpointId":68},"\u002Fendpoints\u002Ffetch-company-live","Company profile live",210,"fetch-company-live",{"path":70,"title":71,"category":24,"order":72,"family":26,"subfamily":33,"status":20,"endpointId":73},"\u002Fendpoints\u002Ffetch-profile","Person profile",100,"fetch-profile",{"path":75,"title":76,"category":24,"order":77,"family":26,"subfamily":33,"status":20,"endpointId":78},"\u002Fendpoints\u002Ffetch-profile-live","Person profile live",110,"fetch-profile-live",{"path":80,"title":81,"category":24,"order":82,"family":83,"subfamily":84,"status":20,"endpointId":85},"\u002Fendpoints\u002Fsearch-companies","Company search",94,"Search","Companies","search-companies",{"path":87,"title":88,"category":24,"order":89,"family":90,"subfamily":9,"status":20,"endpointId":91},"\u002Fendpoints\u002Fsearch-companies-available-fields","Company search available fields",720,"Utility","search-companies-available-fields",{"path":93,"title":94,"category":24,"order":95,"family":83,"subfamily":96,"status":10,"endpointId":97},"\u002Fendpoints\u002Fsearch-people","People search",92,"People","search-people",{"path":99,"title":100,"category":24,"order":101,"family":90,"subfamily":9,"status":10,"endpointId":102},"\u002Fendpoints\u002Fsearch-people-available-fields","People search available fields",710,"search-people-available-fields",{"path":104,"title":105,"category":24,"order":106,"family":83,"subfamily":96,"status":10,"endpointId":107},"\u002Fendpoints\u002Fsearch-people-count","People search count",93,"search-people-count",{"path":109,"title":110,"category":24,"order":111,"family":83,"subfamily":96,"status":10,"endpointId":112},"\u002Fendpoints\u002Fsearch-people-lookalike","People lookalike",95,"search-people-lookalike",{"path":114,"title":115,"category":24,"order":116,"family":83,"subfamily":96,"status":10,"endpointId":117},"\u002Fendpoints\u002Fsearch-people-prompt","Agentic Search",96,"search-people-prompt",{"path":119,"title":120,"category":24,"order":121,"family":90,"subfamily":9,"status":20,"endpointId":122},"\u002Fendpoints\u002Fusage","Usage",700,"usage",{"path":124,"title":125,"category":14,"order":126,"family":9,"subfamily":9,"status":9,"endpointId":9},"\u002Fgetting-started","Getting started",10,{"path":128,"title":129,"category":130,"order":131,"family":9,"subfamily":9,"status":10,"endpointId":9},"\u002Fguides\u002Fagent-skills","Agent skills","cli",70,{"path":133,"title":134,"category":135,"order":136,"family":9,"subfamily":9,"status":20,"endpointId":9},"\u002Fguides\u002Fapi-key-management","API key management","guides",12,{"path":138,"title":139,"category":130,"order":140,"family":9,"subfamily":9,"status":10,"endpointId":9},"\u002Fguides\u002Fcli","Command line interface (CLI)",60,{"path":142,"title":143,"category":135,"order":144,"family":9,"subfamily":9,"status":10,"endpointId":9},"\u002Fguides\u002Fcurrent-position-resolution","Current position and work history ordering",35,{"path":146,"title":147,"category":135,"order":8,"family":9,"subfamily":9,"status":20,"endpointId":9},"\u002Fguides\u002Fdata-freshness","Data freshness",{"path":149,"title":150,"category":135,"order":151,"family":9,"subfamily":9,"status":10,"endpointId":9},"\u002Fguides\u002Fdata-quality","Data quality",18,{"path":153,"title":154,"category":155,"order":156,"family":9,"subfamily":9,"status":10,"endpointId":9},"\u002Fguides\u002Fendpoint-transition-october-2026","Endpoint transition on October 13, 2026","migrations",1,{"path":158,"title":159,"category":135,"order":19,"family":9,"subfamily":9,"status":20,"endpointId":9},"\u002Fguides\u002Ferrors-retries","Error handling & retries",{"path":161,"title":162,"category":135,"order":126,"family":9,"subfamily":9,"status":10,"endpointId":9},"\u002Fguides\u002Ffirst-api-call","Your first API call",{"path":164,"title":165,"category":135,"order":166,"family":9,"subfamily":9,"status":10,"endpointId":9},"\u002Fguides\u002Findustries","Industry values",50,{"path":168,"title":169,"category":7,"order":166,"family":9,"subfamily":9,"status":20,"endpointId":9},"\u002Fguides\u002Fmcp","Connect AI agents (MCP)",{"path":171,"title":172,"category":155,"order":173,"family":9,"subfamily":9,"status":10,"endpointId":9},"\u002Fguides\u002Fmigrating-search-persons-to-people","Migrating people search from persons to people",51,{"path":175,"title":176,"category":135,"order":177,"family":9,"subfamily":9,"status":10,"endpointId":9},"\u002Fguides\u002Fmissing-and-empty-fields","Missing and empty profile fields",42,{"path":179,"title":180,"category":135,"order":15,"family":9,"subfamily":9,"status":20,"endpointId":9},"\u002Fguides\u002Fpolling","Polling, zero setup",{"path":182,"title":183,"category":135,"order":184,"family":9,"subfamily":9,"status":20,"endpointId":9},"\u002Fguides\u002Fproduction-checklist","Production checklist",45,{"path":186,"title":187,"category":135,"order":188,"family":9,"subfamily":9,"status":20,"endpointId":9},"\u002Fguides\u002Frate-limits-credits","Rate limits & credits",25,{"path":190,"title":191,"category":135,"order":192,"family":9,"subfamily":9,"status":20,"endpointId":9},"\u002Fguides\u002Fwebhooks","Webhooks",31,{"path":194,"title":195,"category":135,"order":196,"family":9,"subfamily":9,"status":20,"endpointId":9},"\u002Fguides\u002Fwhich-endpoint-should-i-use","Which endpoint should I use?",15,{"path":198,"title":199,"category":200,"order":126,"family":9,"subfamily":9,"status":10,"endpointId":9},"\u002Fsdk\u002Fjavascript","JavaScript and TypeScript","sdk",{"path":202,"title":203,"category":200,"order":19,"family":9,"subfamily":9,"status":10,"endpointId":9},"\u002Fsdk\u002Fpython","Python",{"id":205,"title":199,"audience":9,"badgeColor":9,"badgeLabel":9,"body":206,"category":200,"description":494,"endpointId":9,"extension":495,"family":9,"lastVerified":496,"links":9,"meta":497,"navigation":498,"order":126,"path":198,"relatedArticles":499,"requiresFlag":9,"seo":500,"status":10,"stem":501,"subfamily":9,"__hash__":502},"docs\u002Fsdk\u002Fjavascript.md",{"type":207,"value":208,"toc":481},"minimark",[209,213,226,237,241,263,285,293,305,320,324,341,350,357,361,402,411,424,428,433,447,451,457,461],[210,211,212],"h2",{"id":14},"Introduction",[214,215,216,217,221,222,225],"p",{},"There is no Reverse Contact package to install. The API is JSON over HTTPS, so the ",[218,219,220],"code",{},"fetch"," built into Node.js 18 and later, Bun and Deno is all a call needs. For types and autocompletion on every request and response, generate a client from the OpenAPI spec this site publishes at ",[218,223,224],{},"https:\u002F\u002Fdocs.reversecontact.com\u002Fopenapi.json",", which is updated with each docs release.",[214,227,228,229,232,233,236],{},"Keep the API key on the server, in an environment variable such as ",[218,230,231],{},"RC_API_KEY",". Never send it to a browser: see ",[234,235,18],"a",{"href":17},".",[210,238,240],{"id":239},"typed-client-from-the-openapi-spec","Typed client from the OpenAPI spec",[214,242,243,249,250,253,254,256,257,259,260,236],{},[234,244,248],{"href":245,"rel":246},"https:\u002F\u002Fopenapi-ts.dev",[247],"nofollow","openapi-typescript"," turns the spec into TypeScript types, and ",[218,251,252],{},"openapi-fetch"," is a small ",[218,255,220],{}," wrapper that checks every path, body and response against them. ",[218,258,248],{}," needs TypeScript 5, hence ",[218,261,262],{},"typescript@5",[264,265,267,278],"code-group",{"title":266},"Install",[268,269,276],"pre",{"className":270,"code":272,"filename":273,"language":274,"meta":275},[271],"language-bash","npm install openapi-fetch\nnpm install --save-dev openapi-typescript typescript@5\nnpx openapi-typescript https:\u002F\u002Fdocs.reversecontact.com\u002Fopenapi.json -o reversecontact.d.ts\n","npm","bash","",[218,277,272],{"__ignoreMap":275},[268,279,283],{"className":280,"code":281,"filename":282,"language":274,"meta":275},[271],"bun add openapi-fetch\nbun add --dev openapi-typescript typescript@5\nbunx openapi-typescript https:\u002F\u002Fdocs.reversecontact.com\u002Fopenapi.json -o reversecontact.d.ts\n","Bun",[218,284,281],{"__ignoreMap":275},[214,286,287,288,292],{},"Run the last command again whenever the ",[234,289,291],{"href":290},"\u002Fchangelog","changelog"," announces a change to an endpoint you call.",[264,294,296],{"title":295},"Enrich a person",[268,297,303],{"className":298,"code":300,"filename":301,"language":302,"meta":275},[299],"language-typescript","import createClient from 'openapi-fetch'\nimport type { paths } from '.\u002Freversecontact'\n\nconst rc = createClient\u003Cpaths>({\n  baseUrl: 'https:\u002F\u002Fapi.reversecontact.com',\n  headers: { Authorization: `Bearer ${process.env.RC_API_KEY}` }\n})\n\n\u002F\u002F Enrich a person from a work email: 2 credits when found, a 404 is free.\nconst { data, error, response } = await rc.POST('\u002Fv2\u002Fenrich\u002Fpersons', {\n  body: { email: 'jane.doe@acme.com' }\n})\n\nif (data) {\n  const person = data.data?.person\n  console.log(person?.firstName, person?.lastName, person?.currentPositionTitle)\n  console.log('Credits used:', data.quotas.creditsConsumed)\n} else if (response.status === 404) {\n  console.log('No confident match: nothing was charged')\n} else {\n  throw new Error(`${response.status} ${error?.error.code}: ${error?.error.message}`)\n}\n","TypeScript","typescript",[218,304,300],{"__ignoreMap":275},[214,306,307,308,311,312,315,316,319],{},"The paths keep their ",[218,309,310],{},"\u002Fv2"," prefix (",[218,313,314],{},"\u002Fv2\u002Fenrich\u002Fpersons","), as in the spec. On Enrich, a ",[218,317,318],{},"404"," is not an error to retry: it means no profile matched with confidence, and it costs nothing.",[210,321,323],{"id":322},"async-jobs","Async jobs",[214,325,326,327,329,330,332,333,336,337,340],{},"The live fetch endpoints, ",[234,328,37],{"href":36}," and ",[234,331,44],{"href":43}," answer with a job. Poll it until it succeeds or fails: polling is free and does not count toward your rate limit. Give the loop a maximum duration, and stop on a poll that answers an error: ",[218,334,335],{},"404 WEBHOOK_EVENT_NOT_FOUND"," for an unknown job, ",[218,338,339],{},"410 WEBHOOK_EVENT_EXPIRED"," for a result older than 72 hours.",[264,342,344],{"title":343},"Live fetch and polling",[268,345,348],{"className":346,"code":347,"filename":301,"language":302,"meta":275},[299],"const { data: job, error: jobError } = await rc.POST('\u002Fv2\u002Ffetch\u002Fpersons\u002Flive', {\n  body: { url: 'https:\u002F\u002Fsocial.com\u002Fin\u002Fjanedoe' }\n})\nconst webhookId = job?.data?.webhookId\nif (!webhookId) throw new Error(jobError?.error.message ?? 'No job created')\n\n\u002F\u002F Results usually arrive within seconds, but can take tens of minutes.\nconst deadline = Date.now() + 30 * 60 * 1000\n\nfor (;;) {\n  if (Date.now() > deadline) throw new Error(`Job ${webhookId} still running: poll it again later`)\n  await new Promise((resolve) => setTimeout(resolve, 5000))\n  const { data: poll, error: pollError, response } = await rc.GET('\u002Fv2\u002Fwebhooks\u002F{webhookId}', {\n    params: { path: { webhookId } }\n  })\n  \u002F\u002F A 5xx is temporary: poll again. 404 and 410 mean there is nothing left to wait for.\n  if (!poll) {\n    if (response.status >= 500) continue\n    throw new Error(`${response.status} ${pollError?.error.code}: ${pollError?.error.message}`)\n  }\n  if (poll.data?.status === 'succeeded') {\n    console.log(poll.data.result)\n    break\n  }\n  if (poll.data?.status === 'errored') throw new Error(poll.data.errorCode ?? 'Job errored')\n}\n",[218,349,347],{"__ignoreMap":275},[214,351,352,353,356],{},"Every 5 to 10 seconds suits a background job. See ",[234,354,355],{"href":179},"Polling"," for the intervals that fit other cases, and for how long a result stays available.",[210,358,360],{"id":359},"without-code-generation","Without code generation",[214,362,363,364,366,367,370,371,374,375,378,379,378,382,385,386,389,390,385,392,394,395,397,398,401],{},"When you would rather not generate types, this helper is enough. It follows the retry rule of ",[234,365,159],{"href":158},": on a ",[218,368,369],{},"429",", wait the number of seconds in ",[218,372,373],{},"error.details.retryAfter",", then retry; on a ",[218,376,377],{},"500",", ",[218,380,381],{},"502",[218,383,384],{},"503"," or ",[218,387,388],{},"504",", retry with exponential backoff, a few times at most. It reads the status before the body, because a ",[218,391,381],{},[218,393,384],{}," from the network edge may not be JSON. A ",[218,396,369],{}," with the code ",[218,399,400],{},"DAILY_LIMIT_EXCEEDED"," is the daily limit: it is not retried, since it does not clear within minutes.",[264,403,405],{"title":404},"fetch helper",[268,406,409],{"className":407,"code":408,"filename":301,"language":302,"meta":275},[299],"const API = 'https:\u002F\u002Fapi.reversecontact.com\u002Fv2'\nconst BACKOFF = new Set([500, 502, 503, 504])\nconst MAX_ATTEMPTS = 5\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))\n\n\u002F** One call to the API. 429: waits error.details.retryAfter. 500, 502, 503, 504: backs off. *\u002F\nexport async function rc(path: string, body?: unknown) {\n  for (let attempt = 1; ; attempt++) {\n    const response = await fetch(`${API}${path}`, {\n      method: body === undefined ? 'GET' : 'POST',\n      headers: {\n        Authorization: `Bearer ${process.env.RC_API_KEY}`,\n        'Content-Type': 'application\u002Fjson'\n      },\n      body: body === undefined ? undefined : JSON.stringify(body)\n    })\n\n    \u002F\u002F The status first: a 502 or 503 from the network edge may not be JSON.\n    if (BACKOFF.has(response.status) && attempt \u003C MAX_ATTEMPTS) {\n      await sleep(Math.min(1000 * 2 ** attempt, 15000))\n      continue\n    }\n    const json = await response.json().catch(() => ({\n      success: false,\n      error: { code: `HTTP_${response.status}`, message: 'The response is not JSON' }\n    }))\n    if (response.status === 429 && json.error?.code !== 'DAILY_LIMIT_EXCEEDED' && attempt \u003C MAX_ATTEMPTS) {\n      await sleep((json.error?.details?.retryAfter ?? 60) * 1000)\n      continue\n    }\n    return { status: response.status, ...json }\n  }\n}\n\nconst result = await rc('\u002Fenrich\u002Fpersons', { email: 'jane.doe@acme.com' })\nif (result.success) console.log(result.data.person.currentPositionTitle)\nelse if (result.status === 404) console.log('No confident match: nothing was charged')\nelse console.error(result.status, result.error.code, result.error.message)\n",[218,410,408],{"__ignoreMap":275},[214,412,413,414,416,417,419,420,423],{},"Here the paths start after ",[218,415,310],{},". What a ",[218,418,318],{}," means depends on the endpoint: on Enrich, no confident match; on a cached fetch, a profile that is not in the cache; on ",[218,421,422],{},"\u002Fv2\u002Fwebhooks",", an unknown job. Every error other than the retried ones needs a change to the request or the account before it can succeed.",[210,425,427],{"id":426},"faq","FAQ",[429,430,432],"h3",{"id":431},"is-there-an-official-reverse-contact-npm-package","Is there an official Reverse Contact npm package?",[214,434,435,436,438,439,441,442,329,444,446],{},"No. The Reverse Contact API is JSON over HTTPS, so ",[218,437,220],{}," is enough, and a typed client generated from ",[218,440,224],{}," with ",[218,443,248],{},[218,445,252],{}," gives types for every endpoint.",[429,448,450],{"id":449},"can-i-call-the-reverse-contact-api-from-the-browser","Can I call the Reverse Contact API from the browser?",[214,452,453,454,456],{},"Not with your API key: anyone can read a key shipped in front-end code. Call the API from your server, keep the key in an environment variable such as ",[218,455,231],{},", and send the browser only what it needs.",[429,458,460],{"id":459},"which-reverse-contact-api-errors-should-my-code-retry","Which Reverse Contact API errors should my code retry?",[214,462,463,464,370,466,468,469,471,472,378,474,378,476,329,478,480],{},"On a ",[218,465,369],{},[218,467,373],{},", then retry, except for ",[218,470,400],{},", the daily limit. Retry ",[218,473,377],{},[218,475,381],{},[218,477,384],{},[218,479,388],{}," with exponential backoff, a few times at most. Every other error needs a change to the request or the account first.",{"title":275,"searchDepth":482,"depth":482,"links":483},3,[484,486,487,488,489],{"id":14,"depth":485,"text":212},2,{"id":239,"depth":485,"text":240},{"id":322,"depth":485,"text":323},{"id":359,"depth":485,"text":360},{"id":426,"depth":485,"text":427,"children":490},[491,492,493],{"id":431,"depth":482,"text":432},{"id":449,"depth":482,"text":450},{"id":459,"depth":482,"text":460},"Call the Reverse Contact API from Node.js, Bun or Deno with a typed client generated from the OpenAPI spec, or with a small fetch helper.","md","2026-10-15",{},true,"\u002Fdocs\u002Fsdk\u002Fpython,\u002Fdocs\u002Fauthentication,\u002Fdocs\u002Fguides\u002Ferrors-retries,\u002Fdocs\u002Fguides\u002Fpolling",{"title":199,"description":494},"sdk\u002Fjavascript","1kN-bNT6Pkr-zyyO4GOC3_1zfKXKSoZj2vnVlIHZpUs",1792078621431]