API

Campaigns and prospects

A site with a lead form or a CRM sends people into an outreach campaign, learns what became of them, and reports how it ended on its side. The key needs May add prospects to campaigns; without it these requests answer 403.

Your campaigns

curl https://mail.example.com/api/v1/campaigns -H "Authorization: Bearer mr_..."
{
  "ok": true,
  "campaigns": [
    { "id": 3, "name": "Sales", "goal": "sales", "status": "running", "prospects": 13,
      "stages": ["Interest", "Meeting", "Proposal", "Deal"] }
  ]
}
FieldWhat it is
goallinks, sales, partners, press, hiring, reviews, winback or plain
statusdraft, running or paused
stagesThe campaign's pipeline, from first to last

Add prospects

curl https://mail.example.com/api/v1/prospects \
  -H "Authorization: Bearer mr_..." \
  -H "Content-Type: application/json" \
  -d '{
    "campaign": 3,
    "prospects": [
      { "email": "carol@example.com", "name": "Carol", "site": "example.com", "fields": { "plan": "pro" } }
    ]
  }'

Each prospect needs an email or a site. name and fields are optional; fields go into the campaign's emails. Up to 100 prospects per request.

{
  "ok": true, "campaign": 3,
  "added": 1, "updated": 0, "same": 0, "stopped": 0, "invalid": 0,
  "prospects": [ { "contact": "carol@example.com", "result": "added", "id": 30 } ]
}
ResultMeaning
addedA new prospect
updatedAlready in the campaign; the name and fields were updated
sameAlready in the campaign, nothing new
stoppedThe address is on your stop list and will not be written to
invalidNeither a valid address nor a site

Look up a prospect

curl "https://mail.example.com/api/v1/prospects?campaign=3&email=carol@example.com" \
  -H "Authorization: Bearer mr_..."

Pass email or site.

{
  "ok": true,
  "prospect": {
    "id": 30, "email": "carol@example.com", "name": "Carol", "site": "example.com",
    "status": "writing", "reason": "", "step": 1,
    "stage": 0, "stage_name": "", "value": 0,
    "reply": "", "replied_at": null,
    "next_at": "2026-10-20T09:00:00Z", "closed_at": null
  }
}
FieldWhat it is
statusnew, ready, writing (the sequence is under way), hold, later, replied, agreed, placed (the link is up, in link campaigns) or lost
reasonWhy it is in that state, for example why it was lost
stepHow many steps of the sequence went out
stage, stage_nameWhere it is in the pipeline
valueThe deal's value you reported
reply, replied_atThe kind of reply and when it came
next_atWhen the next step goes out
closed_atWhen it was won or lost

Times are in UTC.

Report the outcome

When the conversation moved to your side, tell the campaign, so it stops writing and counts the result.

curl https://mail.example.com/api/v1/prospects/state \
  -H "Authorization: Bearer mr_..." \
  -H "Content-Type: application/json" \
  -d '{ "campaign": 3, "email": "carol@example.com", "state": "agreed", "value": 1200 }'
stateWhat it does
repliedThe person answered on your side: the sequence stops. Only after a step went out
agreedWon
lostLost; add reason: declined, price, timing, competitor, no_need, no_budget or other
stopNever write to this address again: it goes on your stop list

value sets the deal's value, with or without state. The answer is the prospect, as in the lookup. A state that does not apply right now, for example replied before anything was sent, answers 409.