> ## Documentation Index
> Fetch the complete documentation index at: https://help.texterchat.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Message Status Changed

> Fires on every delivery-status change of outgoing messages

Subscribe to receive a notification whenever the status of an outgoing message changes, letting you track the full message lifecycle (e.g. "Sent" to "Delivered" to "Seen").

The `messageStatus` field contains one of:

| Value | Meaning                                                         |
| ----- | --------------------------------------------------------------- |
| `0`   | **Sent** - sent from the platform                               |
| `1`   | **Accepted** - accepted by the provider (e.g. Meta received it) |
| `2`   | **Delivered** - delivered to the recipient's device             |
| `3`   | **Seen** - read/opened by the recipient (blue ticks)            |
| `4`   | **Failed** - failed to deliver (e.g. invalid number)            |
| `5`   | **Channel Failed** - system/channel level failure               |
| `6`   | **Deleted** - message was deleted                               |

**Event name:** `messageStatusChanged`\\

**Required token scopes:**

* `Create scenarios`
* `Manage scenarios on behalf of user`

see [Authentication](/api-reference/authentication)

## Subscribe

Send the body below to [Import Subscription](/api-reference/subscribe-to-events/import-subscription-subscribe-to-an-event). You only need to change:

* **`url`** *(required)* - Located under `data.actions[0].params.url`. Replace `{{yourWebhookURL}}` with the destination URL that should receive the events.
* **`asStatus`** - Keep `"active"` to enable the subscription immediately, or `"inactive"` to save it as an inactive revision.

```json Import body [expandable] theme={null}
{
  "data": {
    "version": "v1",
    "name": "(SUB) Messages Status Changed",
    "description": "Sends a webhook for all outgoing messages status changes (e.g., from \"Delivered\" to \"Seen\")",
    "triggerEvents": [
      "app.message.statusRequest"
    ],
    "loaders": {
      "beforeConditions": [
        {
          "name": "chat",
          "alias": "chat",
          "params": {
            "name": {
              "##provide": {
                "provider": "messageStatusRequest",
                "key": "chat.name"
              }
            },
            "accountId": {
              "##provide": {
                "provider": "messageStatusRequest",
                "key": "chat.accountId"
              }
            },
            "idByChannel": {
              "##provide": {
                "provider": "messageStatusRequest",
                "key": "chat.id"
              }
            }
          },
          "confidentialData": false
        }
      ]
    },
    "conditions": [],
    "actions": [
      {
        "name": "request",
        "params": {
          "url": "{{yourWebhookURL}}",
          "method": "post",
          "json": true,
          "data": {
            "eventName": "messageStatusChanged",
            "eventData": {
              "chat": {
                "##provide": {
                  "provider": "chat",
                  "key": "chat"
                }
              },
              "messageStatus": "%messageStatusRequest:status%",
              "error": "%messageStatusRequest:error%",
              "timestamp": "%messageStatusRequest:timestamp%",
              "externalId": "%messageStatusRequest:ids%"
            }
          }
        },
        "confidentialData": false
      }
    ],
    "options": {
      "unorderedActions": false
    }
  },
  "asStatus": "active"
}
```

<Note>
  A `201` response returns your new subscription - save its `_id` to manage it later. You can also add an optional `authorUid` root field (a Texter user UID) to attribute the subscription to a specific user.
</Note>

## Payload

When the event fires, your URL receives an HTTP `POST` with `eventName: "messageStatusChanged"` and the following `eventData`:

<ResponseField name="chat" type="Chat">
  The chat associated with the message. See the [Chat object](/api-reference/objects/chat) for all fields.
</ResponseField>

<ResponseField name="messageStatus" type="number">
  The new status - see the status codes table above.
</ResponseField>

<ResponseField name="error" type="string | null">
  Error message - only present when status is `4` or `5`, otherwise `null`.
</ResponseField>

<ResponseField name="timestamp" type="number">
  When the status changed (Unix epoch milliseconds).
</ResponseField>

<ResponseField name="externalId" type="string[]">
  Unique IDs assigned to the message(s) by the external provider.
</ResponseField>

```json Example payload theme={null}
{
  "eventName": "messageStatusChanged",
  "eventData": {
    "chat": {
      "_id": "69072b0233aea8a47f8bad9f",
      "displayName": "Josh Dun",
      "channelInfo": {
        "name": "whatsapp",
        "id": "972521234567"
      },
      "...": "..."
    },
    "messageStatus": 3,
    "error": null,
    "timestamp": 1768141074000,
    "externalId": [
      "wamid.HBgMOTcyNTIxMjM0NTY3FQIAERgSMDhGRTVGNEY1MTA0Q0NBMzNEAA=="
    ]
  }
}
```

### How to identify the message

Because this event is triggered by the external provider (e.g. Meta/WhatsApp), the payload does **not** contain the internal `message._id`. Instead, it provides the `externalId`. To find the specific message in your system:

1. Take the `_id` from the `chat` object in the payload.
2. Call [Get Messages of a Chat](/api-reference/messages/get-messages-of-a-chat).
3. Find the message whose `channelInfo.id` matches one of the values in the `externalId` array.

## Manage this subscription

| Action             | Endpoint                                                                              |
| ------------------ | ------------------------------------------------------------------------------------- |
| List subscriptions | [List All Subscriptions](/api-reference/subscribe-to-events/list-all-subscriptions)   |
| Pause              | [Inactivate Subscription](/api-reference/subscribe-to-events/inactivate-subscription) |
| Resume             | [Activate Subscription](/api-reference/subscribe-to-events/activate-subscription)     |
| Delete             | [Delete Subscription](/api-reference/subscribe-to-events/delete-subscription)         |
| Debug executions   | [List Scenario Runs](/api-reference/scenarios-advanced/list-scenario-runs)            |
