Icypeas
BUSINESS · CRM & SUPPORT
Email finding and verification, domain scans, and lead search on their own key.
Acts as the person, not as itself
Each user connects their own account. Every call carries both identities — the agent and the person it is acting for — so the agent can never reach past what that individual can already do.
Credentials never touch the agent
Tokens live in the vault and attach server-side at call time. The agent holds a session, not a secret, and revoking access does not mean rotating a key.
Every call on the record
Who asked, which agent acted, which action ran, and the verdict that let it through — one audit trail across every integration, not one per vendor.
What an agent can do
Each action is granted on its own. An agent allowed to read is not thereby allowed to write, and the scope beside each row is what the acting user must have connected for it to run at all.
icypeas_get_scrape_companyREADScrape one company via GET /scrape/company. Scrape one company's professional-network page from its URL (`url` is the only argument; `https://www.linkedin.com/company/<handle>`). A URL that is not a company page is refused with `wrong_linkedin_url`. A found company costs 0.5 credit; a not-found is a 200 with `success: true` and no company. Cost: 0.5 credit per found company. Rate limit: 20 calls per second. Icypeas reports a rejected INPUT with HTTP 200 and `{"success": false, "validationErrors": [{field, type, message, expected, actual}]}`; this integration raises that as an error naming the offending fields rather than returning it as a success.
icypeas_get_scrape_profileREADScrape one profile via GET /scrape/profile. Scrape one person's professional-network profile from its URL (`url` is the only argument). Anything that is not a profile URL is refused with `wrong_linkedin_url` (measured; a bare hostname is normalised to `https://<host>/` and still refused), so pass the full `https://www.linkedin.com/in/<handle>` form. A found profile costs 1.5 credits; a not-found is a 200 with `success: true` and no profile. Cost: 1.5 credits per found profile. Rate limit: 20 calls per second. Icypeas reports a rejected INPUT with HTTP 200 and `{"success": false, "validationErrors": [{field, type, message, expected, actual}]}`; this integration raises that as an error naming the offending fields rather than returning it as a success.
icypeas_post_a_actions_subscription_informationREADGet subscription and credits via POST /a/actions/subscription-information. Return the connected account's subscription and credit balance: `userId`, `status` (for example `free`), `plan`, `credits` and `quotas.daily`, plus billing ids. Send an EMPTY body: measured 2026-09-20, `{}` answers 200 with the key owner's own record, while the documented `email` field answers **401 `unauthorized_access_error`** for any address that is not the key owner's -- and for a malformed one -- so it is optional here and best left out; that 401 is not a credential failure (a bad key answers 401 `user_not_found_error`). Free, and it is this integration's connection probe: on the hosted connect page the key is checked here before it is stored (the dashboard form stores the key as pasted, and a wrong or revoked key fails at the first call). Cost: free. Rate limit: not listed in Icypeas' published rate-limit table. Icypeas reports a rejected INPUT with HTTP 200 and `{"success": false, "validationErrors": [{field, type, message, expected, actual}]}`; this integration raises that as an error naming the offending fields rather than returning it as a success.
icypeas_post_bulk_searchWRITEStart a bulk search via POST /bulk-search. Launch a bulk search over up to 5000 rows in one call. `task` is one of `email-search` (each row is `[firstname, lastname, domainOrCompany]`, with at least one of the two names non-empty), `email-verification` (each row is `[email]`) or `domain-search` (each row is `[domainOrCompany]`); `name` labels the search in the Icypeas app. `custom.externalIds` must be exactly as long as `data` when given, and `custom.includeResultsInWebhook` puts the results into the bulk-done webhook (keep it off above ~1000 rows unless the receiver accepts large POSTs). ASYNCHRONOUS: the reply carries a `file` id and `status: "in_progress"`, not the results. Follow progress with List bulk search files (`{"file": "<file>"}` -- done when `finished` is true), then fetch the rows with Read search results (`{"mode": "bulk", "file": "<file>"}`, up to 100 per page). Icypeas recommends `custom.webhookUrlItem` / `custom.webhookUrlBulkDone` over polling because the two read routes are limited per MINUTE (30 and 15 calls). Cost: per row, the same as the single route for that task (email-search 1 per found email, email-verification 0.1 per tested email, domain-search 1 per domain with results). Rate limit: 1 call per second, up to 5000 rows per call. Icypeas reports a rejected INPUT with HTTP 200 and `{"success": false, "validationErrors": [{field, type, message, expected, actual}]}`; this integration raises that as an error naming the offending fields rather than returning it as a success.
icypeas_post_bulk_single_searchs_readREADRead search results via POST /bulk-single-searchs/read. Read search results -- the one place every search's outcome comes back from. Three ways to ask, and at least one of `id` or `mode` is required (measured: `{}` answers `mode_or_id_should_be_used_error`): `{"id": "<_id>"}` fetches ONE item by the `_id` a single search returned (an unknown id answers `search_not_found_error`); `{"mode": "single"}` lists your single searches newest first, optionally filtered by `type` (`email-search`, `domain-search`, `email-verification`, ...); `{"mode": "bulk", "file": "<file>"}` lists the rows of one bulk search in data order, or `{"mode": "bulk"}` alone lists every bulk row (and `type` is NOT allowed with mode bulk). Each item carries `status` (see the single-search tools for the terminal statuses), `results` (found emails with `certainty` and `mxProvider`, name, phones), `userData.externalId` and `system` timestamps. PAGINATION is cursor-shaped: `limit` (default 10, max 100) on the first call; the reply's `sorts` array is the cursor -- pass it back with `next: true` for the following page (`false` for the previous), and stop when a page comes back empty. This route is limited to 30 calls per MINUTE, so poll gently or use webhooks. Cost: free. Rate limit: 30 calls per MINUTE. Icypeas reports a rejected INPUT with HTTP 200 and `{"success": false, "validationErrors": [{field, type, message, expected, actual}]}`; this integration raises that as an error naming the offending fields rather than returning it as a success.
icypeas_post_domain_searchWRITEScan one domain for role-based addresses via POST /domain-search. Start a scan of one domain (or company name) for its generic, role-based addresses -- contact@, admin@, sales@ and the like. ASYNCHRONOUS: the reply is not the result. It is `{"success": true, "item": {"_id": "...", "status": "NONE"}}` -- keep `item._id` and fetch the result with Read search results (`{"id": "<_id>"}`) after a few seconds. A status of NONE, SCHEDULED or IN_PROGRESS means not done yet: wait and read again. Terminal statuses are FOUND / DEBITED (a result, credits taken), NOT_FOUND / DEBITED_NOT_FOUND (processed, nothing found), BAD_INPUT, INSUFFICIENT_FUNDS and ABORTED. `custom.webhookUrl` is the alternative to polling: Icypeas POSTs the finished item to it. `custom.externalId` is echoed back in the result's `userData` and is not checked for uniqueness. Cost: 1 credit if any email is found for the domain. Rate limit: 10 calls per second. Icypeas reports a rejected INPUT with HTTP 200 and `{"success": false, "validationErrors": [{field, type, message, expected, actual}]}`; this integration raises that as an error naming the offending fields rather than returning it as a success.
icypeas_post_email_searchWRITEFind one email address via POST /email-search. Start a single email-discovery search for one person: give `domainOrCompany` (the company's domain or name) plus `firstname` and/or `lastname` -- at least ONE of the two names is mandatory (measured: both blank answers `first_last_mandatory_discovery_error`). Do not loop this for a list of people; use Start a bulk search, which takes up to 5000 rows. ASYNCHRONOUS: the reply is not the result. It is `{"success": true, "item": {"_id": "...", "status": "NONE"}}` -- keep `item._id` and fetch the result with Read search results (`{"id": "<_id>"}`) after a few seconds. A status of NONE, SCHEDULED or IN_PROGRESS means not done yet: wait and read again. Terminal statuses are FOUND / DEBITED (a result, credits taken), NOT_FOUND / DEBITED_NOT_FOUND (processed, nothing found), BAD_INPUT, INSUFFICIENT_FUNDS and ABORTED. `custom.webhookUrl` is the alternative to polling: Icypeas POSTs the finished item to it. `custom.externalId` is echoed back in the result's `userData` and is not checked for uniqueness. Cost: 1 credit per found email. Rate limit: 10 calls per second. Icypeas reports a rejected INPUT with HTTP 200 and `{"success": false, "validationErrors": [{field, type, message, expected, actual}]}`; this integration raises that as an error naming the offending fields rather than returning it as a success.
icypeas_post_email_verificationWRITEVerify one email address via POST /email-verification. Start a single verification of one email address: does it exist and is it deliverable. The result's `certainty` grades the answer (for example `ultra_sure`) and `mxProvider` names the mail host. For many addresses use Start a bulk search with task `email-verification`. ASYNCHRONOUS: the reply is not the result. It is `{"success": true, "item": {"_id": "...", "status": "NONE"}}` -- keep `item._id` and fetch the result with Read search results (`{"id": "<_id>"}`) after a few seconds. A status of NONE, SCHEDULED or IN_PROGRESS means not done yet: wait and read again. Terminal statuses are FOUND / DEBITED (a result, credits taken), NOT_FOUND / DEBITED_NOT_FOUND (processed, nothing found), BAD_INPUT, INSUFFICIENT_FUNDS and ABORTED. `custom.webhookUrl` is the alternative to polling: Icypeas POSTs the finished item to it. `custom.externalId` is echoed back in the result's `userData` and is not checked for uniqueness. Cost: 0.1 credit per tested email. Rate limit: 10 calls per second. Icypeas reports a rejected INPUT with HTTP 200 and `{"success": false, "validationErrors": [{field, type, message, expected, actual}]}`; this integration raises that as an error naming the offending fields rather than returning it as a success.
icypeas_post_find_companiesREADFind companies via POST /find-companies. Return the companies matching `query` from Icypeas' lead database, `pagination.size` (1-200, default 100) at a time, at 0.02 credit per returned company -- size the query with Count companies matching a query first. Same filters as the count route. PAGINATION: `pagination: {"size": N}` on the first call, then pass back the `pagination.token` each reply hands you, with the same `query`, until none is returned; tokens expire. SYNCHRONOUS: the companies are in the reply (measured 2026-09-20: `{"name": {"include": ["icypeas"]}}` with size 1 -> total 1 and one full lead). Each lead carries `name`, `lid`, `urn`, `url`, `description`, `address`, `numberOfEmployees`, `headcountRange`, `industry`, `type`, `website`, `specialties` and `_id`. Each call is also recorded as a 'Company search' file visible in List bulk search files. Cost: 0.02 credit per returned result (100 results = 2 credits). Rate limit: 30 calls per second. Icypeas reports a rejected INPUT with HTTP 200 and `{"success": false, "validationErrors": [{field, type, message, expected, actual}]}`; this integration raises that as an error naming the offending fields rather than returning it as a success.
icypeas_post_find_companies_countREADCount companies matching a query via POST /find-companies/count. Count the companies in Icypeas' lead database matching `query`, free of charge (measured: `{"query": {"name": {"include": ["icypeas"]}}}` -> `{"total": 1, "success": true}`). `query` is an object of named filters: `name`, `lid` (the public profile id at the end of the company URL), `urn` (numeric id), `companyId` (domain, URN, URL or vanity name), `type` (Privately Held, Public Company, Nonprofit, ...), `industry`, `location`, `domain`, `keyword`, and the numeric ranges `headcount`, `revenue` and `headcountGrowth`. Text filters take `{"include": [...], "exclude": [...]}`; ranges take `{">": 10, "<=": 500}`. A location like "Paris, France" only matches when every comma-separated part matches. An unknown filter or an empty query is refused. Cost: free. Rate limit: 10 calls per second. Icypeas reports a rejected INPUT with HTTP 200 and `{"success": false, "validationErrors": [{field, type, message, expected, actual}]}`; this integration raises that as an error naming the offending fields rather than returning it as a success.
icypeas_post_find_peopleREADFind people via POST /find-people. Return the people matching `query` from Icypeas' lead database, `pagination.size` (1-200, default 100) at a time, at 0.02 credit per returned person -- 100 results cost 2 credits, so run Count people matching a query first. `query` takes the same filters as the count route (see that tool). PAGINATION: send `pagination: {"size": N}` on the first call; when more remain the reply carries `pagination.token`, which you pass back unchanged (with the SAME `query` -- changing it mid-walk is undefined) until no token comes back. Tokens expire. The reply is `{"success", "total", "leads": [...], "pagination"?}` -- SYNCHRONOUS, the leads are in it (measured 2026-09-20: size 1 returned one full lead). Each call is also recorded as a 'Lead search' file (task `fleads-profile-search`) visible in List bulk search files. Cost: 0.02 credit per returned result (100 results = 2 credits). Rate limit: 30 calls per second. Icypeas reports a rejected INPUT with HTTP 200 and `{"success": false, "validationErrors": [{field, type, message, expected, actual}]}`; this integration raises that as an error naming the offending fields rather than returning it as a success.
icypeas_post_find_people_countREADCount people matching a query via POST /find-people/count. Count the people in Icypeas' lead database matching `query`, without returning any of them and without spending credits. Use it to size a query before Find people bills 0.02 credit per returned person. `query` is an object of named filters -- `firstname`, `lastname`, `currentJobTitle`, `pastJobTitle`, `school`, `languages`, `skills`, `location` / `profileLocation` / `workLocation`, `keyword`, `currentCompanyName`, `pastCompanyName`, `currentCompanyId`, `currentCompanyWebsite`, `currentCompany.type`, `currentCompany.industry`, `currentCompany.location`, `currentCompany.headcount`, `currentCompany.headcountGrowth`, `currentCompany.revenue`, `currentCompany.keyword` and their `pastCompany*` twins. Text filters take `{"include": [...], "exclude": [...]}` (200 values per array); numeric ones take a range `{">=": 5, "<": 10}`; headcount growth takes `{"min", "max", "timespan": "6months"|"12months"|"24months"}`. An unknown filter name is refused (`invalid_keys_in_query_error`), and an EMPTY query is refused too (`empty_query_error`) -- at least one filter is required. Every `current*` filter applies to the SAME current job. Cost: free. Rate limit: 10 calls per second. Icypeas reports a rejected INPUT with HTTP 200 and `{"success": false, "validationErrors": [{field, type, message, expected, actual}]}`; this integration raises that as an error naming the offending fields rather than returning it as a success.
icypeas_post_reverse_email_lookupWRITEReverse-lookup one email address via POST /reverse-email-lookup. Find the professional-network profile URL behind ONE professional email address. This is the most expensive call on the platform (10 credits per FOUND profile; a miss is free), so confirm the address is worth it. The reply says whether a URL was found; a not-found is a 200 with `success: true` and no URL, not an error. Cost: 10 credits per found profile. Rate limit: 20 calls per second. Icypeas reports a rejected INPUT with HTTP 200 and `{"success": false, "validationErrors": [{field, type, message, expected, actual}]}`; this integration raises that as an error naming the offending fields rather than returning it as a success.
icypeas_post_reverse_email_lookupsWRITEReverse-lookup many email addresses via POST /reverse-email-lookups. Find the profile URLs behind MANY professional email addresses in one call: `data` is an array of 2 to 50 addresses (one address is refused; use the single route). Each found profile costs 10 credits, so a full batch of hits can cost 500 credits. Cost: 10 credits per found profile, the same as the single route. Rate limit: 15 calls per second, up to 50 rows per call. Icypeas reports a rejected INPUT with HTTP 200 and `{"success": false, "validationErrors": [{field, type, message, expected, actual}]}`; this integration raises that as an error naming the offending fields rather than returning it as a success.
icypeas_post_scrapeWRITEScrape profiles or companies in bulk via POST /scrape. Scrape up to 50 profiles OR up to 50 companies in one call: `type` is `profile` or `company` and `data` is the matching list of URLs -- the two kinds cannot be mixed in one call, and an empty `data` is refused (`validation_array_empty`, measured). Icypeas documents this route twice, once per type, and documents the reply only as 'Response 200 when your input does not contain any validation errors'; this build did not spend credits to observe a successful bulk scrape, so expect a job reference and read results through Read search results rather than expecting the scraped records inline. Cost: per row, the same as the single scrape route for that type. Rate limit: 20 calls per second, up to 50 rows per call. Icypeas reports a rejected INPUT with HTTP 200 and `{"success": false, "validationErrors": [{field, type, message, expected, actual}]}`; this integration raises that as an error naming the offending fields rather than returning it as a success.
icypeas_post_search_files_readREADList bulk search files via POST /search-files/read. List the bulk searches ("files") on the account with their progress and statistics: `total`, `done`, `found`, `in-progress`, `bad-input`, `credits-missing`, `aborted`, `finished` and `task`. `{}` lists them all newest first; `{"status": "in_progress"}` or `{"status": "done"}` filters; `{"file": "<file>"}` reads one. Measured: an UNKNOWN file id is not an error -- it answers a placeholder record with `total: 0`, an empty `task` and `finished: false`, so check `task` is non-empty before trusting the counters. `limit` is 1-50 (default 10); paginate with the reply's `sorts` array and `next: true`. Limited to 15 calls per MINUTE. A bulk is done when `finished` is true; then fetch its rows with Read search results in mode bulk. Cost: free. Rate limit: 15 calls per MINUTE. Icypeas reports a rejected INPUT with HTTP 200 and `{"success": false, "validationErrors": [{field, type, message, expected, actual}]}`; this integration raises that as an error naming the offending fields rather than returning it as a success.
icypeas_post_url_searchWRITEFind profile or company URLs in bulk via POST /url-search. Find up to 50 profile URLs OR up to 50 company URLs in one call. `type` is `profile` or `company`; each `data` row is `{firstname, lastname, companyOrDomain?, jobTitle?}` for profiles (both names required, plus company or job title) or `{companyOrDomain}` for companies. TWO MEASURED TRAPS: (1) omitting `type` answers HTTP 401 `unauthorized_access_error` ("Unauthorized access.") even with a working key -- that is a missing field, not a credential problem; a bad key answers 401 `user_not_found_error` ("The user does not exist") instead. (2) An EMPTY `data` array is accepted (200 `{"success": true, "data": []}`) and still CREATES an empty bulk file on the account, so do not call this to 'test' the route. ASYNCHRONOUS: the reply carries a `file` id and `status: "in_progress"`, not the results. Follow progress with List bulk search files (`{"file": "<file>"}` -- done when `finished` is true), then fetch the rows with Read search results (`{"mode": "bulk", "file": "<file>"}`, up to 100 per page). Icypeas recommends `custom.webhookUrlItem` / `custom.webhookUrlBulkDone` over polling because the two read routes are limited per MINUTE (30 and 15 calls). Cost: per row, the same as the single url-search route for that type. Rate limit: 20 calls per second, up to 50 rows per call. Icypeas reports a rejected INPUT with HTTP 200 and `{"success": false, "validationErrors": [{field, type, message, expected, actual}]}`; this integration raises that as an error naming the offending fields rather than returning it as a success.
icypeas_post_url_search_companyWRITEFind one company URL via POST /url-search/company. Find ONE company's profile page URL from its name, domain or website (`companyOrDomain`). 1 credit per found URL; a not-found is a 200 with `success: true` and no URL. Cost: 1 credit per found URL. Rate limit: 20 calls per second. Icypeas reports a rejected INPUT with HTTP 200 and `{"success": false, "validationErrors": [{field, type, message, expected, actual}]}`; this integration raises that as an error naming the offending fields rather than returning it as a success.
icypeas_post_url_search_profileWRITEFind one profile URL via POST /url-search/profile. Find ONE person's profile URL from their name: `firstname` and `lastname` are both required, plus at least one of `companyOrDomain` (company name, domain or website) or `jobTitle` (measured: neither given answers `field_required` on companyOrDomain). 1 credit per found URL; a not-found is a 200 with `success: true` and no URL. Cost: 1 credit per found URL. Rate limit: 20 calls per second. Icypeas reports a rejected INPUT with HTTP 200 and `{"success": false, "validationErrors": [{field, type, message, expected, actual}]}`; this integration raises that as an error naming the offending fields rather than returning it as a success.
Often connected alongside
Put Icypeas behind one governed endpoint.
Same permissions, same audit trail, whatever else you connect next.