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/campaigns | Campaigns with status, test mode, any automatic-pause reason, and headline numbers. |
GET /api/v1/campaigns/:id | One campaign: schedule, limits, tracking, sequence steps and numbers. |
POST /api/v1/campaigns/:id/pause | Stop sending; every lead keeps its place. |
POST /api/v1/campaigns/:id/resume | Start sending again (a paused or draft campaign). |
GET /api/v1/campaigns/:id/leads | Leads; filter with status and category; page with ?after=<next>. |
POST /api/v1/campaigns/:id/leads | Add up to 5,000 leads (below). |
GET /api/v1/replies | Replies, newest first; since, category, campaign_id, include_automatic; page with ?before=<next>. |
GET /api/v1/leads/:id | One lead and the whole conversation. |
GET /api/v1/blocklist | The 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.received | A person replied: reply.text, reply.category, reply.from. Not sent for out-of-office or bounces. |
coldemail.reply.category_changed | Someone recategorized a reply: from, to. |
coldemail.lead.opted_out | source: reply, unsubscribe_link, spam_report or sendgrid_unsubscribe. |
coldemail.lead.bounced | The address doesn't exist: source bounce_notice or sendgrid_bounce. |
coldemail.lead.completed | The sequence finished without a reply. |
coldemail.lead.meeting_booked | The person booked a meeting through your booking link (Calendly, Cal.com or similar). |
coldemail.campaign.paused | A 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.