123eworld Knowledge Hub → Transactional SMS → Page 129
Transactional SMS API Delivery Status State Machine: Accepted, Submitted, Delivered, Failed and Expired
A developer reference for modeling SMS message lifecycle states, valid transitions, provider callbacks, terminal states, duplicate events, out-of-order events, reconciliation and API status design.
Why a state machine is useful
Messaging status is not a simple true-or-false value. A message can be accepted internally, submitted to a provider, awaiting delivery evidence, delivered, failed or expired. Explicit states prevent contradictory updates.
Accepted state
Accepted should mean the API has validated and durably recorded the logical message. It should not be presented as proof that a mobile network has received the SMS.
Submitted state
Submitted indicates that the platform has handed the message to an external provider or route. Provider acceptance and final handset delivery remain separate concepts.
Delivered state
Delivered should be assigned only when trustworthy provider evidence indicates successful delivery according to the platform's contract.
Failed state
Failure should carry a stable category or reason code. A temporary provider timeout is different from an invalid destination or a permanently rejected sender configuration.
Expired state
Messages with a defined validity period can become expired when they can no longer be usefully delivered. Expiry is a terminal business state distinct from technical failure.
Transition rules
Define allowed transitions explicitly. For example, delivered should normally be terminal, while an intermediate submitted state can receive multiple provider updates without creating contradictory history.
Out-of-order events
An older provider event may arrive after a newer state. The consumer should use event timestamps, provider sequence data or monotonic state rules to prevent a stale event from moving a message backward.
Status history
Keep an event history or transition record when auditability matters. The current status can then be derived or maintained as a projection of the history.
Client-facing status API
Expose stable business states rather than leaking every provider-specific status. Provider diagnostics can be supplied separately as normalized reason codes or raw references where appropriate.
Reconciliation
Periodic reconciliation can identify messages stuck in non-terminal states and compare internal records with provider evidence.
Implementation checklist
Define states, valid transitions, terminal conditions, provider mapping, ordering rules, history, reconciliation and API status semantics.
State ownership
The messaging platform should have one authoritative state model even when several providers report different terminology. Provider adapters can translate external events into internal transitions, but they should not independently rewrite business state rules.
Terminal states
Define which states are terminal and whether an administrative correction can reopen them. Delivered, permanently failed and expired are commonly terminal for ordinary processing. If a correction is needed, create a new business event rather than silently rewriting history.
State transition concurrency
Two callbacks can be processed simultaneously. Database constraints, compare-and-update logic or an event-sourced transition model should prevent invalid state changes caused by race conditions.
Stuck-message detection
Messages remaining in submitted or pending state beyond a reasonable threshold should be identified by a reconciliation process. A stuck-state alert is often more valuable than simply watching API error rates.
Historical evidence
Store provider references and transition timestamps so support teams can distinguish a message that was never submitted from one submitted successfully but lacking final delivery evidence.
Developer reference rule
Treat message status as a state machine with explicit transition rules, not as a mutable text field updated by whichever callback arrives last.
State transition authority
The state transition service should be the only component permitted to change the canonical message status. Provider adapters produce normalized events; they should not directly update customer-visible status fields through independent database writes.
Monotonic state rules
Where states have an obvious progression, a newer terminal state should not be replaced by an older intermediate state. A delivered message should not return to submitted simply because a delayed provider event arrived afterward.
Unknown and pending
Unknown should be used carefully. If a provider has not supplied evidence yet, pending may be more accurate. Unknown is useful when evidence is contradictory, unsupported or permanently unavailable.
State history retention
Retain transition history long enough to support billing disputes, support investigations and provider reconciliation. The retention period should match the platform's operational and contractual requirements.
API filtering
Status endpoints should allow filtering by current state and time range, while large historical queries should be paginated. This prevents reporting workloads from overwhelming the transactional database.
Practical scenario
A provider first reports accepted, then delivered, followed by a delayed 'pending' event. The state machine keeps delivered as the current terminal state while retaining the delayed event in history for investigation.
Failure scenario
A delivered event arrives after an older pending event. The state machine keeps delivered as the current status while recording the older event in history. This prevents a delayed network message from making the customer-facing status less accurate.
Operational checklist
Verify valid transitions, terminal states, stale-event handling, concurrent updates, state history, stuck-message detection and reconciliation jobs.
Developer takeaway
A status model should make invalid transitions impossible or harmless. That is the central benefit of treating message lifecycle as a state machine.
Design review
Review state transitions whenever a provider, message type or delivery outcome is added. New states should have clear entry conditions, exit conditions and customer-facing semantics.
Reference note
Keep provider status history separate from the normalized business state. This preserves external evidence without forcing customers to understand every provider's vocabulary.
Final standard
Message state should remain internally consistent even when external events are delayed or contradictory.
Implementation example
A message progresses from accepted to submitted to delivered. A duplicate submitted event arrives after delivery. The state machine records the event but does not move the canonical state backward. The API continues reporting delivered while history preserves the complete sequence.
Testing standard
Generate concurrent and out-of-order status events, duplicate callbacks and delayed provider evidence. Confirm that terminal states remain protected and history remains complete.
Final checklist
Confirm status transitions are atomic and invalid backward movement cannot corrupt customer-visible state.
Capacity example
A message-state service may receive multiple callbacks for the same message. Atomic transition checks prevent concurrent workers from overwriting each other's decisions and keep the canonical state consistent under high event volume.
Support guidance
When a status appears to move backward, inspect event timestamps and provider references. The issue may be an out-of-order callback rather than a real reversal in delivery state.
Reference rule
Current state and historical events should be related but not confused.
Production readiness
Run concurrent state updates for the same message and verify that the canonical state remains valid. Include delayed events and terminal-state updates in the test set.
Documentation requirement
Document every public status, its meaning and whether it is terminal. Clearly state that accepted or submitted does not necessarily mean handset delivery.
Long-term maintenance
Add a regression test whenever a new provider status or lifecycle state is introduced. State machines become fragile when new transitions are added without explicit rules.
Architecture review
For high-volume platforms, keep state transitions on a durable transactional path and treat provider callbacks as inputs to that path. This prevents independent callback workers from creating conflicting message states during bursts.
Final implementation note
Expose normalized status codes through the API, retain provider evidence for diagnostics and keep state transitions idempotent under duplicate delivery.
Final production rule
Do not allow delayed or duplicate provider events to move a message into an invalid state.
Reference summary
A well-defined state machine gives developers a stable contract even when providers produce asynchronous, duplicated or out-of-order events.
Developer implementation detail
Store the current state with a version or transition sequence where practical. A worker can then update the state only if the record is still at the expected version. This optimistic concurrency pattern prevents two callbacks from silently overwriting each other and creates a clear retry path when a race occurs.
Final check
Confirm terminal states remain terminal unless an explicit administrative correction creates a new business operation.
Quality standard
Keep state transitions atomic, observable and testable under concurrent callback processing.
Final rule
Protect terminal state integrity.
Need transactional SMS integration?
123eworld.com provides Bulk SMS and API-based business communication solutions for enterprises and software applications.