Autopilot API
Launch goal-driven outreach runs, read live progress, and pull full per-recipient delivery results — api.misar.io/reach/api/autopilot.
Autopilot turns a plain-language goal into a complete outreach run: it finds matching leads, drafts a campaign, queues the sends, and reports delivery as it happens. Queued sends are flushed by the campaign dispatcher, and delivery/open/click/bounce events flow back from MisarMail to the mail-events webhook.
Base URL: https://api.misar.io/reach
Start a run
/api/autopilot/startStarts a new Autopilot run from a goal description. Costs 1 autopilot credit. Returns immediately with a runId; the run executes asynchronously — poll run status or read run detail for progress.
Body parameters
goalstringrequiredPlain-language description of the outreach goal (10–2000 chars), e.g. "Find SaaS founders in India and invite them to a demo of our analytics product."
curl -X POST "https://api.misar.io/reach/api/autopilot/start" \
-H "Authorization: Bearer msr_your_key_here" \
-H "Content-Type: application/json" \
-d '{ "goal": "Find SaaS founders in India and invite them to a demo" }'{ "ok": true, "runId": "uuid" }{ "error": "Autopilot credit limit reached" }List runs
/api/autopilot/runsReturns the authenticated user's Autopilot runs, most recent first. Counters (messages_sent, replies_count) are derived live from the underlying sends, not a cached guess.
Response fields
runs[].statusstringOne of "running" | "completed" | "failed" | "paused" | "stopped". A run stays running until every queued send has been dispatched.
runs[].leads_foundnumberLeads matched and queued for this run.
runs[].messages_sentnumberSends that reached sent or beyond (sent|delivered|opened|clicked|replied) — never counts still-queued rows.
runs[].deals_countnumberAlways 0 for now — there is no CRM-deal linkage from Autopilot yet.
curl "https://api.misar.io/reach/api/autopilot/runs" \
-H "Authorization: Bearer msr_your_key_here"{
"runs": [
{
"id": "uuid",
"goal": "Find SaaS founders in India and invite them to a demo",
"status": "running",
"leads_found": 87,
"messages_sent": 41,
"replies_count": 0,
"deals_count": 0,
"campaign_id": "uuid",
"error": null,
"created_at": "2026-06-15T09:00:00Z"
}
]
}Get run status
/api/autopilot/:id/statusLightweight polling endpoint for an in-progress run — returns the run record including its live log array. Use this while a run is running; switch to run detail for the full results view.
curl "https://api.misar.io/reach/api/autopilot/RUN_ID/status" \
-H "Authorization: Bearer msr_your_key_here"{
"run": {
"id": "uuid",
"status": "running",
"leads_found": 87,
"messages_sent": 41,
"log": ["Plan ready — audience: SaaS founders", "87 leads queued for sending"]
}
}Stop a run
/api/autopilot/:id/statusStops a running run. Already-dispatched sends are not recalled; remaining queued sends will not be sent.
actionstringrequiredMust be "stop".
curl -X POST "https://api.misar.io/reach/api/autopilot/RUN_ID/status" \
-H "Authorization: Bearer msr_your_key_here" \
-H "Content-Type: application/json" \
-d '{ "action": "stop" }'{ "ok": true }Get run detail
/api/autopilot/:idFull results for one run: the run record, the AI-drafted campaign plan, the aggregate delivery funnel, and a paginated per-recipient list joined from the run's sends.
Query parameters
pagenumberquerydefault: 1Page of recipients to return.
limitnumberquerydefault: 50Recipients per page.
Response fields
planobjectThe campaign plan: subject_line, message_body, target_audience, industry, pain_point, keywords. May be null.
statsobjectAggregate funnel: total, queued, sent, delivered, opened, clicked, replied, bounced, failed, skipped.
recipients[]objectPer-recipient rows: id, email, name, status, sent_at, last_event_at, error.
curl "https://api.misar.io/reach/api/autopilot/RUN_ID?page=1&limit=50" \
-H "Authorization: Bearer msr_your_key_here"{
"ok": true,
"run": { "id": "uuid", "status": "completed", "leads_found": 87 },
"plan": {
"subject_line": "Quick idea for your team",
"message_body": "Hi {{first_name}}, …",
"target_audience": "SaaS founders in India"
},
"stats": {
"total": 87, "queued": 0, "sent": 87, "delivered": 80,
"opened": 0, "clicked": 12, "replied": 0, "bounced": 7, "failed": 0, "skipped": 0
},
"recipients": [
{
"id": "uuid",
"email": "[email protected]",
"name": "Priya Sharma",
"status": "delivered",
"sent_at": "2026-06-15T09:02:00Z",
"last_event_at": "2026-06-15T09:03:11Z",
"error": null
}
],
"pagination": { "page": 1, "limit": 50, "total": 87, "totalPages": 2 }
}{ "error": "Run not found" }Inbox-vs-spam placement is not tracked. MisarMail/Postal report delivery, opens, clicks, and bounces — not whether a message landed in the inbox or the spam folder. Open tracking additionally depends on the recipient loading images, and replied/deals_count stay 0 until a reply or CRM signal exists.
Dispatch & delivery
Autopilot only queues sends. A dispatcher flushes the queue to MisarMail:
/api/campaigns/runDispatches due queued email sends for running campaigns via the MisarMail send API. Authenticated by the x-cron-secret header matching the CRON_SECRET env var (fail-closed: if CRON_SECRET is unset the endpoint is disabled). Intended to be driven by a scheduled task every ~2–3 minutes.
curl -fsS -X POST "https://reach.misar.io/api/campaigns/run" \
-H "x-cron-secret: $CRON_SECRET"{ "processed": 41, "sent": 41, "failed": 0, "skipped": 0 }Delivery-events webhook
MisarMail forwards Postal delivery events for reach-originated sends to MisarReach, which advances each recipient's status. This is an internal service-to-service contract — not a public, user-callable endpoint.
/api/webhooks/mail-eventsReceives a single delivery event from MisarMail and advances the matching send. Status transitions are monotonic — an out-of-order or replayed event never regresses a more-advanced status, so the endpoint is idempotent without a dedup store.
Authentication. HMAC-signed, not API-key authed. The header x-reach-signature must equal hex(HMAC-SHA256(rawBody, REACH_EVENTS_WEBHOOK_SECRET)), where the secret is shared with MisarMail.
Body parameters
reach_send_idstringrequiredThe reach_campaign_sends row id this event applies to.
eventstringrequiredOne of "sent" | "delivered" | "clicked" | "bounced" (mapped from the Postal event by MisarMail).
recipientstringRecipient email address.
message_idstringPostal message id, for tracing.
curl -X POST "https://reach.misar.io/api/webhooks/mail-events" \
-H "Content-Type: application/json" \
-H "x-reach-signature: <hex hmac-sha256 of body>" \
-d '{ "reach_send_id": "uuid", "event": "delivered", "recipient": "[email protected]" }'{ "ok": true, "matched": true, "status": "delivered" }{ "ok": true, "matched": false }{ "error": "Invalid signature" }