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.

  1. Knowledge base. Create one and add your hours, services and FAQs as documents. Wait until each document's ingest_status is ready, then test with a query. See Knowledge bases.
  2. Voice. Pick a voice_id from GET /voice/public/voices, or clone your own. See Voice cloning.
  3. Agent. Create it from a template or from scratch, with the voice and think.knowledge pointing at your knowledge base. See AI agents.
  4. 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.
  5. 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.
  6. Test. Call the number from your phone, then read the call with GET /phone/public/calls/{call_id} or watch ai_agent.call.completed.

Nothing is sending: checklist

A 202 means queued, not delivered. When results do not arrive, work down this list.

  1. Read the outcome. Subscribe to the status webhook for the channel, or set callback_url, and look at reason and reason_code. Outcomes explains every code and whether to retry.
  2. 4013 Too 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.
  3. 4011 TCPA 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 with tcpa_expired after 3 days.
  4. 3000 No Funds. Check GET /campaign/public/balance, add funds or turn on auto-recharge.
  5. Consent or do-not-contact. The contact has opted out, lacks consent, or is on your do-not-contact list.
  6. Texting registration. 6009 (Unregistered Brand) or a pool error means the phone line has no approved texting campaign.
  7. Wrong recipient. With contact_id, a phone_selector naming an empty slot fails with "No phone number for contact".
  8. Campaign not sending. A new campaign may be waiting for compliance review (approved: false), or campaign_data.status may be insufficient_credit.
  9. Email. data.success: false means nothing was sent; read error. Contacts over the email frequency cap are skipped.
  10. Webhooks not arriving. Your endpoint must answer 2xx within 5 seconds. After repeated failures deliveries to it pause, and events during a pause are dropped. See Webhooks.
  11. No webhook at all for a send. A wrong x-key or x-secret still gets 202, but it is reported on callback_url only (3007). A resend with the same Idempotency-Key and body is skipped without a second result. Codes 3027 to 3031 mean the request itself needs fixing.

Still stuck? Contact support with the meta.request_id from the response, or your foreign_id.

Code samples

The requests from this page, ready to copy. Set DC_KEY and DC_SECRET to your API key pair first.

Find the IDs you need
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"
  }'
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"
  }'
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>"
  }'
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"
  }'
Send to a whole list
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"