API reference · Get started
Recipes
End-to-end flows for the jobs most integrations need. Every example uses
$DC_KEY and $DC_SECRET for your API key pair and
https://api-v2.dropcowboy.com as the base URL. See
Authentication to create a key.
Before you start: send to yourself
Add your own phone numbers and email addresses as test numbers and test email addresses on the Dialing rules page. They skip the contact frequency limit (by default 3 attempts in 3 days per number, configurable per team) and the email frequency cap, so you can send to yourself as often as you need while you build. Calling hours still apply unless you turn that off on the same page.
Subscribe to the status webhooks before your first send, so you can see what happened. See Webhooks.
Find the IDs you need
Every *_id in a send comes from a lookup route. Fetch them once and store
them.
| You need | Route | Field |
|---|---|---|
| A phone line to send from | GET /phone/public/lines |
phone_line_id |
| An audio file | GET /media/public/media |
media_id |
| A voice, including your clones | GET /voice/public/voices |
voice_id |
| A contact list | GET /contact/public/lists |
list_ids |
| A contact | GET /contact/public/contacts |
contact_id |
| A registered brand | GET /automation/public/brands |
brand_id |
| An AI agent | GET /agents/public/agents |
agent_id |
| A sending mailbox | GET /domain/public/mailboxes |
mailbox_id |
| A saved template | GET /template/public/templates?type=email (or rcs) |
template_id |
curl https://api-v2.dropcowboy.com/phone/public/lines \
-H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"
Send a ringless voicemail
curl -X POST https://api-v2.dropcowboy.com/rvm \
-H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET" \
-H "Content-Type: application/json" \
-d '{
"to": "+13125550142",
"phone_line_id": "e2b6f9a3-5c1d-4e8b-a4f7-9c3e1b5d7a28",
"media_id": "1b7e3c9a-4d2f-4a8b-9e6c-7f2a1d5b3c80",
"foreign_id": "order-1042"
}'
You get 202 with status: queued. The result arrives on
contact.rvm.status. To speak text instead of playing a file, replace
media_id with tts_body and voice_id. See Messaging.
Send a text
curl -X POST https://api-v2.dropcowboy.com/sms \
-H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET" \
-H "Content-Type: application/json" \
-d '{
"to": "+13125550142",
"phone_line_id": "e2b6f9a3-5c1d-4e8b-a4f7-9c3e1b5d7a28",
"body": "Your order is ready for pickup. Reply STOP to opt out.",
"foreign_id": "order-1042"
}'
The phone line must have an approved texting campaign. The result arrives on
contact.sms.status.
Send an email
curl -X POST https://api-v2.dropcowboy.com/email/public/email \
-H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET" \
-H "Content-Type: application/json" \
-d '{
"to": [{ "address": "jordan.rivera@example.com", "name": "Jordan Rivera" }],
"mailbox_id": "c5f1a8d3-6e2b-4c9f-b1a7-8d4e2c6f9b35",
"subject": "Your order is ready",
"html": "<p>Hi Jordan, your order is ready for pickup.</p>"
}'
Check data.success in the response; false means nothing was sent.
Delivery, opens and clicks arrive on contact.email.status. See
Email.
Place an AI call
curl -X POST https://api-v2.dropcowboy.com/ai-broadcast \
-H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET" \
-H "Content-Type: application/json" \
-d '{
"to": "+13125550142",
"caller_id": "+12125550100",
"agent_id": "4c8e2a6f-3b9d-4e1a-9c7b-5d2f8a3e6b19"
}'
The agent must be published. The per-contact result arrives on
contact.rvm.status with campaign_type: ai_broadcast, and the call itself
on one ai_agent.* event. See AI agents.
Send to a whole list
Create a campaign, then start it.
curl -X POST https://api-v2.dropcowboy.com/campaign/public/campaigns \
-H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET" \
-H "Content-Type: application/json" \
-d '{
"type": "rvm",
"campaign_data": {
"name": "Spring reminder",
"list_ids": ["8f3e1a9c-2d4b-4e7a-9c1f-5b6a7c8d9e0f"],
"phone_line_id": "e2b6f9a3-5c1d-4e8b-a4f7-9c3e1b5d7a28",
"media_id": "1b7e3c9a-4d2f-4a8b-9e6c-7f2a1d5b3c80"
}
}'
curl -X POST https://api-v2.dropcowboy.com/campaign/public/campaigns/a9c3e8f1-4b2d-4a7c-8e9b-1c2d3e4f5a6b/start \
-H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"
New campaigns can wait for compliance review before they send. See Campaigns.
Build an AI receptionist
An AI receptionist is an agent answering one of your phone lines. The order matters, because each step needs an ID from the one before.
- Knowledge base. Create one and add your hours, services and FAQs as
documents. Wait until each document's
ingest_statusisready, then test with a query. See Knowledge bases. - Voice. Pick a
voice_idfromGET /voice/public/voices, or clone your own. See Voice cloning. - Agent. Create it from a template or from scratch, with the voice and
think.knowledgepointing at your knowledge base. See AI agents. - Publish.
POST /agents/public/agents/{agent_id}/publish. Publishing fails if a selected knowledge base reads like instructions for staff rather than answers for callers; fix the documents and publish again. - Phone line. Create or update a line whose action sends calls to the agent, add business-hours rules, and assign a number to it. See AI receptionist.
- Test. Call the number from your phone, then read the call with
GET /phone/public/calls/{call_id}or watchai_agent.call.completed.
Nothing is sending: checklist
A 202 means queued, not delivered. When results do not arrive, work down
this list.
- Read the outcome. Subscribe to the status webhook for the channel, or
set
callback_url, and look atreasonandreason_code. Outcomes explains every code and whether to retry. 4013Too Many Attempts. The number reached your account's contact frequency limit (by default 3 attempts in 3 days, configurable per team on the Dialing rules page). Add your own numbers as test numbers, or wait for the window to move on.4011TCPA Hours. A text was sent outside the contact's allowed hours (default 8am to 9pm in their time zone). Voicemails and calls are held instead, and only fail withtcpa_expiredafter 3 days.3000No Funds. CheckGET /campaign/public/balance, add funds or turn on auto-recharge.- Consent or do-not-contact. The contact has opted out, lacks consent, or is on your do-not-contact list.
- Texting registration.
6009(Unregistered Brand) or a pool error means the phone line has no approved texting campaign. - Wrong recipient. With
contact_id, aphone_selectornaming an empty slot fails with "No phone number for contact". - Campaign not sending. A new campaign may be waiting for compliance
review (
approved: false), orcampaign_data.statusmay beinsufficient_credit. - Email.
data.success: falsemeans nothing was sent; readerror. Contacts over the email frequency cap are skipped. - Webhooks not arriving. Your endpoint must answer
2xxwithin 5 seconds. After repeated failures deliveries to it pause, and events during a pause are dropped. See Webhooks. - No webhook at all for a send. A wrong
x-keyorx-secretstill gets202, but it is reported oncallback_urlonly (3007). A resend with the sameIdempotency-Keyand body is skipped without a second result. Codes3027to3031mean the request itself needs fixing.
Still stuck? Contact support with the meta.request_id from the response, or
your foreign_id.