Sales Engine
API documentation
Guides

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
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
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
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
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
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
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
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
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
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
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.