Examples use fictional data. Every company, person, address and count in them is invented, and their domains use the reserved .example TLD.
Autopilot
Campaigns
A campaign is a target definition plus a set of instructions. The agents pick the leads, write each email individually and follow up until someone answers.
13 endpoints
- GET
/v1/campaigns - POST
/v1/campaigns - GET
/v1/campaigns/{campaign_id} - PATCH
/v1/campaigns/{campaign_id} - POST
/v1/campaigns/{campaign_id}/start - POST
/v1/campaigns/{campaign_id}/pause - POST
/v1/campaigns/{campaign_id}/stop - GET
/v1/campaigns/{campaign_id}/stats - GET
/v1/campaigns/{campaign_id}/sequence - PUT
/v1/campaigns/{campaign_id}/sequence - POST
/v1/campaigns/{campaign_id}/leads/generate - POST
/v1/campaigns/{campaign_id}/leads/import - POST
/v1/campaigns/{campaign_id}/preview
/v1/campaignsList campaigns
Every campaign with its live counters embedded, so a dashboard needs one call rather than one per row.
Query parameters
| Field | Type | Description |
|---|---|---|
| status | string | draft, queued, running, paused, scaling, stopped or completed. |
curl "https://beamro.com/api/v1/campaigns?status=running" \
-H "x-api-key: $SALVO_API_KEY"{
"rows": [
{
"id": "cmp_1t7k4v9m2q0b6x3n8w",
"org_id": "org_4k1p8w2ne6ts0ybc7j",
"project_id": "prj_8w3k1n6v0q4z7m2b5d",
"icp_id": "icp_2q7v4m9x1k6b0n3t8p",
"name": "New England venues · autumn",
"status": "running",
"daily_cap": 120,
"sending_window": {
"tz": "America/New_York",
"days": [
1,
2,
3,
4,
5
],
"start": "08:30",
"end": "16:30"
},
"sequence_id": "seq_9m2x5k8v1q4b7t0n3w",
"autopilot": true,
"stats": {
"leads": 1840,
"queued": 402,
"sent": 1438,
"delivered": 1398,
"opened": 641,
"replied": 96,
"interested": 34,
"meetings": 14,
"bounced": 40,
"unsubscribed": 8,
"spend_cents": 4314,
"cost_per_lead_cents": 127
},
"created_at": "2026-08-04T09:00:00.000Z",
"started_at": "2026-08-05T08:30:00.000Z"
}
],
"total": 1,
"limit": 25,
"offset": 0
}/v1/campaignsCreate a campaign
Starts in draft. Nothing is sent until you add a sequence, put leads in it and call start.
Body parameters
| Field | Type | Description |
|---|---|---|
| namereq | string | Internal label. |
| project_id | string | Project supplying the offer and value props. |
| icp_id | string | Selected ICP whose filters define the audience. |
| daily_cap | number | Maximum emails per day across all mailboxes. Default 50. |
curl -X POST "https://beamro.com/api/v1/campaigns" \
-H "x-api-key: $SALVO_API_KEY" \
-H "content-type: application/json" \
-d '{
"name": "New England venues · autumn",
"project_id": "prj_8w3k1n6v0q4z7m2b5d",
"icp_id": "icp_2q7v4m9x1k6b0n3t8p",
"daily_cap": 120
}'{
"id": "cmp_1t7k4v9m2q0b6x3n8w",
"org_id": "org_4k1p8w2ne6ts0ybc7j",
"project_id": "prj_8w3k1n6v0q4z7m2b5d",
"icp_id": "icp_2q7v4m9x1k6b0n3t8p",
"name": "New England venues · autumn",
"status": "draft",
"daily_cap": 120,
"sending_window": {
"tz": "America/New_York",
"days": [
1,
2,
3,
4,
5
],
"start": "08:30",
"end": "16:30"
},
"sequence_id": null,
"autopilot": true,
"stats": {
"leads": 0,
"queued": 0,
"sent": 0,
"delivered": 0,
"opened": 0,
"replied": 0,
"interested": 0,
"meetings": 0,
"bounced": 0,
"unsubscribed": 0,
"spend_cents": 0,
"cost_per_lead_cents": null
},
"created_at": "2026-08-04T09:00:00.000Z",
"started_at": null
}/v1/campaigns/{campaign_id}Retrieve a campaign
Current configuration, sending window and counters.
Path parameters
| Field | Type | Description |
|---|---|---|
| campaign_idreq | string | Campaign identifier. |
curl "https://beamro.com/api/v1/campaigns/cmp_1t7k4v9m2q0b6x3n8w" \
-H "x-api-key: $SALVO_API_KEY"{
"id": "cmp_1t7k4v9m2q0b6x3n8w",
"org_id": "org_4k1p8w2ne6ts0ybc7j",
"project_id": "prj_8w3k1n6v0q4z7m2b5d",
"icp_id": "icp_2q7v4m9x1k6b0n3t8p",
"name": "New England venues · autumn",
"status": "running",
"daily_cap": 120,
"sending_window": {
"tz": "America/New_York",
"days": [
1,
2,
3,
4,
5
],
"start": "08:30",
"end": "16:30"
},
"sequence_id": "seq_9m2x5k8v1q4b7t0n3w",
"autopilot": true,
"stats": {
"leads": 1840,
"queued": 402,
"sent": 1438,
"delivered": 1398,
"opened": 641,
"replied": 96,
"interested": 34,
"meetings": 14,
"bounced": 40,
"unsubscribed": 8,
"spend_cents": 4314,
"cost_per_lead_cents": 127
},
"created_at": "2026-08-04T09:00:00.000Z",
"started_at": "2026-08-05T08:30:00.000Z"
}/v1/campaigns/{campaign_id}Update a campaign
Change the cap, the window or autopilot mid-flight. Changes apply to the next scheduling pass, never to mail already queued.
Path parameters
| Field | Type | Description |
|---|---|---|
| campaign_idreq | string | Campaign identifier. |
Body parameters
| Field | Type | Description |
|---|---|---|
| name | string | Internal label. |
| daily_cap | number | Maximum emails per day. |
| sending_window | object | tz, days (0-6, Sunday is 0), start and end as HH:MM local time. |
| autopilot | boolean | Allow the agent to scale or pause the campaign on its own. |
curl -X PATCH "https://beamro.com/api/v1/campaigns/cmp_1t7k4v9m2q0b6x3n8w" \
-H "x-api-key: $SALVO_API_KEY" \
-H "content-type: application/json" \
-d '{
"daily_cap": 160,
"sending_window": {
"tz": "America/New_York",
"days": [
1,
2,
3,
4
],
"start": "09:00",
"end": "15:00"
}
}'{
"id": "cmp_1t7k4v9m2q0b6x3n8w",
"org_id": "org_4k1p8w2ne6ts0ybc7j",
"project_id": "prj_8w3k1n6v0q4z7m2b5d",
"icp_id": "icp_2q7v4m9x1k6b0n3t8p",
"name": "New England venues · autumn",
"status": "running",
"daily_cap": 160,
"sending_window": {
"tz": "America/New_York",
"days": [
1,
2,
3,
4
],
"start": "09:00",
"end": "15:00"
},
"sequence_id": "seq_9m2x5k8v1q4b7t0n3w",
"autopilot": true,
"stats": {
"leads": 1840,
"queued": 402,
"sent": 1438,
"delivered": 1398,
"opened": 641,
"replied": 96,
"interested": 34,
"meetings": 14,
"bounced": 40,
"unsubscribed": 8,
"spend_cents": 4314,
"cost_per_lead_cents": 127
},
"created_at": "2026-08-04T09:00:00.000Z",
"started_at": "2026-08-05T08:30:00.000Z"
}/v1/campaigns/{campaign_id}/startStart a campaign
Moves the campaign into the scheduler. Rejected with 409 when there is no sequence, no leads, or no verified sending domain; rejected with 402 when the wallet is empty.
Path parameters
| Field | Type | Description |
|---|---|---|
| campaign_idreq | string | Campaign identifier. |
curl -X POST "https://beamro.com/api/v1/campaigns/cmp_1t7k4v9m2q0b6x3n8w/start" \
-H "x-api-key: $SALVO_API_KEY"{
"id": "cmp_1t7k4v9m2q0b6x3n8w",
"org_id": "org_4k1p8w2ne6ts0ybc7j",
"project_id": "prj_8w3k1n6v0q4z7m2b5d",
"icp_id": "icp_2q7v4m9x1k6b0n3t8p",
"name": "New England venues · autumn",
"status": "running",
"daily_cap": 120,
"sending_window": {
"tz": "America/New_York",
"days": [
1,
2,
3,
4,
5
],
"start": "08:30",
"end": "16:30"
},
"sequence_id": "seq_9m2x5k8v1q4b7t0n3w",
"autopilot": true,
"stats": {
"leads": 1840,
"queued": 402,
"sent": 1438,
"delivered": 1398,
"opened": 641,
"replied": 96,
"interested": 34,
"meetings": 14,
"bounced": 40,
"unsubscribed": 8,
"spend_cents": 4314,
"cost_per_lead_cents": 127
},
"created_at": "2026-08-04T09:00:00.000Z",
"started_at": "2026-08-05T08:30:00.000Z"
}/v1/campaigns/{campaign_id}/pausePause a campaign
Stops new sends immediately. Replies keep arriving and the inbox agent keeps answering them.
Path parameters
| Field | Type | Description |
|---|---|---|
| campaign_idreq | string | Campaign identifier. |
curl -X POST "https://beamro.com/api/v1/campaigns/cmp_1t7k4v9m2q0b6x3n8w/pause" \
-H "x-api-key: $SALVO_API_KEY"{
"id": "cmp_1t7k4v9m2q0b6x3n8w",
"org_id": "org_4k1p8w2ne6ts0ybc7j",
"project_id": "prj_8w3k1n6v0q4z7m2b5d",
"icp_id": "icp_2q7v4m9x1k6b0n3t8p",
"name": "New England venues · autumn",
"status": "paused",
"daily_cap": 120,
"sending_window": {
"tz": "America/New_York",
"days": [
1,
2,
3,
4,
5
],
"start": "08:30",
"end": "16:30"
},
"sequence_id": "seq_9m2x5k8v1q4b7t0n3w",
"autopilot": true,
"stats": {
"leads": 1840,
"queued": 402,
"sent": 1438,
"delivered": 1398,
"opened": 641,
"replied": 96,
"interested": 34,
"meetings": 14,
"bounced": 40,
"unsubscribed": 8,
"spend_cents": 4314,
"cost_per_lead_cents": 127
},
"created_at": "2026-08-04T09:00:00.000Z",
"started_at": "2026-08-05T08:30:00.000Z"
}/v1/campaigns/{campaign_id}/stopStop a campaign
Terminal. Queued mail is discarded and the campaign cannot be restarted — clone it instead.
Path parameters
| Field | Type | Description |
|---|---|---|
| campaign_idreq | string | Campaign identifier. |
curl -X POST "https://beamro.com/api/v1/campaigns/cmp_1t7k4v9m2q0b6x3n8w/stop" \
-H "x-api-key: $SALVO_API_KEY"{
"id": "cmp_1t7k4v9m2q0b6x3n8w",
"org_id": "org_4k1p8w2ne6ts0ybc7j",
"project_id": "prj_8w3k1n6v0q4z7m2b5d",
"icp_id": "icp_2q7v4m9x1k6b0n3t8p",
"name": "New England venues · autumn",
"status": "stopped",
"daily_cap": 120,
"sending_window": {
"tz": "America/New_York",
"days": [
1,
2,
3,
4,
5
],
"start": "08:30",
"end": "16:30"
},
"sequence_id": "seq_9m2x5k8v1q4b7t0n3w",
"autopilot": true,
"stats": {
"leads": 1840,
"queued": 402,
"sent": 1438,
"delivered": 1398,
"opened": 641,
"replied": 96,
"interested": 34,
"meetings": 14,
"bounced": 40,
"unsubscribed": 8,
"spend_cents": 4314,
"cost_per_lead_cents": 127
},
"created_at": "2026-08-04T09:00:00.000Z",
"started_at": "2026-08-05T08:30:00.000Z"
}/v1/campaigns/{campaign_id}/statsCampaign counters
The same counters embedded in the campaign object, fetched on their own for polling.
Path parameters
| Field | Type | Description |
|---|---|---|
| campaign_idreq | string | Campaign identifier. |
curl "https://beamro.com/api/v1/campaigns/cmp_1t7k4v9m2q0b6x3n8w/stats" \
-H "x-api-key: $SALVO_API_KEY"{
"leads": 1840,
"queued": 402,
"sent": 1438,
"delivered": 1398,
"opened": 641,
"replied": 96,
"interested": 34,
"meetings": 14,
"bounced": 40,
"unsubscribed": 8,
"spend_cents": 4314,
"cost_per_lead_cents": 127
}/v1/campaigns/{campaign_id}/sequenceRetrieve the sequence
The touches in order. Steps are prompts, not mail-merge templates — the writer agent composes each email from scratch.
Path parameters
| Field | Type | Description |
|---|---|---|
| campaign_idreq | string | Campaign identifier. |
curl "https://beamro.com/api/v1/campaigns/cmp_1t7k4v9m2q0b6x3n8w/sequence" \
-H "x-api-key: $SALVO_API_KEY"{
"steps": [
{
"id": "stp_1",
"sequence_id": "seq_9m2x5k8v1q4b7t0n3w",
"position": 1,
"delay_days": 0,
"channel": "email",
"prompt": "Open on something specific and recent from their own site. One sentence on the install crew. Ask whether they want the autumn availability sheet. Under 90 words, no stacked adjectives, never open with a pleasantry.",
"subject_hint": "autumn install windows",
"stop_on_reply": true
},
{
"id": "stp_2",
"sequence_id": "seq_9m2x5k8v1q4b7t0n3w",
"position": 2,
"delay_days": 3,
"channel": "email",
"prompt": "One-clause reference to the first note, then a single new proof point about load-in timing. Ask the same question a different way. Under 60 words.",
"subject_hint": null,
"stop_on_reply": true
},
{
"id": "stp_3",
"sequence_id": "seq_9m2x5k8v1q4b7t0n3w",
"position": 3,
"delay_days": 5,
"channel": "email",
"prompt": "Close the loop politely, leave the availability sheet link, say you will stop following up. Under 40 words.",
"subject_hint": null,
"stop_on_reply": true
}
]
}/v1/campaigns/{campaign_id}/sequenceReplace the sequence
Send the whole ladder; it replaces what is there. Leads mid-sequence keep their position, so editing step three never re-sends step one.
Path parameters
| Field | Type | Description |
|---|---|---|
| campaign_idreq | string | Campaign identifier. |
Body parameters
| Field | Type | Description |
|---|---|---|
| stepsreq | SequenceStep[] | Ordered touches. Each needs position, delay_days, channel and prompt. |
| steps[].delay_days | number | Days to wait after the previous touch. Step one is normally 0. |
| steps[].prompt | string | Instructions for the writer agent — angle, length, what to ask for. |
| steps[].subject_hint | string | null | Optional steer on the subject line. Null lets the agent choose. |
| steps[].stop_on_reply | boolean | Halt the ladder for that lead as soon as they answer. Almost always true. |
curl -X PUT "https://beamro.com/api/v1/campaigns/cmp_1t7k4v9m2q0b6x3n8w/sequence" \
-H "x-api-key: $SALVO_API_KEY" \
-H "content-type: application/json" \
-d '{
"steps": [
{
"position": 1,
"delay_days": 0,
"channel": "email",
"prompt": "Open on something specific from their own site. Ask about the autumn availability sheet. Under 90 words.",
"subject_hint": "autumn install windows",
"stop_on_reply": true
},
{
"position": 2,
"delay_days": 3,
"channel": "email",
"prompt": "Short bump with one new proof point about load-in timing.",
"subject_hint": null,
"stop_on_reply": true
}
]
}'{
"steps": [
{
"id": "stp_1",
"sequence_id": "seq_9m2x5k8v1q4b7t0n3w",
"position": 1,
"delay_days": 0,
"channel": "email",
"prompt": "Open on something specific and recent from their own site. One sentence on the install crew. Ask whether they want the autumn availability sheet. Under 90 words, no stacked adjectives, never open with a pleasantry.",
"subject_hint": "autumn install windows",
"stop_on_reply": true
},
{
"id": "stp_2",
"sequence_id": "seq_9m2x5k8v1q4b7t0n3w",
"position": 2,
"delay_days": 3,
"channel": "email",
"prompt": "One-clause reference to the first note, then a single new proof point about load-in timing. Ask the same question a different way. Under 60 words.",
"subject_hint": null,
"stop_on_reply": true
}
]
}/v1/campaigns/{campaign_id}/leads/generateGenerate leads from an ICP
Resolves the ICP filters, picks contacts, researches each one and adds them to the campaign. Already-contacted and suppressed addresses are skipped.
Path parameters
| Field | Type | Description |
|---|---|---|
| campaign_idreq | string | Campaign identifier. |
Body parameters
| Field | Type | Description |
|---|---|---|
| countreq | number | How many leads to add. Up to 5,000 per call. |
| icp_id | string | Override the campaign ICP for this batch. |
curl -X POST "https://beamro.com/api/v1/campaigns/cmp_1t7k4v9m2q0b6x3n8w/leads/generate" \
-H "x-api-key: $SALVO_API_KEY" \
-H "content-type: application/json" \
-d '{
"count": 250,
"icp_id": "icp_2q7v4m9x1k6b0n3t8p"
}'{
"added": 243,
"rows": [
{
"id": "led_9f21c7ab4d0e",
"org_id": "org_7t2m9v",
"campaign_id": "cmp_1t7k4v9m2q0b6x3n8w",
"person_id": "per_2k7n4v9x1m6q0b3t8c",
"company_id": "cmp_3h8q1w6x0m4v9k2t7b",
"full_name": "Priya Whitcombe",
"title": "Founder & Creative Director",
"email": "priya.whitcombe@harlowmeadow.example",
"email_status": "valid",
"company_name": "Harlow Meadow Events",
"company_domain": "harlowmeadow.example",
"country": "US",
"linkedin_url": "https://www.linkedin.example/in/priya-whitcombe-4c",
"fit_score": 88,
"status": "queued",
"research": {
"hooks": [
"Posted three November barn weddings in the last month",
"Hiring a second install crew"
],
"summary": "Small studio scaling install capacity for the autumn season; buys stems by the case.",
"signals": [
"hiring",
"seasonal_peak"
]
},
"last_contacted_at": null,
"replied_at": null,
"created_at": "2026-08-19T10:00:00.000Z"
}
]
}/v1/campaigns/{campaign_id}/leads/importImport your own leads
Bring a list you already own. Rows are de-duplicated against the campaign and checked against suppressions before anything is queued.
Path parameters
| Field | Type | Description |
|---|---|---|
| campaign_idreq | string | Campaign identifier. |
Body parameters
| Field | Type | Description |
|---|---|---|
| rowsreq | Partial<Lead>[] | Lead rows. email is required; full_name, title, company_name and company_domain sharpen the writing. |
curl -X POST "https://beamro.com/api/v1/campaigns/cmp_1t7k4v9m2q0b6x3n8w/leads/import" \
-H "x-api-key: $SALVO_API_KEY" \
-H "content-type: application/json" \
-d '{
"rows": [
{
"full_name": "Marisol Enderby",
"title": "Venue Director",
"email": "marisol@stonecroftbarn.example",
"company_name": "Stonecroft Barn",
"company_domain": "stonecroftbarn.example",
"country": "US"
}
]
}'{
"added": 1,
"skipped": 0
}/v1/campaigns/{campaign_id}/previewPreview a written email
Writes the first touch for one real lead without sending it. The fastest way to sanity-check a prompt before committing a wallet to it.
Path parameters
| Field | Type | Description |
|---|---|---|
| campaign_idreq | string | Campaign identifier. |
Body parameters
| Field | Type | Description |
|---|---|---|
| lead_id | string | Lead to write for. Omit and a queued lead is chosen for you. |
curl -X POST "https://beamro.com/api/v1/campaigns/cmp_1t7k4v9m2q0b6x3n8w/preview" \
-H "x-api-key: $SALVO_API_KEY" \
-H "content-type: application/json" \
-d '{
"lead_id": "led_9f21c7ab4d0e"
}'{
"subject": "autumn install windows at Harlow Meadow",
"body": "Priya — you have three barn weddings listed for November, which is the month venues start refusing late load-ins.\n\nWe install with our own two-van crew and work to whatever window the venue signs off, so the setup is finished before the coordinator starts asking.\n\nWant the autumn availability sheet? It is one page.\n\n— Devon",
"lead": {
"id": "led_9f21c7ab4d0e",
"org_id": "org_7t2m9v",
"campaign_id": "cmp_1t7k4v9m2q0b6x3n8w",
"person_id": "per_2k7n4v9x1m6q0b3t8c",
"company_id": "cmp_3h8q1w6x0m4v9k2t7b",
"full_name": "Priya Whitcombe",
"title": "Founder & Creative Director",
"email": "priya.whitcombe@harlowmeadow.example",
"email_status": "valid",
"company_name": "Harlow Meadow Events",
"company_domain": "harlowmeadow.example",
"country": "US",
"linkedin_url": "https://www.linkedin.example/in/priya-whitcombe-4c",
"fit_score": 88,
"status": "replied",
"research": {
"hooks": [
"Posted three November barn weddings in the last month",
"Hiring a second install crew"
],
"summary": "Small studio scaling install capacity for the autumn season; buys stems by the case.",
"signals": [
"hiring",
"seasonal_peak"
]
},
"last_contacted_at": "2026-08-27T13:02:10.000Z",
"replied_at": "2026-08-28T08:41:55.000Z",
"created_at": "2026-08-19T10:00:00.000Z"
}
}