Skip to content

SMS Sending Workflow

The Notifications module can send SMS messages through Twilio. The current implementation keeps SMS delivery simple: it sends a raw message body, records the delivery attempt, and exposes a development-only endpoint for manual testing.

How It Works

  1. A caller sends a request to POST /api/notifications/sms/test.
  2. The SmsController validates the payload with the shared sendTestSmsSchema.
  3. The controller dispatches a SendSmsNotificationCommand with the fixed log key manual-test-sms.
  4. The SendSmsNotificationHandler calls the TwilioSmsAdapter, emits structured app logs for provider failures, and persists a NotificationLog with type: SMS.
  5. On success, the API returns the Twilio message SID as providerMessageId.
  6. On failure, the command still writes a failed notification log and returns an application error.

Required Twilio Environment Variables

  • TWILIO_ACCOUNT_SID: Twilio account SID used to authenticate the SDK.
  • TWILIO_AUTH_TOKEN: Twilio auth token paired with the account SID.
  • TWILIO_MESSAGING_SERVICE_SID: Recommended sender configuration when using a Twilio Messaging Service.
  • TWILIO_FROM_PHONE_NUMBER: Fallback sender number in E.164 format when a messaging service is not used.

At least one sender option must be configured: TWILIO_MESSAGING_SERVICE_SID or TWILIO_FROM_PHONE_NUMBER.

Test Endpoint

  • Route: POST /api/notifications/sms/test
  • Availability: development only
  • Rate limit: 3 requests per 5 minutes per IP
  • Request body:
    • to: destination phone number in E.164 format
    • message: SMS body text

Example payload:

json
{
  "to": "+15555550123",
  "message": "Hello from DaraMex"
}

Twilio Notes

  • Twilio expects phone numbers in E.164 format.
  • Trial Twilio accounts can only send to verified recipient numbers.
  • If both sender options are configured, the adapter prefers TWILIO_MESSAGING_SERVICE_SID over TWILIO_FROM_PHONE_NUMBER.

Observability

SMS failures now emit structured OTEL log events through AppLoggerService in addition to the notifications.notification_logs audit row:

  • notifications.sms.provider_misconfigured: emitted when Twilio credentials or sender configuration are missing.
  • notifications.sms.delivery_failed: emitted when Twilio rejects or fails a send attempt.
  • notifications.sms.log_persist_failed: emitted when the NotificationLog row cannot be saved.

These events include templateKey, recipient, channel, any available entity IDs, and Twilio-specific diagnostics when present (providerErrorCode, providerMoreInfo, providerDetails, or missingVariables). This makes provider failures queryable in Loki without inspecting the database directly.

Error Handling

If Twilio is not configured or rejects the request, the API returns an application error, emits a structured app log, and stores the failure reason in notifications.notification_logs.error. For Twilio RestException responses, the stored value is a JSON string that includes message, code, moreInfo, and details, so provider diagnostics are preserved for debugging in both the database row and the OTEL log stream.