Introduction
This documentation aims to provide all the information you need to work with our API.
Rate limits
Most endpoints limit how many requests can run at the same time, not how many you send per minute. A request counts from the moment it is received until its response is sent: you can send as many requests as you want, as long as no more than the endpoint's limit are in progress at once. Each endpoint lists its Rate limit. Requests over the limit are rejected with a 429 status code.
On usage-based plans, the limit on each endpoint is capped by your plan. An endpoint with a lower limit keeps it.
- Individual: up to 25 simultaneous requests
- Team: up to 50 simultaneous requests
- Scale: up to 150 simultaneous requests
Credit cost
Each endpoint lists its Credit cost (credit-based plans). On a credit-based plan, the cost is deducted from your team's credit balance, and requests are rejected with a 402 status code when the balance is too low.
Usage-based plans (Individual, Team, Scale) are not billed in credits: requests count toward your plan's usage limits.
Authenticating requests
To authenticate requests, include an Authorization header with the value "Bearer {YOUR_AUTH_KEY}".
All authenticated endpoints are marked with a requires authentication badge in the documentation below.
You can retrieve your token by visiting API page.
Email Verifier
Verify an email
requires authentication
Rate limit: 300 simultaneous requests.
Credit cost (credit-based plans): 1 verifier credit per verification, whatever the result.
Example request:
curl --request POST \
"https://app.findymail.com/api/verify" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--data "{
\"email\": \"[email protected]\"
}"
const url = new URL(
"https://app.findymail.com/api/verify"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "[email protected]"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{ "email": "[email protected]", "verified" : true, "provider": 'Google'}
Example response (200):
{
"error": "Not enough credits"
}
Example response (402, Error : Not enough credits):
{
"error": "Not enough credits"
}
Example response (423, Error : Subscription is paused):
{
"error": "Subscription is paused"
}
Example response (429, Plan usage capacity reached):
{
"error": "Your plan's usage capacity is reached for now. Retry after 2026-09-18T14:05:00+00:00 (in 300 seconds).",
"retry_after": 300,
"retry_at": "2026-09-18T14:05:00+00:00"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Contacts
Get the list of contact lists
requires authentication
Example request:
curl --request GET \
--get "https://app.findymail.com/api/lists" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}"const url = new URL(
"https://app.findymail.com/api/lists"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"lists": [
{
"id": 1,
"name": "my list",
"created_at": "2022-08-23T16:46:43.000000Z",
"updated_at": "2022-08-23T16:46:43.000000Z",
"shared_with_team": false,
"is_owner": true
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create a new list
requires authentication
Example request:
curl --request POST \
"https://app.findymail.com/api/lists" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--data "{
\"name\": \"architecto\"
}"
const url = new URL(
"https://app.findymail.com/api/lists"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "architecto"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"list": {
"id": 1,
"name": "new list",
"created_at": "2022-08-23T16:46:43.000000Z",
"updated_at": "2022-08-23T16:46:43.000000Z",
"shared_with_team": false,
"is_owner": true
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update a contact list
requires authentication
Example request:
curl --request PUT \
"https://app.findymail.com/api/lists/16" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--data "{
\"name\": \"architecto\",
\"isShared\": false
}"
const url = new URL(
"https://app.findymail.com/api/lists/16"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "architecto",
"isShared": false
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"id": 1,
"name": "updated list name",
"created_at": "2022-08-23T16:46:43.000000Z",
"updated_at": "2022-08-23T16:46:43.000000Z",
"shared_with_team": true,
"is_owner": true
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete a given list
requires authentication
Example request:
curl --request DELETE \
"https://app.findymail.com/api/lists/16" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}"const url = new URL(
"https://app.findymail.com/api/lists/16"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (200, Success):
{}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get contacts saved
requires authentication
Example request:
curl --request GET \
--get "https://app.findymail.com/api/contacts/get/16" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}"const url = new URL(
"https://app.findymail.com/api/contacts/get/16"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"draw": 0,
"recordsTotal": 1,
"recordsFiltered": 1,
"data": [
{
"id": 1,
"name": "John Doe",
"email": "[email protected]",
"linkedin_url": "https://www.linkedin.com/in/linkedin",
"company": "MyCompany",
"job_title": "CEO"
},
],
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Email Finder
Find from name
requires authentication
Find someone's email from name and company (website or name).
Rate limit: 300 simultaneous requests.
Credit cost (credit-based plans): 1 finder credit when an email is found. Free when no email is found.
Example request:
curl --request POST \
"https://app.findymail.com/api/search/name" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--data "{
\"name\": \"John Doe\",
\"domain\": \"website.com\"
}"
const url = new URL(
"https://app.findymail.com/api/search/name"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "John Doe",
"domain": "website.com"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, Success):
{
"contact": {
"name": "John Doe",
"domain": "website.com",
"email": "[email protected]"
}
}
Example response (200, Webhook URL provided process asynchronous):
{
"payload": {
"contact": {
"name": "john doe",
"email": "[email protected]",
"domain": "website.com"
}
}
}
Example response (402, Error : Not enough credits):
{
"error": "Not enough credits"
}
Example response (423, Error : Subscription is paused):
{
"error": "Subscription is paused"
}
Example response (429, Plan usage capacity reached):
{
"error": "Your plan's usage capacity is reached for now. Retry after 2026-09-18T14:05:00+00:00 (in 300 seconds).",
"retry_after": 300,
"retry_at": "2026-09-18T14:05:00+00:00"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
payload
(when using webhook_url) object POST method callback request triggered when webhook_url provided. See example response
Find from domain
requires authentication
Try finding a contact with a valid email at a given domain with a given role. A contact is only returned if we found a valid email.
Due to the heavy processing involved (real-time search), async jobs can take up to 24 hours to be processed depending on our workload (usually sooner).
Rate limit: 10 simultaneous requests.
Credit cost (credit-based plans): 1 finder credit when an email is found. Free when no email is found.
Example request:
curl --request POST \
"https://app.findymail.com/api/search/domain" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--data "{
\"domain\": \"domain.com\",
\"roles\": [
\"CEO\",
\"Founder\"
]
}"
const url = new URL(
"https://app.findymail.com/api/search/domain"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"domain": "domain.com",
"roles": [
"CEO",
"Founder"
]
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (0, Webhook URL provided process asynchronous):
{
"payload": {
"contacts": [
{
"name": "say my name",
"email": "[email protected]",
"domain": "domain.com"
}
]
}
}
Example response (200):
{
"contacts": [
{
"domain": "website.com",
"email": "[email protected]",
"name": "john doe"
}
]
}
Example response (402, Error : Not enough credits):
{
"error": "Not enough credits"
}
Example response (423, Error : Subscription is paused):
{
"error": "Subscription is paused"
}
Example response (429, Plan usage capacity reached):
{
"error": "Your plan's usage capacity is reached for now. Retry after 2026-09-18T14:05:00+00:00 (in 300 seconds).",
"retry_after": 300,
"retry_at": "2026-09-18T14:05:00+00:00"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
payload
(when using webhook_url) object POST method callback request triggered when webhook_url provided. See example response
Find from business profile
requires authentication
Find someone's email from a business profile URL.
Rate limit: 50 simultaneous requests.
Credit cost (credit-based plans): 1 finder credit when an email is found. Free when no email is found.
Example request:
curl --request POST \
"https://app.findymail.com/api/search/business-profile" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--data "{
\"linkedin_url\": \"https:\\/\\/www.linkedin.com\\/in\\/johndoe\"
}"
const url = new URL(
"https://app.findymail.com/api/search/business-profile"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"linkedin_url": "https:\/\/www.linkedin.com\/in\/johndoe"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (0, Webhook URL provided process asynchronous):
{
"payload": {
"contact": {
"name": "john doe",
"email": "[email protected]",
"domain": "website.com"
}
}
}
Example response (200):
{
"contact": {
"name": "John Doe",
"domain": "website.com",
"email": "[email protected]"
}
}
Example response (402, Error : Not enough credits):
{
"error": "Not enough credits"
}
Example response (423, Error : Subscription is paused):
{
"error": "Subscription is paused"
}
Example response (429, Plan usage capacity reached):
{
"error": "Your plan's usage capacity is reached for now. Retry after 2026-09-18T14:05:00+00:00 (in 300 seconds).",
"retry_after": 300,
"retry_at": "2026-09-18T14:05:00+00:00"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
payload
(when using webhook_url) object POST method callback request triggered when webhook_url provided. See example response
Exclusion Lists
APIs for managing excluded websites from Intellimatch searches
Get all exclusion lists
requires authentication
Returns all exclusion lists the authenticated user has access to (owned lists and lists shared with their team)
Rate limit: 50 simultaneous requests.
Example request:
curl --request GET \
--get "https://app.findymail.com/api/intellimatch/exclusion-lists" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}"const url = new URL(
"https://app.findymail.com/api/intellimatch/exclusion-lists"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, Ok):
{
"lists": [
{
"id": 1,
"name": "Competitors",
"is_shared": true,
"is_owner": true,
"user_id": 123,
"owner_name": "John Doe"
}
]
}
Example response (401, Unauthenticated):
{
"message": "Unauthenticated."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create a new exclusion list
requires authentication
Creates a new exclusion list for the authenticated user.
Optionally share the list with the user's current team.
Rate limit: 50 simultaneous requests.
Example request:
curl --request POST \
"https://app.findymail.com/api/intellimatch/exclusion-lists" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--data "{
\"name\": \"Competitors\",
\"is_shared\": true
}"
const url = new URL(
"https://app.findymail.com/api/intellimatch/exclusion-lists"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Competitors",
"is_shared": true
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, Ok):
{
"id": 1,
"name": "Competitors",
"is_shared": true,
"is_owner": true
}
Example response (401, Unauthenticated):
{
"message": "Unauthenticated."
}
Example response (422, Validation failed):
{
"message": "The given data was invalid.",
"errors": {
"name": [
"The name has already been taken."
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get exclusion list details
requires authentication
Returns the details of a specific exclusion list (without domains). To get domains, use the dedicated GET /api/intellimatch/domains?list_id={id} endpoint. Users can only access lists they own or lists shared with their team.
Rate limit: 50 simultaneous requests.
Example request:
curl --request GET \
--get "https://app.findymail.com/api/intellimatch/exclusion-lists/16" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}"const url = new URL(
"https://app.findymail.com/api/intellimatch/exclusion-lists/16"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, Ok):
{
"id": 1,
"name": "Competitors",
"is_shared": true,
"is_owner": true,
"user_id": 123,
"owner_name": "John Doe"
}
Example response (401, Unauthenticated):
{
"message": "Unauthenticated."
}
Example response (403, Forbidden):
{
"message": "This action is unauthorized."
}
Example response (404, Not found):
{
"message": "No query results for model [ExcludedDomainList]."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update an exclusion list
requires authentication
Updates an exclusion list's name and/or sharing status.
Only the list owner can update or change sharing settings.
Rate limit: 50 simultaneous requests.
Example request:
curl --request PUT \
"https://app.findymail.com/api/intellimatch/exclusion-lists/16" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--data "{
\"name\": \"Updated List Name\",
\"is_shared\": true
}"
const url = new URL(
"https://app.findymail.com/api/intellimatch/exclusion-lists/16"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Updated List Name",
"is_shared": true
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, Ok):
{
"success": true,
"list": {
"id": 1,
"name": "Updated List Name",
"is_shared": true,
"is_owner": true
}
}
Example response (400, No team):
{
"error": "You must be part of a team to share lists."
}
Example response (401, Unauthenticated):
{
"message": "Unauthenticated."
}
Example response (403, Forbidden):
{
"message": "This action is unauthorized."
}
Example response (404, Not found):
{
"message": "No query results for model [ExcludedDomainList]."
}
Example response (422, Validation failed):
{
"message": "The given data was invalid.",
"errors": {
"name": [
"The name has already been taken."
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete an exclusion list
requires authentication
Deletes an exclusion list and all its associated domains.
Only the list owner can delete the list.
Rate limit: 50 simultaneous requests.
Example request:
curl --request DELETE \
"https://app.findymail.com/api/intellimatch/exclusion-lists/16" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}"const url = new URL(
"https://app.findymail.com/api/intellimatch/exclusion-lists/16"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (200, Ok):
{
"success": true
}
Example response (401, Unauthenticated):
{
"message": "Unauthenticated."
}
Example response (403, Forbidden):
{
"message": "This action is unauthorized."
}
Example response (404, Not found):
{
"message": "No query results for model [ExcludedDomainList]."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get excluded domains
requires authentication
Returns a paginated list of excluded domains for the authenticated user.
Can be filtered by list_id to get domains from a specific list, otherwise returns the global exclusion list.
Rate limit: 50 simultaneous requests.
Example request:
curl --request GET \
--get "https://app.findymail.com/api/intellimatch/domains?query=example.com&list_id=1&per_page=15&page=1" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}"const url = new URL(
"https://app.findymail.com/api/intellimatch/domains"
);
const params = {
"query": "example.com",
"list_id": "1",
"per_page": "15",
"page": "1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, Ok):
{
"data": [
{
"id": 1,
"domain": "competitor.com",
"excluded_domain_list_id": 1
},
{
"id": 2,
"domain": "blocked.io",
"excluded_domain_list_id": null
}
],
"current_page": 1,
"per_page": 15,
"total": 150
}
Example response (401, Unauthenticated):
{
"message": "Unauthenticated."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Add excluded domains
requires authentication
Adds one or more domains to the user's exclusion list. If list_id is provided, domains are added to that specific list. For large batches (>50 domains), the first 50 are processed immediately and the rest are queued for background processing.
Rate limit: 50 simultaneous requests.
Example request:
curl --request POST \
"https://app.findymail.com/api/intellimatch/domains" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--data "{
\"domains\": [
\"competitor.com\",
\"blocked.io\"
],
\"list_id\": 1
}"
const url = new URL(
"https://app.findymail.com/api/intellimatch/domains"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"domains": [
"competitor.com",
"blocked.io"
],
"list_id": 1
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, Ok):
{
"success": true,
"total": 150,
"processed_immediately": 50,
"queued": 100,
"list_id": 1
}
Example response (401, Unauthenticated):
{
"message": "Unauthenticated."
}
Example response (403, Forbidden):
{
"message": "This action is unauthorized."
}
Example response (422, Validation failed):
{
"message": "The given data was invalid.",
"errors": {
"domains": [
"The domains field is required."
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Remove excluded domains
requires authentication
Removes one or more domains from the user's exclusion lists.
Only domains the user has permission to delete will be removed.
For domains in shared lists, the user must have removeDomains permission on the list.
For global domains (no list), the user must own the domain.
Rate limit: 50 simultaneous requests.
Example request:
curl --request DELETE \
"https://app.findymail.com/api/intellimatch/domains" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--data "{
\"ids\": [
1,
2,
3
]
}"
const url = new URL(
"https://app.findymail.com/api/intellimatch/domains"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"ids": [
1,
2,
3
]
};
fetch(url, {
method: "DELETE",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, Ok):
{
"success": true,
"deleted_count": 3
}
Example response (200, No permission):
{
"success": false,
"deleted_count": 0
}
Example response (401, Unauthenticated):
{
"message": "Unauthenticated."
}
Example response (422, Validation failed):
{
"message": "The given data was invalid.",
"errors": {
"ids": [
"The ids field is required."
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Intellimatch
Search leads
requires authentication
Create an Intellimatch search task.
Intellimatch is Findymail’s intelligent company search tool that lets you build highly targeted lead lists using plain language queries.
Instead of manually applying filters or reviewing websites one by one, Intellimatch uses real-time semantic search to find the best-fit companies and contacts.
The API responds immediately with a hash identifying the task for polling completion status.
Please check https://help.findymail.com/en/article/what-is-supported-in-intellimatch-15s0u10/ for more information about what is supported or not.
Rate limit: 50 simultaneous requests.
Credit cost (credit-based plans), charged once the export is generated:
- Companies: 1 finder credit per 10 companies returned, rounded up, in
broadmode; 1 finder credit per company intargetedmode - 1 finder credit per contact found (
find_contact) - 1 finder credit per email found (
find_email) - 10 finder credits per phone number found (
find_phone)
Example request:
curl --request POST \
"https://app.findymail.com/api/intellimatch/search" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--data "{
\"query\": \"SaaS companies in US with 50-200 employees\",
\"limit\": 100,
\"config\": {
\"find_contact\": true,
\"find_email\": true,
\"target_job_titles\": [
[
\"RevOps\"
],
[
\"CEO\",
\"CTO\"
]
],
\"mode\": \"broad\",
\"find_phone\": false,
\"lead_list_id\": 123,
\"require_email\": true,
\"add_to_exclusion_list\": true,
\"exclusion_list_id\": 456,
\"exclusion_filter_list_ids\": [
1,
2,
3
]
}
}"
const url = new URL(
"https://app.findymail.com/api/intellimatch/search"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"query": "SaaS companies in US with 50-200 employees",
"limit": 100,
"config": {
"find_contact": true,
"find_email": true,
"target_job_titles": [
[
"RevOps"
],
[
"CEO",
"CTO"
]
],
"mode": "broad",
"find_phone": false,
"lead_list_id": 123,
"require_email": true,
"add_to_exclusion_list": true,
"exclusion_list_id": 456,
"exclusion_filter_list_ids": [
1,
2,
3
]
}
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, Ok):
{
"hash": "74ebbec924a9666053d234eecc685a1d73c699d1"
}
Example response (401, Unauthenticated):
{
"message": "Unauthenticated."
}
Example response (422, Validation failed):
{
"message": "The given data was invalid.",
"errors": {
"query": [
"The search query is required."
],
"limit": [
"The limit cannot exceed 5000 companies."
]
}
}
Example response (423, Subscription issue):
{
"error": "Your subscription is currently paused."
}
Example response (429, Too Many Attempts):
{
"message": "Too Many Attempts."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
hash
string
Unique hash to track the export progress and retrieve results.
Get export status
requires authentication
Poll this endpoint to check if a given search is completed.
The response will contain a status field with one of the following values:
success: Export is completed and ready to downloadprocessing: Export is currently being processed (includes progress information)pending: Export is queued but not yet startedfailed: Export has failednot_found: Export hash not found or expired
Rate limit: 50 simultaneous requests.
Credit cost (credit-based plans): free.
Example request:
curl --request GET \
--get "https://app.findymail.com/api/intellimatch/status?hash=74ebbec924a9666053d234eecc685a1d73c699d1" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}"const url = new URL(
"https://app.findymail.com/api/intellimatch/status"
);
const params = {
"hash": "74ebbec924a9666053d234eecc685a1d73c699d1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, Export processing):
{
"status": "processing",
"progress": 45,
"total_jobs": 100,
"processed_jobs": 45,
"pending_jobs": 55,
"failed_jobs": 0
}
Example response (401, Unauthenticated):
{
"message": "Unauthenticated."
}
Example response (422, Validation failed):
{
"message": "The given data was invalid.",
"errors": {
"hash": [
"The hash parameter is required."
]
}
}
Example response (423, Subscription issue):
{
"error": "Your subscription is currently paused."
}
Example response (429, Too Many Attempts):
{
"message": "Too Many Attempts."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
status
string
The current status of the export.
progress
integer
The progress percentage (only when status is "processing").
total_jobs
integer
Total number of jobs (only when status is "processing").
processed_jobs
integer
Number of processed jobs (only when status is "processing").
pending_jobs
integer
Number of pending jobs (only when status is "processing").
failed_jobs
integer
Number of failed jobs (only when status is "processing").
Get results
requires authentication
Retrieve paginated company and contact results from a completed search task.
Rate limit: 50 simultaneous requests.
Credit cost (credit-based plans): free. Credits are charged by the search itself.
Example request:
curl --request GET \
--get "https://app.findymail.com/api/intellimatch/data?hash=74ebbec924a9666053d234eecc685a1d73c699d1&page=1&per_page=100" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}"const url = new URL(
"https://app.findymail.com/api/intellimatch/data"
);
const params = {
"hash": "74ebbec924a9666053d234eecc685a1d73c699d1",
"page": "1",
"per_page": "100",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, Ok):
{
"data": [
{
"id": 1,
"name": "Acme Corp",
"domain": "acme.com",
"description": "Leading SaaS company",
"employee_count_range": "51-200",
"industries": [
"Technology",
"Software"
],
"country": "FR",
"match_score": 95,
"contact_name": "John Doe",
"contact_email": "[email protected]",
"contact_job_title": "CEO",
"contact_phone": "+33 6 12 34 56 78",
"contact_linkedin_url": "https://www.linkedin.com/in/johndoe"
}
],
"meta": {
"current_page": 1,
"per_page": 100,
"total": 250,
"last_page": 3,
"from": 1,
"to": 100
}
}
Example response (401, Unauthenticated):
{
"message": "Unauthenticated."
}
Example response (404, Export not found):
{
"status": "error",
"message": "Export not found or not ready yet"
}
Example response (422, Validation failed):
{
"message": "The given data was invalid.",
"errors": {
"hash": [
"The hash parameter is required."
],
"per_page": [
"The per_page cannot exceed 500."
]
}
}
Example response (423, Subscription issue):
{
"error": "Your subscription is currently paused."
}
Example response (429, Too Many Attempts):
{
"message": "Too Many Attempts."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Search lookalike companies
requires authentication
Find companies similar to a given seed domain.
Optionally filter results by same country or same company size, and exclude companies from specific exclusion lists.
Rate limit: 50 simultaneous requests.
Credit cost (credit-based plans): 1 finder credit per 10 companies returned, rounded up. Free when no company is returned.
Example request:
curl --request POST \
"https://app.findymail.com/api/lookalike/search" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--data "{
\"seed\": \"stripe.com\",
\"same_country\": true,
\"same_size\": false,
\"limit\": 100,
\"exclusion_list_ids\": [
1,
2
]
}"
const url = new URL(
"https://app.findymail.com/api/lookalike/search"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"seed": "stripe.com",
"same_country": true,
"same_size": false,
"limit": 100,
"exclusion_list_ids": [
1,
2
]
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, Ok):
{
"companies": [
{
"domain": "notion.so",
"name": "Notion",
"linkedin_url": "https://www.linkedin.com/company/notionhq",
"company_size": "501-1000",
"country": "United States"
},
{
"domain": "airtable.com",
"name": "Airtable",
"linkedin_url": "https://www.linkedin.com/company/airtable",
"company_size": "501-1000",
"country": "United States"
}
],
"total": 2,
"credits_used": 1
}
Example response (200, No results with message):
{
"companies": [],
"total": 0,
"credits_used": 0,
"message": "We don't have country data for example.com yet. The same country filter is not available at the moment but will be soon."
}
Example response (402, Not enough credits):
{
"error": "insufficient_credits",
"message": "You don't have enough credits."
}
Example response (422, Seed not processable):
{
"error": "seed_not_processable",
"message": "We could not process this domain. Please try another one."
}
Example response (422, Validation failed):
{
"message": "The given data was invalid.",
"errors": {
"seed": [
"The seed must be a valid domain or URL. Given: not-a-domain"
]
}
}
Example response (423, Subscription issue):
{
"error": "Your subscription is currently paused."
}
Example response (429, Too Many Attempts):
{
"message": "Too Many Attempts."
}
Example response (429, Plan usage capacity reached):
{
"error": "Your plan's usage capacity is reached for now. Retry after 2026-09-18T14:05:00+00:00 (in 300 seconds).",
"retry_after": 300,
"retry_at": "2026-09-18T14:05:00+00:00"
}
Example response (500, Internal error):
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again later."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
companies
object[]
List of similar companies found.
domain
string
The company domain.
name
string
The company name.
linkedin_url
string
The company LinkedIn URL (nullable).
company_size
string
Employee count range (e.g. "51-200").
country
string
Country display name (nullable).
total
integer
Total number of companies returned.
credits_used
integer
Number of Finder credits consumed.
message
string
Informational message when filters cannot be applied (only present when relevant).
Misc
Reverse email lookup
requires authentication
Find a business profile from an email address (work email or personal email).
Rate limit: 300 simultaneous requests.
Credit cost (credit-based plans):
- 1 finder credit when a profile is found
- 1 more finder credit when
with_profileis enabled and the profile data is retrieved - Free when no profile is found
Example request:
curl --request POST \
"https://app.findymail.com/api/search/reverse-email" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--data "{
\"email\": \"[email protected]\",
\"with_profile\": false
}"
const url = new URL(
"https://app.findymail.com/api/search/reverse-email"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "[email protected]",
"with_profile": false
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, Without profile enrichment):
{
"linkedin_url": "https://www.linkedin.com/in/johndoe"
}
Example response (200, With profile enrichment):
{
"fullName": "John Doe",
"username": "johndoe",
"headline": "CEO at Example",
"jobTitle": "CEO",
"summary": "Summary",
"city": "City",
"region": "Region",
"country": "Country",
"companyLinkedinUrl": "https://linkedin.com/company/example",
"companyName": "Example",
"companyWebsite": "example.com",
"isPremium": true,
"isOpenProfile": true,
"skills": [],
"jobs": [],
"educations": [
{
"school": "Harvard University",
"degree": "Bachelor of Science",
"fieldOfStudy": "Computer Science",
"startDate": "2010-09",
"endDate": "2014-06"
}
],
"certificates": [
{
"name": "AWS Solutions Architect",
"issuingOrganization": "Amazon Web Services",
"issueDate": "2020-01",
"expirationDate": "2023-01"
}
]
}
Example response (200, No LinkedIn URL found):
{
"linkedin_url": null
}
Example response (402, Error : Not enough credits):
{
"error": "Not enough credits"
}
Example response (423, Error : Subscription is paused):
{
"error": "Subscription is paused"
}
Example response (429, Plan usage capacity reached):
{
"error": "Your plan's usage capacity is reached for now. Retry after 2026-09-18T14:05:00+00:00 (in 300 seconds).",
"retry_after": 300,
"retry_at": "2026-09-18T14:05:00+00:00"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get company information
requires authentication
Retrieve company data using a company profile URL, name, or website domain. At least one of these fields must be specified.
Rate limit: 300 simultaneous requests.
Credit cost (credit-based plans): 1 finder credit when the company is found. Free when no company is found.
Example request:
curl --request POST \
"https://app.findymail.com/api/search/company" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--data "{
\"linkedin_url\": \"https:\\/\\/www.linkedin.com\\/company\\/findymail\\/\",
\"domain\": \"stripe.com\",
\"name\": \"Stripe\"
}"
const url = new URL(
"https://app.findymail.com/api/search/company"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"linkedin_url": "https:\/\/www.linkedin.com\/company\/findymail\/",
"domain": "stripe.com",
"name": "Stripe"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"name": "Stripe",
"domain": "stripe.com",
"company_size": "1001-5000",
"industry": "Financial Services",
"linkedin_url": "https://www.linkedin.com/company/stripe/",
"description": "Stripe is a technology company..."
}
Example response (404):
{
"message": "Not Found"
}
Example response (422):
{
"error": "One identifier is required: linkedin_url, domain, name"
}
Example response (429, Plan usage capacity reached):
{
"error": "Your plan's usage capacity is reached for now. Retry after 2026-09-18T14:05:00+00:00 (in 300 seconds).",
"retry_after": 300,
"retry_at": "2026-09-18T14:05:00+00:00"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Find employees
requires authentication
Find one or more employees using the company website and job title.
Rate limit: 50 simultaneous requests.
Credit cost (credit-based plans): 1 finder credit per employee returned. Free when no employee is found.
This endpoint does NOT return an email.
Example request:
curl --request POST \
"https://app.findymail.com/api/search/employees" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--data "{
\"website\": \"google.com\",
\"job_titles\": [
\"Software Engineer\",
\"CEO\"
],
\"count\": 2
}"
const url = new URL(
"https://app.findymail.com/api/search/employees"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"website": "google.com",
"job_titles": [
"Software Engineer",
"CEO"
],
"count": 2
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
[
{
"name": "John Done",
"linkedinUrl": "https://www.linkedin.com/in/john-doe/",
"companyWebsite": "https://www.findymail.com",
"companyName": "Findymail",
"jobTitle": "Software Engineer"
}
]
Example response (402, Error : Not enough credits):
{
"error": "Not enough credits"
}
Example response (423, Error : Subscription is paused):
{
"error": "Subscription is paused"
}
Example response (429, Plan usage capacity reached):
{
"error": "Your plan's usage capacity is reached for now. Retry after 2026-09-18T14:05:00+00:00 (in 300 seconds).",
"retry_after": 300,
"retry_at": "2026-09-18T14:05:00+00:00"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Phone Finder
Find phone
requires authentication
Find someone's phone number from a business profile URL.
For legal reasons, requests for EU citizens will not return any result.
Rate limit: 300 simultaneous requests.
Credit cost (credit-based plans): 10 finder credits when a phone number is found. Free when no phone number is found.
Example request:
curl --request POST \
"https://app.findymail.com/api/search/phone" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--data "{
\"linkedin_url\": \"https:\\/\\/www.linkedin.com\\/in\\/johndoe\"
}"
const url = new URL(
"https://app.findymail.com/api/search/phone"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"linkedin_url": "https:\/\/www.linkedin.com\/in\/johndoe"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"phone": "+1234567890",
"line_type": "Mobile"
}
Example response (200, Phone not found):
{
"phone": null,
"line_type": null
}
Example response (402, Error : Not enough credits):
{
"error": "Not enough credits"
}
Example response (423, Error : Subscription is paused):
{
"error": "Subscription is paused"
}
Example response (429, Plan usage capacity reached):
{
"error": "Your plan's usage capacity is reached for now. Retry after 2026-09-18T14:05:00+00:00 (in 300 seconds).",
"retry_after": 300,
"retry_at": "2026-09-18T14:05:00+00:00"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
phone
string
The phone number in E.164 format (e.g. +1234567890), or null if not found. Only available for US numbers.
line_type
string
The type of phone line (e.g. "Mobile", "Landline"), or null if not found.
Signals
List signals
requires authentication
Returns a paginated list of signals from monitors accessible by the authenticated user (owned and team-shared). Supports filtering by signal_type, monitor_id, and date range.
Example request:
curl --request GET \
--get "https://app.findymail.com/api/signals?signal_type=keyword_mention&monitor_id=1&date_from=2026-01-01&date_to=2026-03-01&relevance_scores=3%2C4%2C5&page=1&per_page=50" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}"const url = new URL(
"https://app.findymail.com/api/signals"
);
const params = {
"signal_type": "keyword_mention",
"monitor_id": "1",
"date_from": "2026-01-01",
"date_to": "2026-03-01",
"relevance_scores": "3,4,5",
"page": "1",
"per_page": "50",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, Ok):
{
"data": [
{
"id": 1,
"type": "keyword_mention",
"category": "contact",
"payload": {
"matched_keyword": "hiring",
"snippet": "We are hiring a new VP of Sales..."
},
"detected_at": "2026-03-01T12:00:00+00:00",
"expires_at": "2026-06-01T12:00:00+00:00",
"contact": {
"id": 1,
"name": "John Doe",
"job_title": "CEO",
"linkedin_url": "https://www.linkedin.com/in/johndoe"
},
"company": {
"id": 1,
"name": "Acme Corp",
"domain": "acme.com",
"industry": "Technology, Information and Internet",
"employee_count_range": "51-200",
"country": "US"
},
"monitors": [
{
"id": 1,
"name": "Hiring monitor",
"keywords": [
"hiring"
],
"enrichment_level": "email",
"relevance_score": 4,
"relevance_reasoning": "Post discusses active hiring for sales roles"
}
]
}
],
"meta": {
"current_page": 1,
"per_page": 50,
"total": 1,
"last_page": 1,
"from": 1,
"to": 1
}
}
Example response (401, Unauthenticated):
{
"message": "Unauthenticated."
}
Example response (422, Validation failed):
{
"message": "The given data was invalid."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
List monitors
requires authentication
Returns all monitors accessible by the authenticated user (owned and team-shared), ordered by most recent first. Each monitor includes a match_count with the number of signals matched.
Example request:
curl --request GET \
--get "https://app.findymail.com/api/signals/monitors?ownership=my" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}"const url = new URL(
"https://app.findymail.com/api/signals/monitors"
);
const params = {
"ownership": "my",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, Ok):
[
{
"id": 1,
"name": "Hiring monitor",
"signal_type": "keyword_mention",
"signal_type_label": "Keyword Mention",
"signal_level": "contact",
"status": "active",
"keywords": [
"hiring",
"fundraise"
],
"icp_filters": {
"industries": [
"Biotechnology"
],
"countries": [
"US"
]
},
"webhook_url": "https://example.com/webhooks/signals",
"webhook_paused_at": null,
"post_url": null,
"profile_url": null,
"engagement_types": null,
"enrichment_level": "email",
"lead_list_id": null,
"ai_relevance_prompt": null,
"target_companies": null,
"max_matches": 50,
"match_count": 42,
"is_shared": true,
"is_owner": true,
"is_team_owner": false,
"uses_current_users_monitor_cap": true,
"user_id": 42,
"owner_name": "Jane Doe",
"created_at": "2026-02-01T10:00:00.000000Z"
}
]
Example response (401, Unauthenticated):
{
"message": "Unauthenticated."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create a monitor
requires authentication
Creates a new signal monitor for the authenticated user.
Credit cost (credit-based plans): creating a monitor is free. Each signal it delivers costs:
- 1 finder credit
- 1 more finder credit for
keyword_mentionandpost_engagementmonitors with company filters (icp_filters.industries,icp_filters.employee_count_rangesoricp_filters.countries) - 1 more finder credit for
keyword_mentionandpost_engagementmonitors with contact filters (icp_filters.job_title_keywordsoricp_filters.seniority_levels) - With
enrichment_level: 1 finder credit when an email is found, and 10 finder credits when a phone number is found (email_phone)
Example request:
curl --request POST \
"https://app.findymail.com/api/signals/monitors" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--data "{
\"name\": \"Hiring monitor\",
\"signal_type\": \"keyword_mention\",
\"keywords\": [
\"hiring\",
\"fundraise\"
],
\"webhook_url\": \"https:\\/\\/example.com\\/webhooks\\/signals\",
\"enrichment_level\": \"email\",
\"lead_list_id\": 42,
\"ai_relevance_prompt\": \"Focus on Series B+ SaaS companies hiring VP Sales.\",
\"max_matches\": 50,
\"is_shared\": false,
\"icp_filters\": {
\"industries\": [
\"Biotechnology\"
],
\"employee_count_ranges\": [
\"51-200\"
],
\"countries\": [
\"US\",
\"FR\"
],
\"job_title_keywords\": [
\"VP Sales\",
\"CTO\"
],
\"seniority_levels\": [
11,
13
]
}
}"
const url = new URL(
"https://app.findymail.com/api/signals/monitors"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Hiring monitor",
"signal_type": "keyword_mention",
"keywords": [
"hiring",
"fundraise"
],
"webhook_url": "https:\/\/example.com\/webhooks\/signals",
"enrichment_level": "email",
"lead_list_id": 42,
"ai_relevance_prompt": "Focus on Series B+ SaaS companies hiring VP Sales.",
"max_matches": 50,
"is_shared": false,
"icp_filters": {
"industries": [
"Biotechnology"
],
"employee_count_ranges": [
"51-200"
],
"countries": [
"US",
"FR"
],
"job_title_keywords": [
"VP Sales",
"CTO"
],
"seniority_levels": [
11,
13
]
}
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201, Created):
{
"id": 1,
"name": "Hiring monitor",
"signal_type": "keyword_mention",
"signal_type_label": "Keyword Mention",
"signal_level": "contact",
"status": "active",
"keywords": [
"hiring",
"fundraise"
],
"icp_filters": null,
"webhook_url": null,
"webhook_paused_at": null,
"post_url": null,
"profile_url": null,
"engagement_types": null,
"enrichment_level": null,
"lead_list_id": null,
"ai_relevance_prompt": null,
"target_companies": null,
"max_matches": 50,
"match_count": 0,
"is_shared": false,
"is_owner": true,
"is_team_owner": false,
"uses_current_users_monitor_cap": true,
"user_id": 42,
"owner_name": "Jane Doe",
"created_at": "2026-02-01T10:00:00.000000Z"
}
Example response (401, Unauthenticated):
{
"message": "Unauthenticated."
}
Example response (422, Validation failed):
{
"message": "The given data was invalid."
}
Example response (422, Active monitor cap reached):
{
"message": "Your Individual plan includes 5 active signals. Upgrade to Team to get 25 active signals.",
"errors": {
"monitors": [
"Your Individual plan includes 5 active signals. Upgrade to Team to get 25 active signals."
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update a monitor
requires authentication
Updates an existing monitor. The signal_type cannot be changed after creation.
Example request:
curl --request PATCH \
"https://app.findymail.com/api/signals/monitors/1" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--data "{
\"name\": \"Updated monitor name\",
\"keywords\": [
\"hiring\",
\"fundraise\"
],
\"webhook_url\": \"https:\\/\\/example.com\\/webhooks\\/signals\",
\"enrichment_level\": \"email\",
\"lead_list_id\": 42,
\"ai_relevance_prompt\": \"Focus on Series B+ SaaS companies hiring VP Sales.\",
\"max_matches\": 50,
\"is_shared\": true,
\"icp_filters\": {
\"industries\": [
\"Biotechnology\"
],
\"employee_count_ranges\": [
\"51-200\"
],
\"countries\": [
\"US\",
\"FR\"
],
\"job_title_keywords\": [
\"VP Sales\"
],
\"seniority_levels\": [
11,
13
]
}
}"
const url = new URL(
"https://app.findymail.com/api/signals/monitors/1"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Updated monitor name",
"keywords": [
"hiring",
"fundraise"
],
"webhook_url": "https:\/\/example.com\/webhooks\/signals",
"enrichment_level": "email",
"lead_list_id": 42,
"ai_relevance_prompt": "Focus on Series B+ SaaS companies hiring VP Sales.",
"max_matches": 50,
"is_shared": true,
"icp_filters": {
"industries": [
"Biotechnology"
],
"employee_count_ranges": [
"51-200"
],
"countries": [
"US",
"FR"
],
"job_title_keywords": [
"VP Sales"
],
"seniority_levels": [
11,
13
]
}
};
fetch(url, {
method: "PATCH",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, Ok):
{
"id": 1,
"name": "Updated monitor name",
"signal_type": "keyword_mention",
"signal_type_label": "Keyword Mention",
"signal_level": "contact",
"status": "active",
"keywords": [
"hiring",
"fundraise"
],
"icp_filters": null,
"webhook_url": null,
"webhook_paused_at": null,
"post_url": null,
"profile_url": null,
"engagement_types": null,
"enrichment_level": null,
"lead_list_id": null,
"ai_relevance_prompt": null,
"target_companies": null,
"max_matches": 50,
"match_count": 42,
"is_shared": true,
"is_owner": true,
"is_team_owner": false,
"user_id": 42,
"owner_name": "Jane Doe",
"created_at": "2026-02-01T10:00:00.000000Z"
}
Example response (401, Unauthenticated):
{
"message": "Unauthenticated."
}
Example response (403, Forbidden):
{
"message": "This action is unauthorized."
}
Example response (422, Validation failed):
{
"message": "The given data was invalid."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete a monitor
requires authentication
Soft-deletes the specified monitor.
Example request:
curl --request DELETE \
"https://app.findymail.com/api/signals/monitors/1" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}"const url = new URL(
"https://app.findymail.com/api/signals/monitors/1"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (204, Deleted):
Empty response
Example response (401, Unauthenticated):
{
"message": "Unauthenticated."
}
Example response (403, Forbidden):
{
"message": "This action is unauthorized."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get a signal
requires authentication
Returns a single signal with its associated contact, company, and the authenticated user's monitors.
Example request:
curl --request GET \
--get "https://app.findymail.com/api/signals/1" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}"const url = new URL(
"https://app.findymail.com/api/signals/1"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, Ok):
{
"id": 1,
"type": "keyword_mention",
"category": "contact",
"payload": {
"matched_keyword": "hiring",
"snippet": "We are hiring a new VP of Sales..."
},
"detected_at": "2026-03-01T12:00:00+00:00",
"expires_at": "2026-06-01T12:00:00+00:00",
"contact": {
"id": 1,
"name": "John Doe",
"job_title": "CEO",
"linkedin_url": "https://www.linkedin.com/in/johndoe"
},
"company": {
"id": 1,
"name": "Acme Corp",
"domain": "acme.com",
"industry": "Technology, Information and Internet",
"employee_count_range": "51-200",
"country": "US"
},
"monitors": [
{
"id": 1,
"name": "Hiring monitor",
"keywords": [
"hiring"
],
"enrichment_level": "email"
}
]
}
Example response (401, Unauthenticated):
{
"message": "Unauthenticated."
}
Example response (403, Forbidden):
{
"message": "This action is unauthorized."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Technologies
Search technologies
requires authentication
Search the technology catalog by name. Returns up to 25 technologies.
Rate limit: 10 requests per minute.
Credit cost (credit-based plans): free.
Example request:
curl --request GET \
--get "https://app.findymail.com/api/technologies/search?q=React" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}"const url = new URL(
"https://app.findymail.com/api/technologies/search"
);
const params = {
"q": "React",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, Ok):
{
"data": [
{
"name": "React",
"category": "Programming Languages And Frameworks",
"subcategory": "Frameworks"
}
]
}
Example response (422, Validation failed):
{
"message": "The given data was invalid.",
"errors": {
"q": [
"The q field is required."
]
}
}
Example response (429, Too Many Attempts):
{
"message": "Too Many Attempts."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
data
object[]
List of matching technologies.
name
string
Technology name.
category
string
Technology category (nullable).
subcategory
string
Technology subcategory (nullable).
Lookup technologies by domain
requires authentication
Get the technology stack for a company by its domain.
Optionally filter by technology name (case-insensitive).
Rate limit: 300 simultaneous requests.
Credit cost (credit-based plans): 1 finder credit when at least one technology is returned. Free when no technology is returned.
Example request:
curl --request POST \
"https://app.findymail.com/api/technologies" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--data "{
\"domain\": \"stripe.com\",
\"technologies\": [
\"React\",
\"typescript\"
]
}"
const url = new URL(
"https://app.findymail.com/api/technologies"
);
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"domain": "stripe.com",
"technologies": [
"React",
"typescript"
]
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, Technologies found):
{
"domain": "stripe.com",
"technologies": [
{
"name": "React",
"category": "Programming Languages And Frameworks",
"subcategory": "Frameworks",
"last_detected_at": "2026-03-15T10:00:00.000000Z"
}
]
}
Example response (200, No results (no credit charged)):
{
"domain": "unknown-domain.com",
"technologies": []
}
Example response (402, Not enough credits):
{
"error": "insufficient_credits",
"message": "You don't have enough credits."
}
Example response (422, Validation failed):
{
"message": "The given data was invalid.",
"errors": {
"domain": [
"The domain field is required."
]
}
}
Example response (423, Subscription issue):
{
"error": "Your subscription is currently paused."
}
Example response (429, Plan usage capacity reached):
{
"error": "Your plan's usage capacity is reached for now. Retry after 2026-09-18T14:05:00+00:00 (in 300 seconds).",
"retry_after": 300,
"retry_at": "2026-09-18T14:05:00+00:00"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
domain
string
The resolved company domain.
technologies
object[]
List of technologies detected for this company.
name
string
Technology name.
category
string
Technology category (nullable).
subcategory
string
Technology subcategory (nullable).
last_detected_at
string
ISO 8601 timestamp of the most recent detection (nullable).
Usage
Get remaining credits
requires authentication
Returns the remaining credit balance of your team. Credits belong to the team owner, so every team member gets the same balance.
On a usage-based plan (Individual, Team, Scale), has_capacity tells whether your team can still
run requests. On a credit-based plan it is null: rely on credits instead.
Example request:
curl --request GET \
--get "https://app.findymail.com/api/credits?type=finder" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}"const url = new URL(
"https://app.findymail.com/api/credits"
);
const params = {
"type": "finder",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200, Credit-based plan):
{
"credits": 150,
"email": "[email protected]",
"has_capacity": null,
"verifier_credits": 100
}
Example response (200, Usage-based plan):
{
"credits": 0,
"email": "[email protected]",
"has_capacity": true,
"verifier_credits": 0
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
credits
integer
Remaining credits of the requested type.
verifier_credits
integer
Remaining verifier credits. Absent when your account uses a single balance for finder and verifier requests.
has_capacity
boolean|null
Usage-based plans only: true while your team can still run requests, false once it has reached its plan usage limit. null on credit-based plans.
email
string
Email of the authenticated user.
Get usage
requires authentication
Returns the daily or monthly credit usage of the authenticated user.
Groups by day for periods shorter than 2 months, otherwise groups by month.
Example request:
curl --request GET \
--get "https://app.findymail.com/api/credits/report/summary?from=2025-01-01&to=2025-01-31" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}"const url = new URL(
"https://app.findymail.com/api/credits/report/summary"
);
const params = {
"from": "2025-01-01",
"to": "2025-01-31",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"from": "2025-01-01",
"to": "2025-01-31",
"total": {
"finder": 250,
"verifier": 180
},
"items": [
{
"date": "2025-01-01",
"finder": 10,
"verifier": 5
},
{
"date": "2025-01-02",
"finder": 15,
"verifier": 8
},
{
"date": "2025-01-03",
"finder": 0,
"verifier": 0
}
]
}
Example response (422):
{
"message": "The from field must be a valid date.",
"errors": {
"from": [
"The from field must be a valid date."
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get team usage
requires authentication
Returns a summary of credit usage of all team members within a specific date range.
Only team owners can access this endpoint.
Example request:
curl --request GET \
--get "https://app.findymail.com/api/credits/report/team-summary?from=2025-01-01&to=2025-01-31" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}"const url = new URL(
"https://app.findymail.com/api/credits/report/team-summary"
);
const params = {
"from": "2025-01-01",
"to": "2025-01-31",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"from": "2025-01-01",
"to": "2025-01-31",
"total": {
"finder": 150,
"verifier": 75
},
"members": [
{
"name": "John Doe",
"finder": 100,
"verifier": 50
},
{
"name": "Jane Smith",
"finder": 50,
"verifier": 25
}
]
}
Example response (403):
{
"error": "You must be the team owner to access this endpoint"
}
Example response (422):
{
"message": "The from field must be a valid date.",
"errors": {
"from": [
"The from field must be a valid date."
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.