API reference / Outreach
Texts
POST /sms sends one text to one person. Add files to send an MMS, or a
template_id to send RCS. The recipient fields, foreign_id, callback_url
and merge fields work the same on every send; see
Sending basics. To answer someone who texted you, use
Send a reply instead.
A
202means accepted, not delivered. The result of each text arrives on thecontact.sms.statuswebhook. Calling hours, the contact frequency limit and retries are explained in Send lifecycle. What eachreason_codemeans, and what to do about it, is in Outcomes and what to do.
Send a text
POST /sms. With OAuth, the token needs the sms:send scope.
| Field | Type | Required | Description |
|---|---|---|---|
body |
string | One of body, template_id or media |
The message, up to 1,600 characters. With media, it's the caption. Supports merge fields. |
template_id |
string | One of body, template_id or media |
An RCS template built in the dashboard. Find yours with GET /template/public/templates?type=rcs. |
phone_line_id |
string | No | The phone line to send from. Its numbers are the sender and its approved texting campaign is used. List lines with GET /phone/public/lines. |
media_urls |
string[] | No | https URLs of files to send as MMS. See MMS. |
media_ids |
string[] | No | Media API ids to send as MMS. See MMS. |
curl -X POST https://api-v2.dropcowboy.com/sms \
-H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET" \
-H "Idempotency-Key: 0d7e3b9f-2a6c-4e1d-8f5b-7c9a3e1d5b42" \
-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.",
"callback_url": "https://hooks.example.com/dropcowboy/outcome"
}'
{ "status": "queued", "message_id": "8e4a2c6f-9d1b-4f7e-b3a5-6c9e1f4d2b78" }
message_id is a receipt for the request. It doesn't appear on webhooks, and
the text isn't stored for reading back. The result arrives on
contact.sms.status and your callback_url; see
Where results arrive.
A text without opt-out language gets Reply STOP to opt-out added to the
end. Put your own opt-out wording in body to control it. A text is billed per
153 characters.
Texts aren't held for calling hours. Outside the contact's allowed hours the
send fails with 4011 and isn't retried, so send again inside the window.
See Calling hours.
Send from a phone line
Send from a phone_line_id whose line has an approved texting campaign. The
line picks the sender number and the registered campaign. Without a phone
line, we pick a sender from your account's own texting numbers. Texts never
go out from numbers shared with other accounts.
| Code | Cause | What to do |
|---|---|---|
3013 |
phone_line_id isn't one of your phone lines |
Check the id with GET /phone/public/lines. |
3029 |
The phone line has no texting campaign | Attach the line to an approved texting campaign, or send from another line. |
6009 |
Your account needs a registered brand and campaign to text | Register your brand and texting campaign in the dashboard, wait for approval, then send. |
3025 |
The line's texting campaign reached its daily carrier limit | Resend after midnight Pacific time. |
3026 |
We couldn't check the daily limit | Retry. |
Send RCS
With template_id, the message goes as RCS. Where the recipient's phone
can't receive RCS, the template's fallback text is sent instead. If you send
both body and template_id, the template wins. A template_id that isn't
one of your RCS templates fails with 3999 (Other).
{
"contact_id": "5a4b3c2d-1e0f-4a9b-8c7d-6e5f4a3b2c1d",
"phone_line_id": "e2b6f9a3-5c1d-4e8b-a4f7-9c3e1b5d7a28",
"template_id": "3a7d1f9c-5e2b-4c8a-9f6d-1b4e7a2c5d93"
}
MMS
Add files with media_urls, media_ids, or both, to send an MMS. body
becomes the caption and is optional. Send a reply
takes media with the same rules.
{
"contact_id": "5a4b3c2d-1e0f-4a9b-8c7d-6e5f4a3b2c1d",
"phone_line_id": "e2b6f9a3-5c1d-4e8b-a4f7-9c3e1b5d7a28",
"body": "Your order is ready. Show this at pickup.",
"media_urls": ["https://files.example.com/pickup-code.png"]
}
Choose the files
| Limit | Value |
|---|---|
| Files per message, across both fields | 10 |
| Size per file | 1 MiB |
| Size per message | 5 MiB |
| URL length | 2,048 characters |
| Time to fetch a URL | 10 seconds per file, 15 seconds in total |
We accept JPEG, PNG, GIF, WAV and MP3. We read the type from the file's
bytes, not from its name or Content-Type.
For media_urls, host each file at a public https URL that answers 200
without a redirect. Don't put a user name or password in the URL. We fetch
the file once, when the message is sent.
media_ids take audio only, because the Media API stores audio
files. Send images with media_urls. A media_id must be yours, not
deleted, and fully uploaded.
Scanning
We copy each file to mms.dropcowboy.com and scan it for malware. The message
goes out only when every file is clean. A scan can take up to 45 seconds;
after that the send fails with 3038. Retry it: a retry of the same file on
the same UTC day reuses the finished scan.
The copies are deleted after 3 days. Your media_id in the Media API isn't
affected.
Caption, opt-out text and billing
- The caption is sent exactly as written. No opt-out text is added to an MMS. If your texting campaign needs opt-out wording, put it in the caption.
- An MMS with no caption goes out as media only.
- An MMS is billed per file, and the caption adds nothing. Three files cost three MMS units.
- If the phone line's texting campaign asks contacts to opt in first, a contact who hasn't opted in gets the opt-in request as a plain text without the media, billed per 153 characters. The MMS is sent, and billed per file, after they opt in.
- MMS works to any country your account doesn't block, at that country's MMS rate.
- You can't combine media with
template_id, and you can't send media on voice routes. Both fail with3032.
MMS results
Media is checked after the 202, so media problems arrive with the result.
An MMS that went out reports campaign_type: mms. status: success means the
carrier accepted the message, not that the phone displayed it.
| Code | Cause | What to do |
|---|---|---|
3032 |
Bad media_urls or media_ids, more than 10 files, or media combined with a template or a voice route |
Fix the request. |
3033 |
A media_id isn't found |
Check the id with GET /media/public/media. |
3034 |
A URL didn't answer 200 in time, or redirected |
Retry once the URL answers 200 without a redirect. |
3035 |
A file, or the files together, are too large | Send smaller files. |
3036 |
Not JPEG, PNG, GIF, WAV or MP3 | Convert the file. |
3037 |
The malware scan flagged a file | Don't retry. |
3038 |
The scan didn't finish in time | Retry. |
3039 |
The scan failed | Retry later. |
3999 |
Storing a file failed | Retry later. |
Receive MMS
An inbound MMS arrives on contact.msg.received, with each file's id, type,
size and scan status under sms.media. The event has no download link,
because files are scanned after they arrive. Fetch the message with
Get an SMS record a little later; each
clean file has a url. See Inbound messages.
Common problems
- The text failed with
4011. It was outside the contact's calling hours. Send it again inside the window. - The text failed with
3029or6009. Your phone line or account isn't set up for texting yet. See Send from a phone line. - The text failed with
6005or6011. The contact opted out, or there's no consent on file. Don't text them until they opt in; see Consent. - The text failed with
3025. The line's texting campaign hit the daily limit carriers set for it. Resend after midnight Pacific time, or send from a line on another texting campaign. - The text failed with
3020. It had nobody, notemplate_idand no media. - An MMS failed with
3038. The malware scan took too long. Retry.
For more symptoms and fixes, see Troubleshooting. Every code is in Outcomes.
While Drop Cowboy provides tools to support compliance efforts, customers remain solely responsible for obtaining proper consent, maintaining opt-out lists, and complying with all federal and state telemarketing regulations. Consult with your legal counsel to ensure your specific use case and consent mechanisms comply with applicable laws.