Cold Email API

Read campaigns, results and replies; add leads; pause and resume; manage the blocklist. Base URL: https://coldemail.doctorrebrand.com

Authentication

Send Authorization: Bearer <personal access token> — create one at API tokens. Every call acts on the organization currently selected for that person. Errors are { "error": { "code": "…", "message": "…" } }.

Endpoints

GET /api/v1/campaignsCampaigns with status, test mode, any automatic-pause reason, and headline numbers.
GET /api/v1/campaigns/:idOne campaign: schedule, limits, tracking, sequence steps and numbers.
POST /api/v1/campaigns/:id/pauseStop sending; every lead keeps its place.
POST /api/v1/campaigns/:id/resumeStart sending again (a paused or draft campaign).
GET /api/v1/campaigns/:id/leadsLeads; filter with status and category; page with ?after=<next>.
POST /api/v1/campaigns/:id/leadsAdd up to 5,000 leads (below).
GET /api/v1/repliesReplies, newest first; since, category, campaign_id, include_automatic; page with ?before=<next>.
GET /api/v1/leads/:idOne lead and the whole conversation.
GET /api/v1/blocklistThe organization's do-not-mail list; ?q= to search.
POST /api/v1/blocklist{ "entries": ["jane@acme.com", "competitor.com"], "note": "…" }

Adding leads

curl -X POST https://coldemail.doctorrebrand.com/api/v1/campaigns/<id>/leads \
  -H "Authorization: Bearer …" -H "Content-Type: application/json" \
  -d '{"leads":[{"email":"jane@acme.com","first_name":"Jane","company":"Acme","variables":{"city":"Tampa"}}],"tags":["q4-list"]}'

201 {"added":1,"skipped":{"invalid":0,"duplicates":0,"blocklisted":0,"global_bounce_or_spam":0,"disposable":0,
     "generic":0,"no_mail_domain":0,"already_in_campaign":0},"in_other_campaigns":0}

The same checks as an import: the blocklist, the global bounce and spam-report lists, disposable addresses, generic addresses (skip_generic, default on), domains that can't receive mail (skip_no_mail, default on), and people in another active campaign (skip_other_campaigns, default off). Any variables become {{placeholders}} in the emails.

Reply categories

interested, meeting_request, information_request, not_interested, do_not_contact, out_of_office, wrong_person, bounce, other. Opt-outs are decided by rules, not AI; people can recategorize in the inbox.

Webhook events

Add an endpoint under Developers → Webhooks and subscribe to any of these. Each POST is signed (X-AMC-Signature: t=…,v1=…, HMAC-SHA256 of t.bodywith your endpoint's secret) and retried with backoff. The body is { id, type, createdAt, data }; data carries lead (id, email, names, company, status, category, variables), campaign (id, name) and occurred_at, plus:

coldemail.reply.receivedA person replied: reply.text, reply.category, reply.from. Not sent for out-of-office or bounces.
coldemail.reply.category_changedSomeone recategorized a reply: from, to.
coldemail.lead.opted_outsource: reply, unsubscribe_link, spam_report or sendgrid_unsubscribe.
coldemail.lead.bouncedThe address doesn't exist: source bounce_notice or sendgrid_bounce.
coldemail.lead.completedThe sequence finished without a reply.
coldemail.lead.meeting_bookedThe person booked a meeting through your booking link (Calendly, Cal.com or similar).
coldemail.campaign.pausedA campaign paused itself: reason.

From Claude or ChatGPT

The MCP server wraps these as coldemail_campaigns, coldemail_campaign, coldemail_replies, coldemail_pause_campaign, coldemail_resume_campaign, coldemail_add_leads and coldemail_block.