When a message can’t be sent or delivered, the API returns a structured error object. Here’s what each error means and what to do about it.
Error structure
All errors follow the same shape:
Some errors include a detail object with field-level information:
Errors at send time
These errors come back synchronously when you call POST /accounts/{account_id}/messages.
opted_out (422)
The recipient has previously replied STOP. Carriers require you to honor opt-outs. Do not attempt to send to this contact until they explicitly re-opt-in by texting START.
Fix: Check contact opt-out state before sending. Subscribe to contact.opted_out webhook events to update your database in real time.
demo_message_limit (403)
You’ve sent 25 messages from the demo number. The demo is for exploration — it’s not for production use.
Fix: Register your business and purchase a phone number.
link_size_limit (422)
A link included in the message body is over 1000 bytes long. This is too long for our shortener to handle, and likely to be broken in the message.
Fix: Remove unnecessary parameters from the link, or try shortening it before sending.
no_phone_number (422)
No from number was specified and the account has no default phone number configured.
Fix: Either set a default phone number on the account in the dashboard, or always pass a from value.
phone_number_not_found (422)
The phone number ID passed as from doesn’t exist or doesn’t belong to this account.
Fix: Confirm the phone number ID is correct and belongs to the account you’re sending from.
Errors at delivery (via webhooks)
These appear in message.failed webhook events after a message was initially accepted. The failure_reason field on the event contains the slug.
unreachable_destination
The recipient’s number is disconnected, out of service, or unreachable on the carrier network.
What to do: Try again later in case the recipient’s phone was turned off or outside of the carrier’s service area. If continued attempts fail to be delivered, consider removing them from your list, as it may be a permanent disconnection.
Permanent undeliverability. When Surge receives invalid_mobile_number or unreachable_carrier for a number, that number is permanently flagged as undeliverable in Surge’s carrier database. All future sends to it (from any account) are cancelled immediately without hitting the carrier. If a number becomes reachable again (e.g., the subscriber reactivates their SIM), the flag clears when a successful delivery is recorded. Stop sending to failed numbers — it has no effect, and your campaign volume quota is still consumed. Contact support if you’d like to opt out of this behavior.
invalid_content_type
An MMS attachment’s content type isn’t supported by the recipient’s carrier or handset.
What to do: Retry with a different format (prefer image/jpeg or image/png) or send the content as a link instead of an attachment.
message_filtered
The carrier’s spam filter blocked the message. This can happen when message content matches spam patterns, and is most typically seen when links included in the message have been flagged by the carrier as potentially spam.
What to do:
- Check that message content matches your registered campaign description and sample messages
- Make sure message content doesn’t use any wording that could suggest a relationship to forbidden messaging categories including alcohol, gambling, drugs, cryptocurrency, etc.
- Avoid link shorteners that aren’t trusted by carriers. If possible use a link domain that is specific to the brand sending the messages.
Complete failure reason reference
All possible values for failure_reason in message.failed events:
Validation errors
validation_error (422)
A request field is missing or invalid. The detail map contains per-field errors.
Fix: Correct the flagged fields. Phone numbers must include the country code with a + prefix (e.g. +18015551234, not 8015551234).
Full error reference
See the Error Reference for the complete list of error types, HTTP status codes, and additional context.