API reference / Track results
Troubleshooting
Each entry starts from what you see, then gives the likely cause, how to
confirm it and the fix. For what a single reason_code means, see
Outcomes.
I got a 202 but nothing happened
Likely cause. A 202 means the request was received, not sent. The send
failed a later check, and the result went somewhere you aren't listening:
- You have no webhook subscription for the channel's status event, and no
callback_urlon the send. - The key or secret was wrong. That failure (
3007) goes tocallback_urlonly, never to a webhook. - You retried with the same
Idempotency-Keyand body. The retry is skipped and produces no second result.
How to confirm. Resend with a callback_url and a new Idempotency-Key,
then read reason_code in the body it receives. List your subscriptions
with GET /register/public/webhooks.
Fix. Subscribe to the status event for each channel you send on (see
Results of your sends), then act on the
reason_code as Outcomes describes. The checks that run after
the 202 are in Send lifecycle.
No webhook arrives
Likely cause.
- The subscription's
hook_typedoesn't exactly match a name fromGET /register/public/events. A misspelt name is accepted when you subscribe and never receives anything. - Your endpoint didn't answer
2xxwithin 5 seconds, or answered a4xx, which isn't retried. - Deliveries to your endpoint are paused after repeated failures. Events during a pause are dropped.
- The URL resolves to a private or loopback address, which is never called.
How to confirm. Compare GET /register/public/webhooks with
GET /register/public/events. Check your server logs for requests with an
X-Attempt header, and how long you took to answer them.
Fix. Resubscribe with the exact event name, and update your verifier,
because resubscribing issues a new signing secret. Answer 2xx first and do
the work afterwards. After fixing a failing endpoint, reconcile missed
results from the API. See Endpoint pauses.
A webhook arrives but the signature doesn't verify
Likely cause.
- You verify the parsed JSON instead of the raw request bytes.
- You use the wrong secret. Each subscription has its own, and resubscribing replaces it.
- You treat
X-Timestampas milliseconds. It is in seconds. - Your server clock is more than 5 minutes off, so a fresh delivery looks old.
How to confirm. Fetch GET /register/public/account/webhook-signing-secret
and compare the secret for that hook_type with the one your verifier uses.
Log the raw body and the X-Signature and X-Timestamp headers.
Fix. Use the samples in Verify the signature. Fix this quickly: five rejections in a row pause deliveries to your endpoint.
The voicemail shows success but the contact says they didn't get it
Likely cause. reason_code 0 means the message was left in the mailbox
that answered. From there the contact's carrier delivers it, which can take
up to 24 hours, and some carriers filter voicemails as spam. That part is
outside our control. Otherwise the contact hasn't checked their voicemail, or
the number reaches someone else's mailbox, for example after it was
reassigned.
How to confirm. Open the result's proof_of_delivery_url and listen to
the greeting before your message. Check that to in the status event is the
number you meant to reach.
Fix. If the greeting belongs to someone else, update the contact's number. If it's theirs, the message was left in their mailbox; give the carrier up to 24 hours. See Proof of delivery.
Calls fail with 4003
Likely cause. The contact's number was temporarily unreachable. Often their phone carrier is having network problems, which isn't on our side.
How to confirm. Read reason_code on the status event. A few 4003
results spread across carriers are normal.
Fix. Try the call again later. If many sends fail with 4003 at once,
contact support with a drop_id.
The proof of delivery link answers 404
Likely cause. The body's error tells you which case it is:
not_ready: the recording isn't stored yet. The status event can arrive before it is.not_found: the link is wrong (for example cut off when copied), or the voicemail is more than 7 days old, so proof of delivery is no longer available.
How to confirm. Read error and the Retry-After header on the response.
Fix. For not_ready, retry after Retry-After seconds, or subscribe to
contact.rvm.receipt, which fires once the recording is ready. For an
expired link (410 expired), get a new one with
GET /campaign/public/deliveries/{drop_id}/receipt within 7 days of the
voicemail. After 7 days proof of delivery is no longer available; keep your
own copy if you need it longer. See Keep the recording.
A result has no proof of delivery
Likely cause. A result has it when a voicemail system took the call: a
ringless voicemail, voice broadcast or AI call with reason_code 0, 4001
or 4002. A voice broadcast a person picked up has no recording, and an AI
call a person picked up has one only when the agent's Record calls
setting is on. Texts and emails have none. Proof of delivery is available for
7 days after the call.
How to confirm. Check reason_code, campaign_type and the time of the
status event.
Fix. For other outcomes there's nothing to fetch. For an eligible result
under 7 days old with no link, request one with
GET /campaign/public/deliveries/{drop_id}/receipt. If that answers 404,
contact support with the drop_id.
Every test send fails with 4013
Likely cause. Sending to your own number again and again reaches the contact frequency limit, 3 attempts in 3 days by default.
How to confirm. The 4013 status event carries frequency_limit, with
attempts_in_window at or above max_attempts.
Fix. Add your numbers as test numbers on the Dialing rules page. They skip the limit. See Test numbers.
Texts fail with 6009 or 3029
Likely cause.
6009(Unregistered Brand): your account requires a registered brand, and the send had nobrand_id, or itsbrand_idisn't a valid id.3029(Phone Line Has No SMS Campaign): thephone_line_idyou sent from isn't attached to a registered texting campaign.
How to confirm. For 3029, GET /phone/public/lines/{line_id} returns
campaign_id: null for the line.
Fix. For 6009, pass the brand_id of your registered brand
(GET /automation/public/brands), or register a brand and wait for approval.
For 3029, attach the line to an approved texting campaign in the dashboard,
or send from a line that has one. See Texts.
Texts outside business hours fail with 4011
Likely cause. Texts sent outside the contact's allowed hours fail with
4011 (TCPA Hours) instead of waiting. The window follows federal and
state-specific calling hours in the contact's time zone.
How to confirm. Compare the send time with the contact's local time.
Fix. Send inside the window, with a new Idempotency-Key. Schedule
campaigns for business hours. Voice sends are held until the window opens
instead. See Calling hours.
MMS fails
Likely cause. Codes 3032 to 3039 are about the media on a text:
| Code | Cause | Fix |
|---|---|---|
3032 |
media_urls or media_ids malformed, more than 10 files, media with template_id, or media on a voice route |
Fix the request |
3033 |
A media_id isn't on your account, was deleted, or has no uploaded file |
Use an id from GET /media/public/media |
3034 |
A media URL didn't answer 200 in time, or redirected |
Host the file at a public https URL that answers directly, then retry |
3035 |
A file is over 1 MiB, or the files total over 5 MiB | Make the files smaller |
3036 |
A file isn't JPEG, PNG, GIF, WAV or MP3, judged by its bytes | Convert the file |
3037 |
The malware scan flagged a file | Don't send the file |
3038 |
The malware scan didn't finish in time | Retry shortly |
3039 |
The malware scan failed | Retry |
How to confirm. Read reason_code on the contact.sms.status event or
callback_url body.
Fix. As in the table. See MMS.
A voicemail fails with 4001 or 4002
Likely cause. The call reached the contact's mailbox, but it isn't set up
(4001) or is full (4002), so no message could be left.
How to confirm. The result's proof of delivery recording plays the carrier's announcement.
Fix. Retrying the voicemail won't help until the contact sets up or clears their mailbox. Reach them on another channel they've agreed to, after checking their consent for it, for example a text.
Sends fail with 3000 or 5001
Likely cause.
3000(No Funds): your balance is empty.5001(Payment Required): a subscription payment failed. It stops every channel, not only email.
How to confirm. Check GET /campaign/public/balance. For 5001, check
the Billing page in the dashboard.
Fix. For 3000, add funds or turn on auto-recharge, then resend. For
5001, update the card on the Billing page, then resend. See
Balance.
A campaign doesn't start
Likely cause.
- It's waiting for compliance review (
approved: false). - It was never started or scheduled (
campaign_data.statusisnot_started). - It stopped because the balance ran out (
campaign_data.statusisinsufficient_credit). - It's
paused. A campaign that was sending pauses itself when an edit to its message, audio, lists or sending numbers sends it back to review.
How to confirm. GET /campaign/public/campaigns/{id} and read approved
and campaign_data.status. A start that returns approved: false and
started: false means the campaign is in review.
Fix. Create campaigns ahead of time so review can finish, and start them
again once approved is true. Start one with
POST /campaign/public/campaigns/{id}/start; a started: false answer means
nothing was sent. For insufficient_credit, add funds, then start it again.
See Campaigns.
Email isn't sent
Likely cause.
- The send answered
200withdata.success: false, for example because the account has no verified sending domain. - The send answered
403: the key lacksemail:send, or your plan doesn't include email. - The send succeeded, then the email was stopped by your do-not-contact list, an opt-out, missing email consent, the email frequency cap or a daily send limit.
How to confirm. Read data.success and error on the response. For a
campaign email, read reason_code on contact.email.status. An email sent
with POST /email/public/email that was stopped gets no delivered event.
Fix. Verify a sending domain and create a mailbox on it. Record email consent where your account requires it. Wait out the frequency cap, or add your own addresses as test email addresses on the Dialing rules page. See Email and Email-specific outcomes.
Still stuck?
Contact support with whichever of these you have: the meta.request_id from
the response, the drop_id from the result, or your foreign_id.
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.