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 URLhttps://dowsely.com
EndpointPOST /api/v1/enrich
AuthAuthorization: Bearer as_live_...
Content typeapplication/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

  1. Register at https://dowsely.com/register and sign in.
  2. Go to your account and create an API key.
  3. 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.

OutcomeCredits
Work email found1
Nothing found0
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.

FieldRequiredNotes
first_nameNoImproves the hit rate substantially.
last_nameWith domain
domainWith last_nameCompany domain, not the person's email domain.
linkedin_urlAlternativeSufficient 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

StatusBodyCharged
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
wait

Not implemented yet

Listed so you can rule us out now rather than after paying:

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.