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_url on the send.
  • The key or secret was wrong. That failure (3007) goes to callback_url only, never to a webhook.
  • You retried with the same Idempotency-Key and 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_type doesn't exactly match a name from GET /register/public/events. A misspelt name is accepted when you subscribe and never receives anything.
  • Your endpoint didn't answer 2xx within 5 seconds, or answered a 4xx, 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-Timestamp as 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.

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 no brand_id, or its brand_id isn't a valid id.
  • 3029 (Phone Line Has No SMS Campaign): the phone_line_id you 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.status is not_started).
  • It stopped because the balance ran out (campaign_data.status is insufficient_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 200 with data.success: false, for example because the account has no verified sending domain.
  • The send answered 403: the key lacks email: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.