# Understanding webhook The message status webhook allows you to programmatically track the delivery status of messages you send. To receive the status update notifications in your application, you have to create a webhook configuration using the `webhook` property in the [`send`](/products/sms/enterprise-documentation/developer-documentation/api-references/send) methods. Each SMS message can be linked to a specific [webhook configuration](/products/sms/enterprise-documentation/developer-documentation/wb/wb-configuration). Example: ```json { "destination": "+1234567890", "text": "Your verification code is: 123456", "reference": { "service": "AUTHENTICATION", "action": "2FA", "key": "user-12345" }, "detailed": true, "webhook": { "url": "https://example.com/callback", "authentication": { "type": "NONE" } } } ``` Check the [webhook configuration](/products/sms/enterprise-documentation/developer-documentation/wb/wb-configuration) page for more details. When the message is accepted by the provider, the `send` API returns `200` (`OK`). The message status is immediately changed to `PROVIDER_ACCEPTANCE` and the webhook configuration is created. No webhook notification is sent for the initial `PROVIDER_ACCEPTANCE` status. ### Status Change Notifications The system sends a notification via webhook for every change. ```mermaid sequenceDiagram participant App as Your Application participant Gateway as SMS Gateway participant Provider as Provider participant Carrier as Carrier participant Handset as Handset App->>Gateway: Send an SMS Gateway->>Provider: Send an SMS Provider-->>Gateway: PROVIDER_ACCEPTANCE Gateway-->>App: HTTP Status = 200 Note over Gateway,App: Status = PROVIDER_ACCEPTANCE Provider->>Carrier: SMS Carrier->>Handset: SMS Handset-->>Carrier: Status Callback Carrier-->>Provider: Status Callback Provider-->>Gateway: Status Callback Gateway-->>App: Message Status Webhook ``` The system sends status notifications as HTTP `POST` requests to your configured webhook URL. Example: ``` { "id": "2bf9a88a-29f2-438a-89a1-9a13bf03d03f", "webhookConfigurationId": "2dab9410-d2c8-4b60-bcb0-c5eeb073e71d", "type": "STATUS_UPDATE", "createdAt": "2026-02-12T14:51:00Z", "message": { "id": "b31b6607-9c55-48ba-b145-3f40b809d2d2", "providerAcceptanceAt" : "2026-02-12T14:49:00Z", "statusChangedAt": "2026-02-12T14:50:35Z", "reference": { "service": "DIGITALSIGN", "action": "AUTH", "key": "webhook_3" }, "channel": "SMS", "status": "DELIVERED", "provider": { "name": "MITTO", "id": "ee055245-afa5-4dd0-8d8f-10fec8bf64a3", "status": "DELIVERED", "code": "0" }, "sms": { "segments": 1 } } } ``` The webhook contains the following info: * **id**: Unique identifier of the notification sent via webhook. * **webhookConfigurationId** : Webhook configuration identifier * **type**: Event type (always `STATUS_UPDATE` for status notifications) * **createdAt**: Date and time in ISO 8601 format (e.g., `2026-02-12T14:51:00Z`) * **message**: Message information object: * **id**: Message identifier * **providerAcceptanceAt**: Timestamp when the message was accepted by the provider (ISO 8601 format, e.g., 2026-02-12T14:51:00Z). Corresponds to the initial PROVIDER_ACCEPTANCE status. * **statusChangedAt**: Timestamp of the most recent status change (ISO 8601 format, e.g., 2026-02-12T14:51:05Z). * **reference**: Reference object specified in the send request * **channel** : Delivery channel. Possible values: * `SMS` * `RCS` * **status**: Current delivery status. Possible values: * `SENT` : Request sent by the provider * `DELIVERED` : Message delivered to handset * `REJECTED`: Request rejected by the provider. Message not sent. * `UNDELIVERED` : Message failed to deliver * `READ` : (RCS only) Message delivered and read by recipient * **provider**: Provider information * **name** : Provider name * **id**: Provider's message identifier * **status**: Provider-specific status * **code**: Provider status/error code * **message**: (Optional) Provider error details (e.g. `Number Blocked by Carrier`) * **sms**: SMS-specific information: * **segments** : Number of SMS segments used. Messages exceeding 160 characters (GSM-7) or 70 characters (UCS-2) are split into multiple segments. ### Webhook Retry Mechanism **Expected Response:** - HTTP status code: `200` (OK) - Response timeout: 10 seconds - Response body: Not required (ignored if present) **Retry Behavior:** The system retries failed webhook deliveries using exponential backoff: | Attempt | Wait Time | Cumulative Time | | --- | --- | --- | | 1 | 1 second | 1 second | | 2 | 2 seconds | 3 seconds | | 3 | 4 seconds | 7 seconds | | 4 | 8 seconds | 15 seconds | | ... | ... | ... | | Final | - | 24 hours max | **Retry Triggers:** - HTTP status codes: 4xx (except 400, 401, 403), 5xx - Network errors (timeout, connection refused, DNS failure) - No response within 10 seconds **After 24 Hours:** - Retries stop permanently - Notification is marked as failed - No further attempts are made **Handling Duplicate Notifications** The same notification may be delivered multiple times due to retries or network issues. Use the `id` field to detect and ignore duplicates: ```json { "id": "2bf9a88a-29f2-438a-89a1-9a13bf03d03f", // Use this as idempotency key "webhookConfigurationId": "2dab9410-d2c8-4b60-bcb0-c5eeb073e71d", ... } ``` ### Status Transition Diagram The diagram below shows the status transitions of the messages for which the SMS Gateway sends a status notification request. ```mermaid flowchart LR Start([Send
Message]) --> PA[PROVIDER_ACCEPTANCE] PA --> D1{Sending
Succeeds?} D1 -->|YES| SENT[SENT] D1 -->|NO| REJECTED[REJECTED] SENT --> D2{Delivery
Succeeds?} D2 -->|YES| DELIVERED[DELIVERED] D2 -->|NO| UNDELIVERED[UNDELIVERED] DELIVERED --> D3{Read
Receipt
available?} D3 -->|YES| READ[READ] style PA fill:#87CEEB,stroke:#333,stroke-width:2px style SENT fill:#87CEEB,stroke:#333,stroke-width:2px style DELIVERED fill:#87CEEB,stroke:#333,stroke-width:2px style UNDELIVERED fill:#87CEEB,stroke:#333,stroke-width:2px style REJECTED fill:#87CEEB,stroke:#333,stroke-width:2px style READ fill:#87CEEB,stroke:#333,stroke-width:2px ``` **Delivery Confirmation Limitations**. Status notifications are generally reliable indicators of message delivery. However, they depend on carrier-provided information and are not absolute guarantees. Factors affecting accuracy include: - Carrier reporting delays - Network issues - Handset status (on/off, signal strength) **RCS Channel Variants** When sending via RCS, the flow varies based on availability of RCS and the message expiration: RCS is unavailable when: - Destination country lacks RCS coverage - Destination operator doesn't support RCS - Recipient's device doesn't support RCS Alternative scenarios: - RCS unavailable → automatic fallback to SMS - RCS available but message expires → automatic fallback to SMS In all these cases, the system automatically falls back to SMS and sends the message via that channel. ```mermaid flowchart TD Start[Send RCS Message] --> Check{RCS Available?} Check -->|Yes| Send[Send via RCS] Check -->|No| Fallback1[Fallback to SMS] Send --> Expire{Message
Expires?} Expire -->|No| Delivered[RCS Delivered] Expire -->|Yes| Fallback2[Fallback to SMS] Fallback1 --> SMS[Send via SMS] Fallback2 --> SMS style Start fill:#90EE90 style Delivered fill:#90EE90 style SMS fill:#87CEEB ``` Status Notifications: - The message status webhook sends notifications for the SMS message - In some cases, a `REJECTED` notification for the `RCS` channel may also be sent | Scenario | RCS Status | SMS Status | Webhooks Sent | | --- | --- | --- | --- | | RCS unavailable | - | DELIVERED | 1 (SMS only) | | RCS expired | REJECTED | DELIVERED | 2 (RCS + SMS) | | RCS delivered | DELIVERED | - | 1 (RCS only) | When RCS expires and fallback occurs, you may receive two webhook notifications: 1. First: RCS channel with `REJECTED` status 2. Second: SMS channel with delivery status Use the `channel` field to distinguish between them. Example: ``` { "id": "87b81d7b-d0d8-4561-8caf-de0d14cbf9d1", ... "message": { "id": "3eb93593-4d81-4b9e-ba48-531f66cbcb74", "channel": "RCS", "status": "REJECTED" } } ```