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
{
  "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

FieldWhat it holds
idThe event's id, which is also the webhook-id header of its deliveries.
typeOne of the types below.
created_atWhen the change was recorded, exact to the second and within about a minute of the change.
livemodetrue for live events, false for test events.
projectThe project the event is about, or null for ping.
data.objectThe project, listing, report or webhook endpoint right after the change.
data.previous_statusThe status before the change, or null for project.listings_added and ping.
data.listings_createdOn project.launched only: how many listings the launch created.
data.listings_addedOn 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

TypeSent when
project.launchedA 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_addedDirectories 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_progressA project moves again after action_required, on_hold or completed. A launch does not send it.
project.action_requiredA project needs you or your client. data.object.action says what and who, and client_message is ready to forward.
project.on_holdWork on a project pauses. data.object.hold_reason is review while we review the project, which clears without action from you, or paused.
project.completedNo listing is pending, in_progress or action_required, and auto-replace has nothing to add. Listings in submitted can still go live.

Listing events

TypeSent when
listing.in_progressA listing leaves pending, or moves on after action_required.
listing.action_requiredA 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.submittedThe directory has the listing and reviews it. Also sent, with data.previous_status live, when a live listing goes back to review.
listing.liveThe listing is published. data.object.live_url points to it, or is null when it went live without a link.
listing.not_acceptedThe 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.cancelledWe 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

TypeSent when
report.readyA report has been built. Download it with GET /reports/{report_id}/file before data.object.expires_at, 7 days later.
report.failedA 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

TypeSent when
pingYou 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 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