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

# Events and the event log

> Every event a partner can receive, which ones reach the webhook, and the feed to poll or catch up from.

Everything that happens to your applications and your account is an event. Each one is written to your event log, and delivered to your [webhook](/partners/webhooks) when you subscribed to it. The log is readable as a feed, so your backend can poll it instead of running a webhook, or catch up after an outage without losing anything.

## The events

Every `service.*` event carries `service_id` and `application_id` (the same value; `service_id` is the legacy name) and your `external_id`.

| Event                      | When                                                                                                  | Extra `data`                                                      |
| -------------------------- | ----------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| `service.approved`         | The application was approved: by you in the console, by Tawked, or at once under the auto-clean mode. | `status: "active"`                                                |
| `service.rejected`         | Rejected, by you or by Tawked.                                                                        | `status: "rejected"`, `reason` when one was given                 |
| `service.suspended`        | Suspended: by you (the endpoint or the console) or by Tawked.                                         |                                                                   |
| `service.resumed`          | Switched back on: by you, or by Tawked lifting its suspension.                                        |                                                                   |
| `service.paused`           | The protection guard paused it after a spike in new destinations.                                     | `reason: "destination_spike"`                                     |
| `service.unpaused`         | The pause was lifted, by you or by Tawked.                                                            |                                                                   |
| `service.review_requested` | A brand or logo change sent a live or rejected application back to review.                            | `status: "review"`, `reason: "brand_changed"` or `"logo_changed"` |
| `service.owner_invited`    | You invited a merchant to own the application.                                                        | `owner: { name, phone, invited_at, expires_at }`                  |
| `service.owner_accepted`   | The merchant signed in with the invited phone and accepted.                                           | `owner: { name, phone, accepted_at }`                             |
| `service.owner_revoked`    | You took the application back from an accepted owner.                                                 |                                                                   |
| `service.archived`         | You archived the application, from the API or the console.                                            | `archived_at`                                                     |
| `service.restored`         | The application came back from the archive: you restored it, or provisioned its `external_id` again.  |                                                                   |
| `balance.low`              | A charge took your balance from at or above your threshold to below it.                               | `balance_halalas`, `threshold_halalas`; no application fields     |

And, opt-in because they come one per code or message, the events a client application would get on its own webhook, with your `external_id` added to the data:

| Event                                                                  | When                                                                                                                                        |
| ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `verification.verified`, `verification.failed`, `verification.expired` | A code was entered correctly, a verification failed, a code expired unused. The data is the verification as `GET /v1/verify/{id}` shows it. |
| `message.sent`, `message.delivered`, `message.read`, `message.failed`  | A WhatsApp message moved to that status. The data is the message as the client webhook carries it, the destination masked.                  |

## Subscriptions

By default every `service.*` event and `balance.low` reach your webhook; the verification and message events do not until you opt in. Change the set in the partner console under **Integration**, or with [`PUT /v1/partner/webhook`](/api-reference/partner/update-the-webhook):

```bash theme={"dark"}
curl -X PUT https://tawked.com/v1/partner/webhook \
  -H "Authorization: Bearer tk_partner_xxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{ "events": ["service.approved", "service.rejected", "service.owner_accepted", "verification.verified"] }'
```

An empty list delivers nothing; `null` resets the default set. [`GET /v1/partner/webhook`](/api-reference/partner/get-the-webhook) shows the current set beside `default_events` and `available_events`. A subscription changes delivery only: lifecycle and balance events are written to the log whatever you subscribed to, while the opt-in events are written only when subscribed, since they are readable through the logs anyway.

<Note>
  Endpoints that existed before subscriptions did keep receiving exactly the seven events they always received (`service.approved`, `service.rejected`, `service.suspended`, `service.paused`, `service.owner_accepted`, `service.owner_revoked`, `balance.low`) until you opt in to more. Nothing new reaches an existing integration on its own.
</Note>

## The feed

[`GET /v1/partner/events`](/api-reference/partner/get-the-event-feed) lists the log oldest first, up to 100 rows a page, each with the event, your `external_id`, the `data` the webhook would carry, and the delivery it produced when there was one.

```bash theme={"dark"}
curl "https://tawked.com/v1/partner/events?since=2026-09-26T00:00:00Z&limit=50" \
  -H "Authorization: Bearer tk_partner_xxxxxxxxxxxxxxxxxxxx"
```

```json theme={"dark"}
{
  "data": [
    {
      "id": "0f4c9c0e-6d2b-4b8a-9c3e-7a1d2e3f4a5b",
      "event": "service.approved",
      "external_id": "store_88",
      "data": { "service_id": "c2a10f3e-8b7a-4d2e-9c1a-1a2b3c4d5e6f", "application_id": "c2a10f3e-8b7a-4d2e-9c1a-1a2b3c4d5e6f", "external_id": "store_88", "status": "active" },
      "created_at": "2026-09-26T09:00:00.000Z",
      "delivery": { "id": "6d2b4b8a-9c3e-4a5b-8f2a-0f4c9c0e7a1d", "status": "delivered", "attempts": 1, "delivered_at": "2026-09-26T09:00:01.250Z" }
    }
  ],
  "next_cursor": "eyJzZXEiOjQyfQ",
  "has_more": false
}
```

* **Resume with the cursor.** `next_cursor` points after the last row you received, whether or not more rows exist now; keep it and pass it back as `cursor` on the next call. `has_more` says whether a page is waiting right now. An empty page answers `null`, so keep the cursor you had.
* **Start from a time.** `since` takes an ISO 8601 date or datetime for the first call, when you have no cursor yet.
* **Filter** with `event` (one event name) and `application` (your `external_id`).
* **Two seconds behind.** Rows younger than two seconds are held back, so a cursor you save never skips a row whose sequence was taken earlier but committed later.
* **At least once.** Treat the feed like the webhook: dedupe by the event `id`.
* **Ninety days.** Events and finished deliveries older than 90 days are pruned.

The feed and the webhook carry the same events with the same `data`; a webhook delivery's `event` header is the same name. Read the [deliveries](/partners/webhooks#deliveries) when you want to know whether a specific webhook call succeeded.
