Your first campaign
From a target profile to a launched sequence, in the order the dashboard's wizard walks it. Nine calls, two of them jobs you wait for.
Before the first call: the workspace needs its provider keys (Apollo at least, Reoon for verification, OpenRouter for the writer) and one connected mailbox. Both are Settings work, or provider keys and mailboxes with an admin key.
1. Describe who you sell to
An ICP profile is what searches and the writer draw defaults from. Make it the default so later calls can lean on it.
curl -X POST https://crm.ashwanth.dev/api/v1/icp -H "Authorization: Bearer $SALES_ENGINE_API_KEY" -H "Content-Type: application/json" \
-d '{"name":"Heads of Sales, UK SaaS","target_titles":["Head of Sales","VP Sales","CRO"],"industries":["Computer Software"],"employee_ranges":["51,100","101,200"],"locations":["United Kingdom"],"make_default":true}'2. See what a search would cost
A preview reads one page from Apollo and returns the audience size, a masked sample and the price of sourcing. It is a job: the response is the job, and its result fills in a few seconds.
curl -X POST https://crm.ashwanth.dev/api/v1/lead-lists/preview -H "Authorization: Bearer $SALES_ENGINE_API_KEY" -H "Content-Type: application/json" \
-d '{"mode":"form","use_icp_defaults":true,"options":{"verify":true,"profile_tier":"cheap"}}'3. Source the list
The same search, with a name and how many leads you want. The list comes back at once with a job_id; the job does the sourcing, verification and enrichment.
curl -X POST https://crm.ashwanth.dev/api/v1/lead-lists -H "Authorization: Bearer $SALES_ENGINE_API_KEY" -H "Content-Type: application/json" \
-d '{"name":"UK SaaS sales leaders, September","requested_count":50,"params":{"mode":"form","use_icp_defaults":true,"options":{"verify":true,"profile_tier":"cheap"}}}'Wait for it (how), then read the list for its counts and spend.
4. Choose the sequence shape
You decide the number of steps, the days they go out, variants and the writer's mode; nothing is derived for you. Save it once and reuse it across campaigns.
curl -X POST https://crm.ashwanth.dev/api/v1/sequences -H "Authorization: Bearer $SALES_ENGINE_API_KEY" -H "Content-Type: application/json" \
-d '{"name":"Three touches, ten days","total_steps":3,"day_offsets":[0,3,10],"generation_mode":"personalized","cta_policy":"reply_only","word_ceiling":120,"thread_followups":true,"steps":[{"step_number":1,"purpose":"opener"},{"step_number":2,"purpose":"proof"},{"step_number":3,"purpose":"breakup"}]}'5. Create the campaign from the list
curl -X POST https://crm.ashwanth.dev/api/v1/campaigns -H "Authorization: Bearer $SALES_ENGINE_API_KEY" -H "Content-Type: application/json" \
-d '{"name":"UK SaaS, September","lead_list_ids":["LIST_ID"]}'Then apply the sequence and pick the mailboxes it sends from:
curl -X POST https://crm.ashwanth.dev/api/v1/campaigns/CAMPAIGN_ID/sequence -H "Authorization: Bearer $SALES_ENGINE_API_KEY" -H "Content-Type: application/json" \
-d '{"sequence_id":"SEQUENCE_ID"}'
curl -X PATCH https://crm.ashwanth.dev/api/v1/campaigns/CAMPAIGN_ID -H "Authorization: Bearer $SALES_ENGINE_API_KEY" -H "Content-Type: application/json" \
-d '{"mailbox_ids":["MAILBOX_ID"],"daily_limit":40,"track_opens":true}'6. Approve the audience
Only approved leads get copy and get sent. Approve everyone, or pass a rule (min_icp_score, tiers, email_statuses) to be choosy.
curl -X POST https://crm.ashwanth.dev/api/v1/campaigns/CAMPAIGN_ID/leads -H "Authorization: Bearer $SALES_ENGINE_API_KEY" -H "Content-Type: application/json" \
-d '{"action":"approve","rule":{"email_statuses":["valid"]}}'7. Write the copy
One build job, then one job per approved lead in personalized mode. Wait for the parent job; its children_done climbs to children_total.
curl -X POST https://crm.ashwanth.dev/api/v1/campaigns/CAMPAIGN_ID/generate -H "Authorization: Bearer $SALES_ENGINE_API_KEY" -H "Content-Type: application/json" -d '{}'Preview renders every step for one lead, and a test send puts one in your own inbox (that needs the send scope).
8. Check, then launch
The checklist says what still blocks a launch: a shape, approved leads, a healthy mailbox with enough capacity for day one, copy that passed the guardrails. Launch refuses until every line is clear.
curl https://crm.ashwanth.dev/api/v1/campaigns/CAMPAIGN_ID/checklist -H "Authorization: Bearer $SALES_ENGINE_API_KEY"
curl -X POST https://crm.ashwanth.dev/api/v1/campaigns/CAMPAIGN_ID/launch -H "Authorization: Bearer $SALES_ENGINE_API_KEY" -H "Content-Type: application/json" -d '{"mode":"now"}'Launch locks the shape and enrolls the approved leads; the runner sends inside each mailbox's window and daily limit.
9. Read what comes back
curl "https://crm.ashwanth.dev/api/v1/inbox?view=replies&campaign_id=CAMPAIGN_ID" -H "Authorization: Bearer $SALES_ENGINE_API_KEY"
curl "https://crm.ashwanth.dev/api/v1/inbox/drafts?status=proposed" -H "Authorization: Bearer $SALES_ENGINE_API_KEY"
curl https://crm.ashwanth.dev/api/v1/campaigns/CAMPAIGN_ID/analytics -H "Authorization: Bearer $SALES_ENGINE_API_KEY"Replies arrive classified (interested, meeting request, not interested, out of office and so on) and a positive one stops the lead's sequence. The agent proposes a draft for each; approving it sends it threaded from the same mailbox.