# Enrow API - Full Reference for LLMs Base URL: https://api.enrow.io ## Authentication All endpoints require an API key passed as a header: - Header: `x-api-key: YOUR_API_KEY` - The API is available to customers with an active subscription or pay-as-you-go credits. ## Common Error Responses These errors apply to ALL POST endpoints: | Code | Messages | |------|----------| | 401 | `No apikey found in the x-api-key headers` | | 401 | `This apikey is not valid` | | 402 | `Insufficient credits` | | 429 | Rate limit exceeded (10 req/s per API key on POST endpoints) | Error body shapes: - Most errors return `{"message": "..."}`. - Insufficient-credit (402) on SINGLE endpoints returns `{"reason": "...", "success": false}`; on BULK endpoints `{"message": "..."}`. - Responses never include `error`, `status`, or `retry_after` fields. - The API never returns 404. An unknown or expired ID returns 500 (single endpoints) or 400 (bulk endpoints). --- # Email Finder - Find Single **POST** `https://api.enrow.io/email/find/single` Find a professional email address from a name and company. Asynchronous — returns a search ID, retrieve results via GET or webhook. **Credit cost:** 1 credit per email found ## Parameters | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | fullname | body | string | yes | The full name of the person | | company_domain | body | string | yes* | Company domain (e.g., "dundermifflin.com"). Multiple formats accepted. | | company_name | body | string | yes* | Company name (e.g., "Dunder Mifflin"). | | custom | body | object | no | Custom params returned as-is in GET response and webhook | | settings.webhook | body | string | no | HTTPS URL notified when search completes | | settings.country_code | body | string | no | ISO 3166 Alpha-2 (default: "US"). Relevant with company_name only. | | settings.retrieve_gender | body | boolean | no | Returns gender (male/female). Default: false. | | settings.retrieve_company_info | body | boolean | no | Returns additional company info. Currently only effective when country_code is "FR". Default: false. | *Either company_domain or company_name is required. ## Responses ### 200 Search initiated ```json { "message": "Single search operating", "id": "0cf517bc-16e8-45bc-b967-ab9116b3c804", "credits_used": 1 } ``` ### 400 Bad Request ```json {"message": "missing fullname"} {"message": "both company_domain and company_name are absent, input payload needs at least one of them"} {"message": "invalid JSON input"} ``` ### 402 Insufficient credits ```json {"reason": "Insufficient credits", "success": false} ``` --- # Email Finder - Get Single Result **GET** `https://api.enrow.io/email/find/single?id={id}` Retrieve the result of a previously launched email search. ## Parameters | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | id | query | string | yes | The search ID returned from the POST request | ## Responses ### 200 Search completed ```json { "email": "dwight.schrute@dundermifflin.com", "custom": {"external_id": "do4eIF8jF40x!", "partition_number": 2}, "info": { "company_domain": "dundermifflin.com", "company_name": "Dunder Mifflin", "fullname": "Dwight Schrute", "firstname": "dwight", "lastname": "schrute", "gender": "male", "companyInfo": {} }, "qualification": "valid" } ``` | Field | Description | |-------|-------------| | qualification | "valid" (email found) or "invalid" (email not found). Binary — no probabilistic categories. | | info.company_domain | Company domain | | info.company_name | Company name, when provided/derived | | info.fullname | Full name as provided in the request | | info.firstname | First name | | info.lastname | Last name | | info.gender | "male" or "female" — only present if `retrieve_gender` was set to `true` | | info.companyInfo | Additional company data, when available | | custom | Custom object passed in original request, returned as-is | ### 202 Search ongoing ```json {"qualification": "ongoing"} ``` ### Errors - 400 `{"message": "The single search id is missing in the URL query string"}` — id missing. - 500 `{"message": "Could not retrieve single search results"}` — unknown/expired id. (No 404.) --- # Email Finder - Find Bulk **POST** `https://api.enrow.io/email/find/bulk` Run multiple email searches in parallel. Up to 5,000 per batch. **Credit cost:** 1 credit per email found (per item) ## Parameters | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | searches | body | array | yes | Array of search objects | | searches[].fullname | body | string | yes | The person's full name | | searches[].company_domain | body | string | yes* | Company domain | | searches[].company_name | body | string | yes* | Company name | | searches[].custom | body | string \| object | no | Custom value returned per-result | | custom | body | object | no | Batch-level custom params, returned in GET response under `general.custom` | | settings.country_code | body | string | no | ISO 3166 Alpha-2 (default: "US") | | settings.webhook | body | string | no | HTTPS URL notified when batch completes | | settings.retrieve_gender | body | boolean | no | Returns gender. Default: false. | | settings.retrieve_company_info | body | boolean | no | Returns company info (only effective when country_code is "FR"). Default: false. | *Either company_domain or company_name is required per search. ### 201 Bulk search started ```json { "message": "Bulk search operating", "id": "0cf517bc-16e8-45bc-b967-ab9116b3c804", "credits_used": 3, "estimated_duration": 1 } ``` ### 400 Bad Request ```json {"message": "Missing payload"} {"message": "Missing searches payload"} {"message": "Too many searches. Limit is currently at 5000 per batch."} {"message": "Error while parsing payload"} ``` ### 402 Insufficient credits ```json {"message": "..."} ``` --- # Email Finder - Get Bulk Results **GET** `https://api.enrow.io/email/find/bulk?id={id}` Retrieve results of a bulk email search. ## Parameters | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | id | query | string | yes | The batch ID returned from the POST request | ### 200 Search completed ```json { "general": {"id": "...", "status": "completed", "custom": {}}, "stats": { "finished": 3, "requested": 3, "valid": 2, "credits_cost": {"initial": 3, "refunded": 1, "final": 2} }, "results": [ { "index": "0", "qualification": "valid", "email": "dwight.schrute@dundermifflin.com", "info": {"domain": "dundermifflin.com", "firstname": "Dwight", "lastname": "Schrute", "gender": "male", "companyInfo": {}}, "raw_params": {"company_domain": "dundermifflin.com", "fullname": "Dwight Schrute"}, "custom": "lead_001" } ] } ``` | Field | Description | |-------|-------------| | general.status | "completed", "ongoing", or "failed" | | general.custom | Batch-level custom object passed in original request | | stats.credits_cost | Object with initial, refunded, final breakdown | | results[].info | Only present for valid results: domain, firstname (capitalized), lastname (capitalized), gender, companyInfo. No `fullname`. | | results[].custom | Per-search custom value passed in original request | | results[].raw_params | Original search parameters | ### 200 Search ongoing ```json {"general": {"id": "...", "status": "ongoing"}, "stats": {"requested": 3, "finished": 2}} ``` ### 400 Not found ```json {"message": "Could not retrieve bulk search results"} ``` --- # Email Verifier - Verify Single **POST** `https://api.enrow.io/email/verify/single` Verify a single email address. Determinist verification — works on catch-all domains, no debouncer needed. **Credit cost:** 0.25 credits per check ## Parameters | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | email | body | string | yes | Email address to verify | | custom | body | object | no | Custom params returned in results | | settings.webhook | body | string | no | HTTPS URL notified when verification completes | ### 200 Verification initiated ```json { "message": "Single verification operating", "id": "0cf517bc-16e8-45bc-b967-ab9116b3c804", "credits_used": 0.25, "credits": {"amount": 0.25, "source": "sub", "split": {"fromPaygo": 0, "fromSub": 0.25}} } ``` `credits.source` is one of `sub`, `paygo`, or `mixed`. ### 400 Bad Request ```json {"message": "invalid email format"} {"message": "invalid JSON input"} ``` ### 402 Insufficient credits ```json {"reason": "Insufficient credits", "success": false} ``` --- # Email Verifier - Get Single Verification **GET** `https://api.enrow.io/email/verify/single?id={id}` ## Parameters | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | id | query | string | yes | The verification ID returned from the POST request | ### 200 Verification finished ```json { "email": "pam.beesly@dundermifflin.com", "custom": {"external_id": "do4eIF8jF40x!"}, "qualification": "valid" } ``` qualification: "valid" (deliverable) or "invalid" (not deliverable). ### 202 Verification ongoing ```json {"qualification": "ongoing"} ``` ### Errors - 400 `{"message": "The single verif id is missing in the URL query string"}` — id missing. - 500 `{"message": "Could not retrieve single verification results"}` — unknown/expired id. (No 404.) --- # Email Verifier - Verify Bulk **POST** `https://api.enrow.io/email/verify/bulk` Verify multiple emails in batch. Up to 5,000 per batch. **Credit cost:** 0.25 credits per check (per item) ## Parameters | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | verifications | body | array of strings | yes | Email addresses to verify | | custom | body | object | no | Custom params returned in GET response under `general.custom` | | settings.webhook | body | string | no | HTTPS URL notified when batch completes | ### 201 Bulk verification started ```json { "message": "Bulk verification operating", "id": "0cf517bc-16e8-45bc-b967-ab9116b3c804", "credits_used": 0.5, "estimated_duration": 1, "credits": {"amount": 0.5, "source": "sub", "split": {"fromPaygo": 0, "fromSub": 0.5}} } ``` `credits.source` is one of `sub`, `paygo`, or `mixed`. ### 400 Bad Request ```json {"message": "Missing payload"} {"message": "At least 1 verification must be present in the payload"} {"message": "Too many verifications. Limit is currently at 5000 per batch."} ``` ### 402 Insufficient credits ```json {"message": "..."} ``` --- # Email Verifier - Get Bulk Verifications **GET** `https://api.enrow.io/email/verify/bulk?id={id}` ## Parameters | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | id | query | string | yes | The batch ID returned from the POST request | ### 200 Verification completed ```json { "general": {"id": "9d4fa0ed-f76b-409f-bee4-d5468ebda70e", "status": "completed", "custom": {}}, "results": [ {"email": "pam.beesly@dundermifflin.com", "index": "195f87c6-376e-4eca-9861-f92935413b0c", "qualification": "valid"}, {"email": "angela.martin@dundermifflin.com", "index": "662784ae-3722-47af-b056-7554e013f73b", "qualification": "valid"} ], "stats": {"credits_cost": 0.5, "requested": 2, "valid": 2} } ``` - `general.status`: "completed", "ongoing", or "failed". `general.custom` is the batch-level custom. - Each result contains only `email`, `index`, `qualification` (no per-result `custom`). ### 200 Verification ongoing ```json {"general": {"id": "...", "status": "ongoing"}, "stats": {"finished": 1, "requested": 2}} ``` ### 400 Not found ```json {"message": "Could not retrieve bulk verification results"} ``` --- # Phone Finder - Find Single **POST** `https://api.enrow.io/phone/single` Find a phone number. Asynchronous. LinkedIn URL recommended — takes precedence if both options provided. **Credit cost:** 40 credits per phone found (default; 50 with legacy plans) Requires phone-finder access: accounts without it receive 401 `This account is not allowed to use the phone search feature`. ## Parameters Option 1 (recommended): | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | linkedin_url | body | string | yes* | LinkedIn profile URL. Takes precedence if both options provided. | Option 2: | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | firstname | body | string | yes* | First name | | lastname | body | string | yes* | Last name | | company_domain | body | string | yes* | Company domain | | company_name | body | string | yes* | Company name (alternative) | Additional: | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | custom | body | string | no | Custom value returned in results | | settings.webhook | body | string | no | HTTPS URL notified when search completes | ### 201 Single search created ```json { "credits_used": 40, "id": "94cbc13b-7d77-4f41-83f0-60106daa7182", "message": "Single search operating", "credits": {"amount": 40, "source": "sub", "split": {"fromPaygo": 0, "fromSub": 40}} } ``` `credits.source` is one of `sub`, `paygo`, or `mixed`. ### 400 Bad Request ```json {"message": "Invalid linkedin_url format"} ``` ### 401 Feature not enabled ```json {"message": "This account is not allowed to use the phone search feature"} ``` ### 402 Insufficient credits ```json {"reason": "Insufficient credits", "success": false} ``` --- # Phone Finder - Get Single Result **GET** `https://api.enrow.io/phone/single?id={search_id}` ## Parameters | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | id | query | string | yes | The search ID returned from the POST request | ### 200 Number found ```json { "params": {"linkedin_url": "https://www.linkedin.com/in/michael-scott/"}, "custom": "#u84hde941Jdx", "number": "+15705551234", "country": "US", "qualification": "found" } ``` | Field | Description | |-------|-------------| | qualification | "found", "not_found", or "ongoing" | | number | Phone number, always `+`-prefixed (only when "found") | | country | ISO 3166-1 Alpha-2 (only when "found") | | params | Original search parameters | | custom | Custom value passed in original request | ### 200 Number not found Structure has `qualification: "not_found"` with `params` (no number/country). Suppressed contacts return only `{"qualification": "not_found"}`. ### 202 Search ongoing ```json {"qualification": "ongoing"} ``` ### Errors - 400 `{"message": "Missing id in the query params"}` — id missing. - 500 `{"message": "Could not retrieve single search results"}` — unknown/expired id. (No 404.) --- # Phone Finder - Find Bulk **POST** `https://api.enrow.io/phone/bulk` Search for multiple phone numbers. Up to 3,000 per batch. **Credit cost:** 40 credits per phone found (default; 50 with legacy plans) Requires phone-finder access (401 if not enabled). ## Parameters | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | searches | body | array | yes | Array of search objects | | searches[].linkedin_url | body | string | yes* | LinkedIn profile URL (recommended) | | searches[].firstname | body | string | yes* | First name (option 2) | | searches[].lastname | body | string | yes* | Last name (option 2) | | searches[].company_domain | body | string | yes* | Company domain (option 2) | | searches[].company_name | body | string | yes* | Company name (option 2, alternative) | | searches[].custom | body | string | no | Custom value returned in results | | custom | body | object | no | Batch-level custom params, returned in GET response under `general.custom` | | settings.webhook | body | string | no | HTTPS URL notified when batch completes | ### 201 Bulk search created ```json { "credits_used": 80, "estimated_duration": 1, "id": "e3b61122-d6a6-4ea7-b331-9b734682a76a", "message": "Bulk search operating", "credits": {"amount": 80, "source": "sub", "split": {"fromPaygo": 0, "fromSub": 80}} } ``` `credits.source` is one of `sub`, `paygo`, or `mixed`. ### 400 Bad Request ```json {"message": "At least 1 phone search must be present in the payload"} {"message": "Missing payload"} {"message": "Too many searches. Limit is currently at 3000 per batch."} ``` ### 401 Feature not enabled ```json {"message": "This account is not allowed to use the phone search feature"} ``` ### 402 Insufficient credits ```json {"message": "..."} ``` --- # Phone Finder - Get Bulk Results **GET** `https://api.enrow.io/phone/bulk?id={batch_id}` ## Parameters | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | id | query | string | yes | The batch ID returned from the POST request | ### 200 Search finished ```json { "general": {"id": "e3b61122-d6a6-4ea7-b331-9b734682a76a", "status": "completed", "custom": {}}, "results": [ {"country": "US", "index": 0, "number": "+15705551234", "params": {"linkedin_url": "https://www.linkedin.com/in/michael-scott"}, "qualification": "found"}, {"country": "US", "index": 1, "number": "+15705555678", "params": {"linkedin_url": "https://www.linkedin.com/in/dwight-schrute"}, "qualification": "found"} ], "stats": {"credits_cost": 80, "credits_to_refund": 0, "found": 2, "requested": 2} } ``` - `general.status`: "completed", "ongoing", or "failed". - Completed `stats`: `credits_cost`, `credits_to_refund`, `found` (number of phones found — NOT `valid`), `requested`. - Suppressed contacts appear as `{"index": n, "params": {...}, "qualification": "not_found"}` (no number/country). ### 200 Search ongoing ```json {"general": {"id": "...", "status": "ongoing"}, "stats": {"finished": 0, "requested": 1}} ``` ### Errors - 400 `{"message": "Missing id in the query params"}` — id missing. - 400 `{"message": "Could not retrieve bulk search results"}` — unknown id. --- # Account Info **GET** `https://api.enrow.io/account/info` Retrieve credit balance and registered webhooks. No body payload needed. ## Parameters | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | (none) | — | — | — | Account info is retrieved from the API key in the header | ### 200 Success ```json { "credits": 36000, "webhooks": ["https://api.mysuperwebsite/api/webhook"] } ``` `credits` is a single number (total balance). `webhooks` is an array of URLs and may be absent if none are configured. ### 401 Unauthorized ```json {"message": "This apikey is not valid"} ``` --- # Webhooks Six event types: | Event | Trigger | Payload | |-------|---------|---------| | single_search_finished | Single email search done | Full result included | | bulk_search_finished | Bulk email search done | ID + credits only — use GET to fetch results | | verification_finished | Single verification done | Full result included | | bulk_verification_finished | Bulk verification done | ID + credits only — use GET to fetch results | | single_phone_search_finished | Single phone search done | Full result included | | bulk_phone_search_finished | Bulk phone search done | ID only — use GET to fetch results | Setup: pass webhook URL in `settings.webhook` per request, or configure globally at https://app.enrow.io/integrations --- # Credits | Endpoint | Cost | |----------|------| | Email Finder | 1 credit per email found | | Email Verifier | 0.25 credits per check | | Phone Finder | 40 credits per phone found (default; 50 with legacy plans) | POST responses for Email Verifier and Phone Finder include a `credits` object: `{amount, source (sub|paygo|mixed), split: {fromPaygo, fromSub}}`. Email Finder SINGLE GET responses include `fullname` in the `info` object; BULK GET results do not include `fullname` in `info` (they expose `domain`, `firstname`, `lastname`, `gender`, `companyInfo`). --- # Qualification System Binary results — no probabilistic categories. Either the result is good or it's not. - Email Finder: "valid" (found) or "invalid" (not found) - Email Verifier: "valid" (deliverable) or "invalid" (not deliverable) - Phone Finder: "found" or "not_found" - All endpoints: "ongoing" while processing - Bulk batch `status`: "ongoing", "completed", or "failed" Enrow verifies catch-all emails deterministically. No debouncer needed. --- # Rate Limits 10 requests/second per API key on all POST endpoints. GET endpoints are not rate limited. No `X-RateLimit-*` headers are returned. Increase available on request: api@enrow.io