When a message ends, inspect its terminal event and error code before deciding whether to retry or investigate delivery.
What does whatsapp.rejected mean?
Bird stopped the message before dispatch and did not charge it.
Recipient checks and charging can produce a rejected outcome. Use the accompanying code to choose the next action:
| Code | Cause | Next action |
|---|---|---|
undeliverable | No usable recipient address | Correct the recipient |
recipient_suppressed | The recipient is suppressed | Honor the opt-out and investigate consent records |
price_not_found | Bird cannot price the send | Contact support with the message identifier |
insufficient_balance | The wallet cannot fund the send or the organization cannot be charged | Resolve billing before sending again |
An unpriced send is refused rather than treated as free. Repeating the unchanged request does not supply the missing price.
The rejection timestamp uses the original acceptance time. Use it consistently in reports so queue delay does not move the rejection into a later reporting period.
What does whatsapp.failed mean?
The message failed during sending or delivery, with its cause recorded in the error details.
Meta can report failure through a delivery callback. It can also refuse Bird's send request before accepting the message for delivery.
Bird records internal_error when the sending number has no usable credential or processing exhausts its retries. meta_error_code is Meta's recorded error code. This Bird code carries none.
A retry exhaustion can include transport errors or upstream failures. Do not infer from internal_error alone that Meta never received a request.
Check the description and sending number's connection. Give support the message identifier when the cause remains unclear.
A failure can occur after charging. Inspect the message's cost instead of assuming that every unsuccessful send was free.
Why does undeliverable appear on both events?
On a rejection, Bird could not address the recipient. On a failure, it is Bird's normalized result for a Meta refusal.
The error code is broader than a statement that the phone cannot receive messages. Bird also uses undeliverable when a Meta code has no more specific mapping.
Read meta_error_code for Meta's recorded code and description for the accompanying explanation. A failure reported without error details still receives undeliverable.
Other normalized failure codes identify more specific problems:
| Code | What to investigate |
|---|---|
service_window_expired | Whether free-form content was sent outside the service window |
rate_limited | Meta's sending or recipient limits |
media_rejected | The media asset Meta refused |
internal_error | Bird's recorded processing or sending failure |
Preserve unfamiliar codes in your logs. The code set can grow, so an unknown value should not invalidate an otherwise usable event.
How should my event handler interpret the outcome?
Branch on the event type and its error code together.
A rejected message does not progress to a sent event. A failed message needs its error details to distinguish an internal failure from Meta's response.
Keep delivery status separate from engagement. A whatsapp.read event records a read without replacing the message's delivery status.
Bird emits its own whatsapp.sent after the send succeeds. It does not create another event from Meta's separate sent-status callback.
Template review uses a different set of statuses. Inspect the template's language when approval is the problem, rather than these message outcomes.
What should I do before another send?
Correct the recorded cause before sending another message.
For service_window_expired, use an approved template or wait for the customer's message to reopen the service window.
For suppression, honor the recipient's choice. Removing an opt-out would ignore the recipient's preference and create a compliance risk.
For a billing or sender-connection problem, resolve that account condition first. Preserve the original message identifier so support can inspect the unsuccessful attempt.
If the number or Business Account is restricted or banned, follow the account restrictions and appeals steps before retrying.
For an uncertain transport failure, investigate before creating another message. A new send can duplicate a request whose outcome was not observed.
In short
A rejection is not charged.
Bird stops the message before dispatch when recipient checks or charging prevent the send.
A failure can come from Bird or Meta.
Inspect the recorded error before deciding where to investigate.
internal_errordoes not carry a Meta error code.Interpret the event and code together.
undeliverableappears on both events. Its meaning depends on where the message stopped.Choose recovery from the cause.
Correct the recipient, account, content or timing problem before attempting another send. Keep unfamiliar codes for investigation.