Ravn docs
Getting started
Three ways in, all with the same tools and the same answers:
- MCP for Claude, Codex, Cursor and other agents:
https://api.askravn.com/mcp - CLI for scripts, CSVs and terminal agents:
npx ravn - REST for jobs and integrations:
POST https://api.askravn.com/v1/tools/{tool}
Agents can set themselves up. Paste this into yours:
Read https://askravn.com/llms.txt and follow its Getting started section. Then call get_account to confirm the connection.
Authentication
Every call sends Authorization: Bearer rw_live_…. Get a key on the home page, with npx ravn login, or headless:
curl -X POST https://api.askravn.com/v1/auth/start -d '{"email":"you@company.com"}'
curl -X POST https://api.askravn.com/v1/auth/verify -d '{"email":"you@company.com","code":"123456"}'
# → {"api_key": "rw_live_…"} shown once
A person has to receive the code, so an agent can't create an account on its own. Manage keys with GET /v1/keys, POST /v1/keys {"name"} and DELETE /v1/keys/{id} (up to 20 per account).
MCP server
Remote MCP over Streamable HTTP at https://api.askravn.com/mcp. The tools are the same as the REST tools below. It supports OAuth sign-in, so there's no key to copy:
- Claude (web, desktop, mobile): Settings → Connectors → Add custom connector → paste
https://api.askravn.com/mcp→ sign in with your email code → Allow. - Claude Code:
claude mcp add --transport http ravn https://api.askravn.com/mcp, then run/mcpand choose Authenticate. - Cursor, Windsurf and other MCP clients: add the URL; they open the same sign-in page.
Prefer an API key (CI, servers, scripts)? Send it as a header instead:
claude mcp add --transport http ravn https://api.askravn.com/mcp \ --scope user --header "Authorization: Bearer $RAVN_API_KEY"
Cursor (.cursor/mcp.json) and other clients:
{ "mcpServers": { "ravn": {
"url": "https://api.askravn.com/mcp",
"headers": { "Authorization": "Bearer rw_live_…" } } } }
CLI
npx ravn login # email code → key saved to ~/.config/ravn
npx ravn whoami # plan, usage this month, spending cap (free)
npx ravn cap 100 # monthly spending cap beyond the plan, in dollars (0 = stop at 10,000)
npx ravn tools # every tool and its cost
npx ravn keys add pdl # connect your People Data Labs key (or: twilio)
npx ravn validate_email --email jane@acme.com
npx ravn search_people --title "Head of Design" --company_domain linear.app --limit 5
npx ravn enrich leads.csv --tool validate_email --column Email --dry-run
npx ravn enrich leads.csv --tool search_business_email_by_name --map name=Name,company=Website --limit 10 --out sample.csv
npx ravn skill list # the skills library
npx ravn skill install --all # Claude skills → ~/.claude/skills
npx ravn audience leads.enriched.csv --column Email --format meta --only-valid
# SHA-256 ad audience, hashed locally, nothing uploaded
Key order: --api-key, RAVN_API_KEY, saved login. Output is JSON when piped and tables in a terminal; logs go to stderr. enrich keeps every original column, adds rw_* columns, saves progress every 25 rows and resumes where it stopped (--restart to start over). When the 5-hour window fills it waits for the reset unless you pass --no-wait. Exit codes: 0 ok · 1 error · 2 usage · 3 auth · 4 rate limited · 5 upgrade needed.
Responses
Every finished call returns HTTP 200 with the same shape. Branch on status, not the HTTP code.
{
"status": "ok", // or "not_found": a normal outcome, nothing charged
"results": { … }, // null when not_found
"metadata": {
"request_id": "req_…", "lookups_used": 1,
"fair_use": { "lookups_remaining_5h": 999, "lookups_reset_5h": "2026-11-03T20:00:00.000Z" }
}
}
Email verdicts carry status (valid, invalid, risky, unknown), a risk_score from A (send) to F (don't), a reason and the checks behind it. mailbox_checked: false means we proved the domain takes mail but did not test the mailbox itself; we never call that valid.
Errors
Errors are {"error": {"code", "message"}} with no results and no charge. Branch on error.code.
| HTTP | code | Meaning |
|---|---|---|
| 401 | unauthorized | Missing, wrong or revoked key |
| 403 | provider_key_required | People, company or carrier tool called with no provider key connected |
| 502 | provider_error | Your data provider rejected the key or returned an error |
| 404 | unknown_tool | No tool by that name (GET /v1/tools lists them) |
| 413 | too_large | Body over 1 MB |
| 422 | invalid_input | Input failed validation; message says which field |
| 429 | fair_use_exhausted, rate_limited | Free allowance used up or a burst limit; wait Retry-After seconds, or upgrade. spend_cap_reached: your monthly spending cap is hit; raise it with PUT /v1/billing/cap or ravn cap <dollars> |
| 503 | upstream_unavailable, provider_keys_unconfigured | A source is down (retry), or provider keys aren’t set up on the server yet |
| 500 | internal_error | Our fault; retry, or send a smaller request |
Limits
Every tool counts as one lookup. Free is 1,000 lookups to try. Ravn is $24 a month and includes 10,000 lookups a month; beyond that it is $1 per 1,000 lookups ($0.001 each), billed monthly, with a monthly spending cap you set (default $100 beyond the plan; $0 stops at 10,000). A miss gives the lookup back and is free. People, company and carrier tools (search_people, domain_to_company, reverse_email_lookup, phone_to_carrier and the like) run on your own provider account: connect a People Data Labs key (people and companies) or a Twilio key (carrier) with ravn keys add pdl or on the account page. Called without one, they return 403 provider_key_required. get_billing lists every tool.
Tools
All tools are POST /v1/tools/{name} with a JSON body. Machine-readable list with JSON Schemas: GET /v1/tools. Names follow search_, reverse_ and x_to_y; /api/v1/tools/{name} works too.
validate_email
Checks one email: syntax, domain and MX, disposable/role/free-provider flags, catch-all and (where enabled) the mailbox itself. Returns status valid|invalid|risky|unknown and a risk score A-F. (lookup)
emailstring, required
validate_emails
Checks up to 1,000 emails at once; one verdict per unique address. Use before sending to a list. (lookup)
emailsstring[], required
search_business_email_by_name
Finds a person's work email from their name and company domain. Learns the company's address pattern from its own website, then checks the best candidates. Charged only when found. (lookup)
namestringfirst_namestringlast_namestringcompanystring, required — Company domain or website URL, e.g. acme.com
verify_lead
Checks a whole lead in one call: verifies the email (or finds it from name + company), validates the phone, confirms the company website is live and reads it (socials, phones, team), and checks the person is listed there. Returns verdict good|review|bad with reasons. One lookup per check run. (lookup)
emailstringphonestringnamestringcompanystring — Company domain or website URL, e.g. acme.comcountrystring — ISO country for national phone numbers, default US
search_businesses
Searches Ravn's own directory of US and Canadian businesses by name, category, MCC/NAICS code, service offered, city, region, postcode or distance, with website, phones, generic role addresses and socials. Business data only — never named people. One lookup per business returned; misses are free. Page with next_cursor. (lookup)
querystring — Business name or part of itcategorystring | string[] — e.g. dentist, plumber, italian_restaurant, accountantcountrystringregionstring — State or province, e.g. TX or ONcitystringpostcodestring — Full or leading part, e.g. M5V or 787mccstring — Merchant category codenaicsstring — NAICS code or prefixservicestring — A service the business offers, e.g. "drain cleaning"nearobjecthas_emailbooleanhas_phonebooleanhas_websitebooleanlive_onlyboolean — Only businesses whose website we found livelimitinteger, default 25cursorstring
lookup_business
Every business in Ravn's directory at a domain or phone number (chains return each location), with generic role addresses and socials. Business data only — never named people. One lookup per call; misses are free. (lookup)
domainstring — Company domain or website URL, e.g. acme.comphonestring
scrape_website
Reads a company's own website (homepage plus its contact, about and team pages) and returns structured JSON: name, description, logo, address, public emails and phones, social profiles, named team members with titles, technologies used, and whether the site looks live. (lookup)
domainstring, required — Company domain or website URL, e.g. acme.com
ip_to_company
Returns the organisation that owns an IPv4 address, from public registry data. Works for company networks; home and mobile ISPs return not_found. (lookup)
ipstring, required
validate_phone
Checks a phone number: valid or not, E.164 format, country and number-plan line type (mobile, landline, VoIP, toll-free). Free of credits; use phone_to_carrier for a live carrier check. (lookup)
phonestring, requiredcountrystring — ISO country for national numbers, default US
phone_to_carrier
Live carrier lookup: the real line type (mobile, landline, fixed or non-fixed VoIP) and carrier name. Use to make sure a number is a real mobile before texting. (lookup + your Twilio key)
phonestring, requiredcountrystring
linkedin_to_mobile_phone
Returns a mobile number for a LinkedIn profile (single or up to 100). When carrier checks are on, only numbers confirmed as mobile are returned. (lookup + your PDL key)
linkedin_urlstringlinkedin_urlsstring[]
search_people
Searches people by title, company, domain, location, seniority, industry, department and company size. Lists mean OR within a field, AND across fields. Charged per profile returned. Page with next_cursor. (lookup + your PDL key)
querystringtitlestring | string[]companystring | string[]company_domainstring | string[]countrystring | string[]statestring | string[]citystring | string[]senioritystring | string[] — Intern, Entry, Senior, Manager, Director, VP, Head, C Suite, Owner, Partnerindustrystring | string[]departmentstring | string[]functional_areastring | string[]employee_rangestring | string[] — 1-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5001+exclude_company_domainstring[]exclude_countrystring[]exclude_statestring[]exclude_industrystring[]exclude_senioritystring[]exclude_employee_rangestring[]limitinteger, default 10cursorstring
search_companies
Searches companies by name, domain, industry, location and size. Charged per company returned. (lookup + your PDL key)
querystringdomainstring | string[]industrystring | string[]countrystring | string[]statestring | string[]employee_rangestring | string[]exclude_industrystring[]limitinteger, default 10cursorstring
domain_to_company
Full company profile from its domain: size, employee count, industry, founded, location, LinkedIn, NAICS. (lookup + your PDL key)
domainstring, required — Company domain or website URL, e.g. acme.com
search_business_profile_by_name
Full business profile (title, company, location, LinkedIn, verified work email) from a name and company. (lookup + your PDL key)
namestring, requiredcompanystring, required
search_linkedin_profile
Finds a person's LinkedIn profile URL from their name and company. (lookup + your PDL key)
namestring, requiredcompanystring, required
linkedin_to_best_email
Best available verified email for a LinkedIn profile: work email first, personal as fallback. (lookup + your PDL key)
linkedin_urlstringlinkedin_urlsstring[]
linkedin_to_business_email
Verified work email for a LinkedIn profile. (lookup + your PDL key)
linkedin_urlstringlinkedin_urlsstring[]
linkedin_to_personal_email_usa
Verified US personal email for a LinkedIn profile. (lookup + your PDL key)
linkedin_urlstringlinkedin_urlsstring[]
reverse_email_lookup
Full business profile from an email (single or up to 100). (lookup + your PDL key)
emailstringemailsstring[]
reverse_linkedin_lookup
Full business profile from a LinkedIn profile URL. (lookup + your PDL key)
linkedin_urlstring, required
email_to_linkedin
The LinkedIn profile URL behind an email. (lookup + your PDL key)
emailstring, required
get_account
Your account, plan, lookups used this billing period, your monthly spending cap, and which data-provider keys you have connected. Free. (free)
get_billing
Your plan, renewal date, usage and spending cap this period, and what each tool costs. Free. (free)
get_usage
Lookups per 5-hour window for the last N days (default 7). Free. (free)
daysinteger, default 7
Privacy
Anyone can opt out at askravn.com/privacy or with POST /v1/privacy/optout {"identifier": "email or phone"}. Opted-out people are never returned again, to anyone. You agree to use the data lawfully: no contacting people who opted out, no spam, and never for credit, employment, insurance or housing decisions. See the terms.