API reference
One endpoint. Give us a name and a company domain, get a verified work email. You are charged one credit when we find one, and nothing when we don't.
| Base URL | https://dowsely.com |
| Endpoint | POST /api/v1/enrich |
| Auth | Authorization: Bearer as_live_... |
| Content type | application/json |
Quickstart
export DOWSELY_KEY="as_live_..." # create one at https://dowsely.com/account
curl https://dowsely.com/api/v1/enrich \
-H "Authorization: Bearer $DOWSELY_KEY" \
-H "Content-Type: application/json" \
-d '{"first_name":"Dana","last_name":"Whitfield","domain":"northwind.com"}'A hit looks like this:
{"status":"found","work_email":"dana.whitfield@northwind.com","credits_charged":1}Run it again and you get the same answer, faster and at the same price. The response is byte-identical — we don't report where the address came from.
Getting a key
- Register at
https://dowsely.com/registerand sign in. - Go to your account and create an API key.
- Copy it immediately — we store only a hash, so it is shown exactly once.
Revoking a key takes effect on the very next request; there is no cache to wait out. Both header forms below work, because rejecting a valid key over a missing prefix would be a support ticket with no upside:
-H "Authorization: Bearer as_live_..."
-H "Authorization: as_live_..."Billing
Credits are deducted only when we return a verified address.
| Outcome | Credits |
|---|---|
| Work email found | 1 |
| Nothing found | 0 |
| Any error (401 / 402 / 422 / 451 / 5xx) | 0 |
Every verified work email costs one credit. We keep results we have already found, which is why a repeat lookup is fast, but it costs the same as the first one and the response does not distinguish the two — you asked one question and got one verified answer.
Every response carries credits_charged. Reconcile against that rather than inferring cost from the status code.
Personal email and mobile phone are priced in the credit model (3 and 10) but not returned yet — see below.
Input: what counts as enough
You need either a last name plus a company domain, or a LinkedIn URL. A first name alone, or a name with no company, is rejected with 422 rather than burned as a coin-flip lookup.
| Field | Required | Notes |
|---|---|---|
first_name | No | Improves the hit rate substantially. |
last_name | With domain | |
domain | With last_name | Company domain, not the person's email domain. |
linkedin_url | Alternative | Sufficient on its own. |
Input is normalized for you: the scheme, www., a trailing path, casing, and stray whitespace are all stripped before we build a cache key, so these are one lookup and not four:
"https://www.Acme.com/careers" -> "acme.com"
" ACME.COM " -> "acme.com"Every response, verbatim
| Status | Body | Charged |
|---|---|---|
200 | {"status":"found","work_email":"...","credits_charged":1} | 1 |
200 | {"status":"not_found","credits_charged":0} | 0 |
401 | {"error":"unauthorized"} | 0 |
402 | {"error":"insufficient_credits"} | 0 |
422 | {"error":"insufficient_input"} | 0 |
451 | {"error":"suppressed"} | 0 |
502 | {"error":"vendor_error"} | 0 |
503 | {"error":"vendor_rate_limited"} | 0 |
504 | {"error":"vendor_timeout"} | 0 |
not_found is a 200, not a 404: the request succeeded, the answer is "nobody matches". A 451 means that person has asked us to delete their data and we will never return them, from cache or from a vendor.
Timeouts and batching
One contact per request. A lookup normally answers in a few seconds; set a client timeout of about 30 seconds and treat 504 as retryable — a timeout is never charged.
There is no bulk endpoint yet. Run requests concurrently instead:
# Read a CSV of first,last,domain and run 5 lookups at a time.
while IFS=, read -r first last domain; do
while [ "$(jobs -r | wc -l)" -ge 5 ]; do wait -n; done
(
curl -s --max-time 30 https://dowsely.com/api/v1/enrich \
-H "Authorization: Bearer $DOWSELY_KEY" \
-H "Content-Type: application/json" \
-d "{\"first_name\":\"$first\",\"last_name\":\"$last\",\"domain\":\"$domain\"}"
echo
) &
done < contacts.csv
waitNot implemented yet
Listed so you can rule us out now rather than after paying:
- Personal emails and mobile numbers. Priced in the credit model, not returned. Mobile resale needs a vendor supply agreement, not an engineering change.
- A bulk endpoint. One contact per request; run them concurrently as above.
- CRM integrations. No HubSpot or Salesforce sync. It is an API you call from your own pipeline.
- Webhooks for async results. Every lookup is synchronous.
Data-subject requests
Anyone whose contact data we hold can have it deleted at /privacy/delete, without an account and free of charge. We confirm by emailing the address being deleted, purge it, and add a hashed entry to a suppression list so it is never re-acquired.
Once suppressed, that person returns 451 for every caller, forever. This is not reversible by us.