Business· Help center

Help center › Importing & exporting

How to use the cold email API

Look up the decision-maker for any website, find and keep leads, run campaigns and answer replies from your own code, with an API key. Nothing reaches anyone without your yes in Reviews.

Updated 2026-10-31

The cold email API lets your own code, or your developer's, use the same services as the Cold email page. Make a key under Settings → Integrations → API keys (see how to read your data with an API key) and tick what it may do:

  • Leads and lookups: look up websites, find businesses, keep or pass on what was found, read your credits and usage.
  • Cold campaigns: make and change campaigns, import your list, have Otto write the emails, ask to start, pause, resume or cancel. Also your Do not contact list, and the state of your sending addresses, mailboxes and domains.
  • Cold email replies: read the sorted replies and answer them.

Every route, with what it takes and gives back, is in the API reference.

Send each request to your Otto site under /hooks/api/v1/, with the header Authorization: Bearer followed by the key, and JSON in the body.

Look up a website

POST /hooks/api/v1/lookup with {"website": "acmeplumbing.com", "who": "owner"}. who can be owner, marketing, sales or operations. The answer has the person and their title, the email address, whether it is a confirmed mailbox, the tools and buying signals their site shows, a LinkedIn link when their site has one, and how many credits you have left.

Lookups are free; a website you looked up before answers from the first time. There is a daily limit on new lookups, the same as for finding businesses.

For many at once, POST /hooks/api/v1/lookups with {"websites": [...], "who": "owner"} (up to 100). Otto works through them in the background; GET /hooks/api/v1/lookups/{id} shows the answers so far.

GET /hooks/api/v1/credits shows how many credits you have, and how many emails used them.

Find and keep leads

  1. POST /hooks/api/v1/describe with {"text": "roofers in Ohio that are hiring"} turns a sentence into the finder's filters.
  2. POST /hooks/api/v1/campaigns/{id}/find with the filters (niche, area, count, who, uses, not_uses, signals, min_team, keywords, no_chains) starts a search. keywords is up to five words or phrases; a business is kept when its website uses at least one.
  3. GET /hooks/api/v1/campaigns/{id}/found?status=preview lists what was found, addresses hidden.
  4. POST /hooks/api/v1/campaigns/{id}/keep with {"ids": [...]} or {"all": true} keeps them (free), and /discard passes on them.

Finding, keeping and passing on work only while the campaign is a draft.

Run a campaign

  • GET or POST /hooks/api/v1/campaigns, and GET or PATCH /hooks/api/v1/campaigns/{id}. A draft's name, pitch, steps, senders, writer, guide, signer, ab (a test of 2 to 4 versions) and options (sending days and hours, a daily limit, a start date, and whether a reply stops the whole company) can be changed.
  • POST /hooks/api/v1/campaigns/{id}/import with {"csv": "..."}.
  • POST /hooks/api/v1/campaigns/{id}/write has Otto write every business its own emails.
  • POST /hooks/api/v1/campaigns/{id}/start with the fingerprint from the campaign as you last read it. This does not send: it puts the campaign's one approval in Reviews, and a person approves it there. A key can never approve anything.
  • POST /hooks/api/v1/campaigns/{id}/pause, /resume or /cancel.

Replies

  • GET /hooks/api/v1/replies?label=interested&state=open lists the sorted replies with Otto's drafted answers. state can be open, answered, done or all.
  • POST /hooks/api/v1/replies/{id}/answer with {"body": "..."} sends an answer. It waits in Reviews unless you set answering cold email replies to Auto.

Be told instead of asking

Rather than asking again and again, your system can be told the moment a reply arrives, a lead is kept or a campaign starts or finishes. See how to get cold email events with webhooks.

Your code can also add its own webhook with the key, the way Zapier does:

  • POST /hooks/api/v1/hooks with {"url": "https://...", "event": "reply.received"} adds one. The key needs the tick for that event: Cold email replies for reply.received and reply.sorted, Leads and lookups for lead.kept, Cold campaigns for campaign.started and campaign.finished. The address is checked the same way as on the Webhooks page, and the answer includes the secret, once.
  • GET /hooks/api/v1/hooks lists the webhooks this key added, and DELETE /hooks/api/v1/hooks/{id} removes one. A key can only remove webhooks it added.
  • GET /hooks/api/v1/hooks/samples/{event} shows the last few messages of that event, or one example marked "sample": true when there have been none yet.

AI assistants and Zapier

The same key also works with AI assistants such as Claude and ChatGPT, through Otto's MCP address: see how to connect Otto to AI assistants with MCP. For Zapier, see how to connect Otto to Zapier.

Limits

Each key does only what was ticked, at most 60 requests a minute (the API, MCP and webhook requests together), and every use is listed under Recent uses. Errors come back as JSON with a detail sentence saying what to do.