123eworld Knowledge Hub → Transactional SMS → Page 147
Transactional SMS API Error Handling: HTTP Status Codes, Error Objects, Reason Codes and Developer Recovery
A practical guide to designing stable, actionable SMS API errors, including validation, authentication, rate limits, provider failures, retries and correlation IDs.
Why generic errors are expensive
A response such as 'SMS failed' creates another support ticket instead of solving the problem. Developers need to know whether the request was malformed, authentication failed, a quota was exceeded, a provider rejected the destination or the outcome is uncertain. Error responses should therefore be designed as recovery instructions. The human message helps people understand the problem, while a stable machine-readable code lets software make a safe decision.
HTTP status versus message status
HTTP status describes the API interaction; it should not be used as a substitute for handset delivery state. A successful asynchronous submission can return an accepted response while the actual SMS remains queued. Delivery status is a separate lifecycle. Keeping these concepts separate prevents developers from treating a 200 or 202 response as proof that the recipient's phone received the message.
A useful error object
A structured error can contain a stable code, message, field reference, correlation ID and retry guidance. The code is the value application logic should use. Do not force developers to parse English text. Human wording can be improved without breaking integrations, while the machine code should remain stable within a supported API version.
Validation failures
Validation errors should identify the problematic field and a useful reason. Examples include missing destination, malformed country code, unsupported sender, empty message text, invalid template variables or an invalid scheduled timestamp. Return enough information to correct the request but do not disclose internal implementation details that could create a security issue.
Authentication and authorization
Authentication and authorization errors are different operational problems. An invalid credential requires credential repair or rotation, while a valid credential attempting a resource outside its permission scope requires an authorization decision. Responses should remain deliberately concise so attackers cannot use error details to enumerate valid credentials or internal resources.
Rate-limit errors
A rate-limit response should make clear that the request was rejected because a configured limit was reached. Where appropriate, provide a retry-after signal. Clients should use bounded backoff rather than immediate loops. Otherwise a rate-limit error can create more traffic and extend the overload. The platform should also distinguish tenant limits from system-wide capacity protection when those distinctions are useful to developers.
Provider normalization
Provider responses are often inconsistent. One provider may return a numeric error, another a textual reason and another a temporary HTTP failure. Do not expose this raw vocabulary as the public API contract. Normalize it into stable categories such as invalid destination, rejected sender, temporary provider failure or uncertain submission. Preserve the original provider evidence internally for support and reconciliation.
Retryable versus permanent
A central responsibility of an error contract is telling the caller whether changing the request is necessary. An invalid phone number should not be retried unchanged. A temporary dependency failure may be retriable. An idempotency conflict may require returning the original operation rather than creating another one. Error codes should map clearly to these recovery decisions.
Correlation IDs
Every failed request should carry a correlation ID or request ID. Support can use that identifier to locate gateway logs, application events, queue records and provider attempts. This is especially valuable for timeouts because the customer may not know whether the platform accepted the message. The correlation ID turns a vague complaint into a searchable transaction.
Documentation and examples
Maintain an error catalogue with code, HTTP status, meaning, cause, retry guidance and example response. Include examples for validation, authentication, rate limits, provider uncertainty and idempotency. Keep documentation versioned. An error contract that is documented separately from the implementation can drift and create confusion.
Testing error contracts
Automated contract tests should assert the status code, error code, field reference and retry classification. Test errors as carefully as successful responses. Refactoring can accidentally turn a useful validation code into a generic server error, and a client may then start retrying a request that should have been corrected.
Operational safety
Error responses should never contain API keys, message bodies, secrets or unnecessary personal information. Detailed diagnostics belong in protected logs. If a provider returns sensitive content, store only what is required for reconciliation and redact it from customer-facing responses.
Developer takeaway
A good error response answers three questions: what happened, can I safely retry, and what must I change? If a developer can answer those questions without opening a support ticket, the API error design is doing its job.
Implementation pattern
Define an error catalogue as versioned configuration or code. Map validation exceptions, authentication failures, provider responses and internal conditions to stable public reason codes. Keep raw provider evidence in protected diagnostics while the API exposes normalized categories.
Recovery matrix
For each public error code, define whether the client should correct the request, retry later, retry with the same idempotency key, authenticate again or contact support. This matrix should be part of automated tests and developer documentation.
Production rule
Do not make customers parse human-readable error messages to decide whether an SMS should be retried.
Operational reference
An error catalogue should be reviewed whenever provider integrations change. A provider-specific code should never accidentally become a permanent public contract. Normalize it, preserve the raw evidence internally and document the customer-facing recovery behaviour.
Error taxonomy
A stable taxonomy can separate client errors, authentication errors, authorization errors, throttling, dependency failures and uncertain outcomes. Within each category, reason codes should be specific enough to guide recovery without exposing sensitive internals. Keep the taxonomy small and intentional; hundreds of poorly defined codes make the API harder to use.
Retry guidance
Retry advice should consider idempotency. A temporary provider failure can often be retried, while an uncertain submission should be retried only with the same logical identity. Documentation should show a complete example rather than saying simply 'retry on 5xx'. A client that retries every server error immediately can create a retry storm.
Support workflow
Support teams should be able to search a correlation ID and see the public error code alongside internal diagnostics. This lets them explain the result without asking customers to resend sensitive information. If the error is caused by configuration, the support view should identify the relevant tenant configuration revision.
Regression protection
Add contract tests whenever an error code is introduced or changed. Test that the same invalid request continues to return the documented code across refactoring and deployment. Error compatibility is particularly important for SDKs that automatically classify failures.
Error ownership
Every public error code should have an owner responsible for its meaning and lifecycle. When the underlying implementation changes, the owner verifies that the public classification remains correct. This prevents internal refactoring from accidentally changing customer recovery behaviour.
Error severity
Not every error is an incident. A single invalid phone number is a normal client correction, while a sudden increase in dependency failures may indicate a platform incident. Dashboards should distinguish expected client errors from infrastructure symptoms.
SDK handling
SDKs can translate stable API errors into language-specific exceptions while preserving the original code and correlation ID. This gives developers a convenient programming model without losing the machine-readable contract.
Final engineering rule
Keep error codes stable, recovery guidance explicit and sensitive diagnostics private. A predictable error contract is a core part of a reliable API.
Production reference
Production teams should review error distributions by tenant, endpoint and provider. A sudden increase in one validation error may indicate a customer integration problem, while a sudden increase in dependency errors can indicate a platform or provider incident. Keeping these categories separate makes operational response much faster.
Production reference
The error contract should also be stable during maintenance. If a database outage changes a useful dependency error into a generic HTML gateway page, client applications may retry incorrectly. Gateways should therefore preserve the documented JSON error shape even when upstream services are degraded.
Production reference
Finally, document examples for developers using common languages and frameworks. A short example showing how to inspect the stable code, correlation ID and retry classification is often more valuable than a long conceptual description.
Continue through the 123eworld Knowledge Hub
Explore the complete 123eworld Knowledge Hub for practical SMS API, transactional messaging, queue, security and developer architecture guides.
Visit 123eworld.com for messaging and digital communication services.