Campaigns end to end
Create the campaign, write the emails, add a list, choose your mailboxes and launch. Every step is one call, and nothing sends before the launch.
Nothing sends until you call launch. The same steps exist as command line commands and MCP tools, so an agent can run the whole flow and ask the user before the launch. Send an Idempotency-Key header with each call so a retry never does the work twice.
Check that a mailbox is connected
curl "https://app.argorant.com/api/v1/inboxes" -H "Authorization: Bearer $ARGORANT_API_KEY"No mailbox yet? Connect a Google Workspace in one step (guide), Microsoft 365 in the app, or a mailbox from any other provider with its server settings (guide).
Create the campaign with its settings
curl -X POST "https://app.argorant.com/api/v1/campaigns" \
-H "Authorization: Bearer $ARGORANT_API_KEY" -H "Content-Type: application/json" \
-d '{
"name": "Q4 CFO outreach",
"daily_limit": 40, "per_mailbox_daily_limit": 20,
"timezone": "Europe/Berlin", "timezone_mode": "fixed",
"window_start": "08:00", "window_end": "17:00", "skip_weekends": true,
"gap_minutes_min": 60, "gap_minutes_max": 120,
"planned_start_date": "2026-10-01", "tags": ["q4"]
}'Only name is required, and every setting can be changed later with PATCH /api/v1/campaigns/{id}. timezone_mode: "lead" sends in each person's local time. Campaigns send plain text, which reaches the inbox best. There is no unsubscribe line unless you set include_unsubscribe to true.
Write the sequence
curl -X POST "https://app.argorant.com/api/v1/campaigns/$ID/emails" \
-H "Authorization: Bearer $ARGORANT_API_KEY" -H "Content-Type: application/json" \
-d '{"emails":[
{"subject":"Quick question, {{first_name}}","body":"Hi {{first_name}},\n\nsaw {{company}} is hiring in finance. Worth a 10 minute call?\n\nBest"},
{"body":"Bumping this up in case it got buried.","delay_days":3,"same_thread":true}
]}'The first email needs a subject. Follow-ups stay in the same thread by default and wait delay_days after the previous one. You can use {{first_name}}, {{last_name}}, {{company}}, {{company_normalized}} (the name people say), {{title}} and any column you sent with the people, such as {{plan}}. Write {a|b} to vary a phrase per person. Add variants to an email for other versions; they are sent in turn. A personal line per person is set up with PUT /api/v1/campaigns/{id}/personalization; see Find and email 200 people.
Enroll the list
curl -X POST "https://app.argorant.com/api/v1/campaigns/$ID/leads" \
-H "Authorization: Bearer $ARGORANT_API_KEY" -H "Content-Type: application/json" \
-d '{"list_id": 1240}'
# {"input_rows": 1240, "inserted": 1188, "duplicates_skipped": 12, "skipped_not_valid": 40, "queued_for_verification": 0}Or send your own rows with email, first_name, last_name, company, title and any column of your own. Every address is checked before it joins. When a list holds addresses that cannot be confirmed, the first answer asks which to take (needs_choice); call again with "grades": ["valid"] (recommended) or ["valid", "catch_all"]. People from Argorant's data cost 1 credit each the first time; your own rows are free. Private addresses (free mail, home internet) are added like any other; send "exclude_private_emails": true for business emails only.
Attach the senders
curl -X POST "https://app.argorant.com/api/v1/campaigns/$ID/senders" \
-H "Authorization: Bearer $ARGORANT_API_KEY" -H "Content-Type: application/json" \
-d '{"all_connected": true}'Or name specific emails. Emails are spread across the mailboxes, each within its own daily limit.
Launch
curl "https://app.argorant.com/api/v1/campaigns/$ID" -H "Authorization: Bearer $ARGORANT_API_KEY" | jq .launch_blockers
curl -X POST "https://app.argorant.com/api/v1/campaigns/$ID/launch" -H "Authorization: Bearer $ARGORANT_API_KEY"launch_blockers is empty when the campaign can go. Before you launch, POST /api/v1/campaigns/{id}/test-email sends one test of an email to you, filled with a sample contact. Launch only after the user said yes. pause holds it, stop ends it, and DELETE removes a campaign that is not running.
Watch it run
GET /api/v1/campaigns/{id}/analytics?days=30 gives the daily numbers (sent, replies, positive replies, bounces, unsubscribes) with totals and rates. GET /api/v1/campaigns/{id} has the live counts. GET /api/v1/campaigns/{id}/leads?status=replied lists who answered, and GET /api/v1/campaigns/{id}/replies gives their messages. For replies across all campaigns use the inbox. GET /api/v1/campaigns/{id}/senders lists the mailboxes that send it, with their status.
Change the people in a running campaign
POST /api/v1/campaigns/{id}/leads/remove takes many people out at once, chosen by status, replied, bounced, email domain, tag, addresses or a saved list. Send "preview": true first to see how many would go. People who already got an email stay unless you send "include_contacted": true. A large add or removal runs in the background: the answer is 202 with a job, and GET /api/v1/campaigns/{id}/lead-jobs/{job_id} says how far it has come.
Personal lines for many people go in one file: POST /api/v1/campaigns/{id}/leads/custom-fields/import takes a CSV, JSON or NDJSON file with up to 200,000 rows (50 MB). Lines people already have are kept and listed with their row. To correct them, upload with ?overwrite=true; a clear column (or null in JSON) takes a line away, and the person gets the fallback again. Every replaced line comes back in the answer, old and new.
Folders
GET /api/v1/folders lists your folders, POST /api/v1/folders creates one and PATCH /api/v1/folders/{id} renames it. POST /api/v1/campaigns/{id}/folder with a folder_id files a campaign, and null takes it out again. Folders only sort campaigns; sending is not affected.
Mailboxes and the blocklist
GET /api/v1/inboxes lists your mailboxes with filters for domain, status, tag and provider. PATCH /api/v1/inboxes/{email} sets a mailbox's daily limit, warm-up, whether it may send, its name or its time zone, and DELETE disconnects it. POST /api/v1/inboxes/update makes the same change for many mailboxes at once, chosen by domain, tag, status or address; it previews by default and changes nothing until you send "preview": false. POST /api/v1/blocklist with an address or a domain stops every email to it in your workspace; DELETE /api/v1/blocklist/{id} lifts that again.
The same steps in the terminal
argorant campaigns create --name "Q4 CFO outreach" --daily-limit 40 --window 08:00-17:00 --timezone Europe/Berlin
argorant campaigns emails set "Q4 CFO" --step 1 --subject "Quick question, {{first_name}}" --body-file step1.txt
argorant campaigns emails set "Q4 CFO" --step 2 --body "Bumping this up." --delay-days 3
argorant campaigns leads add "Q4 CFO" --list 1240
argorant campaigns senders set "Q4 CFO" --all
argorant campaigns test "Q4 CFO" --step 1
argorant campaigns launch "Q4 CFO"
argorant campaigns leads remove "Q4 CFO" --not-replied --domains competitor.com --preview
argorant campaigns folders create --name "Q4"
argorant campaigns move "Q4 CFO" --folder Q4
argorant inboxes update --domains northgate-advisory.com --daily-limit 30