# Event types

URL: https://submitator.com/docs/webhooks/event-types

> The 15 events a webhook endpoint can receive, when each one is sent, and what its data holds.

Every delivery's body is an event, the same object `GET /events` returns. Its `type` is always `<object>.<new status>`, and `data.previous_status` holds the status before the change.

listing.live:

```json
{
  "object": "event",
  "id": "evt_5Rt8Wq2Lm7Xn3Kb9Vz1PdJ",
  "type": "listing.live",
  "created_at": "2026-10-08T14:17:01Z",
  "livemode": false,
  "project": "prj_4QzX1m9Lr2Vb7Nc8Tk3HwP",
  "data": {
    "object": {
      "object": "listing",
      "id": "lst_7Hk2Qn4Rt9Vx1Bm6Cz3LdK",
      "livemode": false,
      "project": "prj_4QzX1m9Lr2Vb7Nc8Tk3HwP",
      "directory": {
        "id": "dir_2Lm8Wq3Zk7Rt1Xc5Vb9NdF",
        "name": "BetaList",
        "domain_rating": 73,
        "logo_url": "https://feed.example.net/a/x1Lq7Rt.k9Zm"
      },
      "status": "live",
      "reason": null,
      "action": null,
      "live_url": "https://betalist.com/startups/ledgerly",
      "proof_url": "https://feed.example.net/a/Pf8Kq2Wm.t6Lx9",
      "created_at": "2026-10-03T14:00:00Z",
      "submitted_at": "2026-10-04T09:00:00Z",
      "live_at": "2026-10-08T14:00:00Z"
    },
    "previous_status": "submitted"
  }
}
```

## The event object

| Field | What it holds |
| --- | --- |
| `id` | The event's id, which is also the `webhook-id` header of its deliveries. |
| `type` | One of the types below. |
| `created_at` | When the change was recorded, exact to the second and within about a minute of the change. |
| `livemode` | `true` for live events, `false` for test events. |
| `project` | The project the event is about, or `null` for `ping`. |
| `data.object` | The project, listing, report or webhook endpoint right after the change. |
| `data.previous_status` | The status before the change, or `null` for `project.listings_added` and `ping`. |
| `data.listings_created` | On `project.launched` only: how many listings the launch created. |
| `data.listings_added` | On `project.listings_added` only: how many listings were added. |

Listing times inside `data.object` stay rounded down to the hour, as everywhere else.

## Project events

| Type | Sent when |
| --- | --- |
| `project.launched` | A project launches. It is the launch's only event: `data.listings_created` counts the new listings, all in `pending`, and `data.previous_status` is `draft`. |
| `project.listings_added` | Directories are added to a launched project, by `POST /projects/{project_id}/listings` or by auto-replace. `data.listings_added` counts the new listings. |
| `project.in_progress` | A project moves again after `action_required`, `on_hold` or `completed`. A launch does not send it. |
| `project.action_required` | A project needs you or your client. `data.object.action` says what and who, and `client_message` is ready to forward. |
| `project.on_hold` | Work on a project pauses. `data.object.hold_reason` is `review` while we review the project, which clears without action from you, or `paused`. |
| `project.completed` | No listing is `pending`, `in_progress` or `action_required`, and auto-replace has nothing to add. Listings in `submitted` can still go live. |

## Listing events

| Type | Sent when |
| --- | --- |
| `listing.in_progress` | A listing leaves `pending`, or moves on after `action_required`. |
| `listing.action_required` | A listing waits on you or your client. For `install_badge`, forward `client_message` to your client and verify the badge once it is on the site. |
| `listing.submitted` | The directory has the listing and reviews it. Also sent, with `data.previous_status` `live`, when a live listing goes back to review. |
| `listing.live` | The listing is published. `data.object.live_url` points to it, or is `null` when it went live without a link. |
| `listing.not_accepted` | The directory declined the listing, could not take it, or took a live listing down. `data.object.reason` says which, and the place in the allowance comes back. |
| `listing.cancelled` | We withdrew the listing before it reached the directory. The place in the allowance comes back. |

A new listing sends no event of its own: `project.launched` and `project.listings_added` count them. A listing can go `live` without a `listing.submitted` first.

## Report events

| Type | Sent when |
| --- | --- |
| `report.ready` | A report has been built. Download it with `GET /reports/{report_id}/file` before `data.object.expires_at`, 7 days later. |
| `report.failed` | A report could not be built. Start a new one, and write to support with the event's id if it fails again. |

## The test event

| Type | Sent when |
| --- | --- |
| `ping` | You send a test event with `POST /webhook_endpoints/{webhook_endpoint_id}/test` or the console's test button. It goes to that endpoint only, whatever its `events` filter, and `data.object` is the endpoint. |

## Choose what an endpoint receives

An endpoint's `events` lists the types it receives: types such as `listing.live`, groups such as `listing.*`, `project.*` and `report.*`, or `["*"]` for every type, which is the default. A new endpoint receives the events created after it, not the ones before.

`PATCH /webhook_endpoints/{webhook_endpoint_id}` with a new `events` list replaces the whole list.

## Order and repeats

Deliveries can arrive out of order, and the same event can arrive more than once. Store each `webhook-id` and skip the ones you have handled. Before you act on an event, compare `data.previous_status` with what you stored, or read the object again with its id.

A status can change after it looked final: [How it works](https://submitator.com/docs/how-it-works#corrections) lists the corrections, and each sends its own event. New event types can appear, so answer 2xx to a type you do not know and ignore it.

## Next steps

- [Signatures](https://submitator.com/docs/webhooks/signatures): check that a delivery came from us.
- [Retries and failures](https://submitator.com/docs/webhooks/retries-and-failures): what counts as delivered, and what happens when it is not.
- [How it works](https://submitator.com/docs/how-it-works): the statuses behind the events.
- [Keep your data in sync](https://submitator.com/docs/guides/keep-your-data-in-sync): webhooks and the events feed together.
