# Outbound webhooks (/docs/concepts/webhooks)



A webhook lets your other tools hear about what happens in Domino as it happens. You give Domino a web address, pick the events you care about, and Domino sends a signed message there each time one occurs. For example:

* **Post in your team's Slack** when a member completes a quest.
* **Add a qualified referral to your CRM.**
* **Ship merch** when a member earns a prize.

Each endpoint belongs to one project and environment. Creating one doesn't send earlier activity.

An event says what happened, not who made it happen: it names no operator, and no tool such as the CLI, Console or an [AI assistant connected](/docs/agents/connect) through Domino's MCP server. The project's audit history records the operator.

> [!DEV]
> Subscriptions select exact event type strings. The event is committed with the business operation and queued for each enabled endpoint whose filters match.

## Events and deliveries [#events-and-deliveries]

An event describes one change, such as a completed quest. A delivery is one endpoint's attempt to send that event, including its automatic retries. Replaying a finished delivery sends the same event again, with its original ID and body.

```mermaid
flowchart LR
  Change[Business change] --> Outbox[Transactional outbox]
  Outbox --> Delivery[Signed HTTPS request]
  Delivery --> Receiver[Operator backend]
  Delivery --> Retry[Retry with backoff]
  Retry --> Delivery
```

* **The same event can arrive twice.** Delivery is **at least once**: a timeout can happen after your receiver accepted a request. Each event has an ID, so your receiver can spot a repeat.
* **Order isn't guaranteed**, even for the same member. When it matters, read the current state through the management API.
* **Completed doesn't mean delivered.** A completed quest doesn't mean its Discord role or prize has arrived. `completion.created` and `reward.delivery.failed` describe different changes.

## Scope and recovery [#scope-and-recovery]

Test and live have separate endpoints, signing secrets, subscriptions, and delivery logs. Both send real requests, so point a test endpoint at a test receiver.

If deliveries keep failing, Domino turns the endpoint off. In Console **Settings → Webhooks** you can see why, fix your receiver, turn the endpoint back on, and replay the deliveries Domino kept.

> [!DEV]
> The same controls are available through the management API and CLI. Disabled endpoints receive no newly created events; a queued delivery encountered while disabled becomes `skipped`. A request already in flight can still arrive after disablement.

See [Receive outbound webhooks](/docs/build/webhooks) to configure a receiver and [Webhook reference](/docs/reference/webhooks) for events, permissions, and limits.

## Delete an endpoint [#delete-an-endpoint]

Choose **Delete endpoint** in Console **Settings → Webhooks** and give a reason. Deleting stops new deliveries and retries and frees up room for another endpoint. Its delivery history stays, read-only, under **Deleted endpoints**. A deleted endpoint can't be turned back on, rotated or replayed; create a new one to send again.

> [!DEV]
> Deleting needs publish permission and the endpoint's current revision. An HTTP request already in flight may finish. Use `management.webhooks.state(id)` for the current fence, then `management.webhooks.delete(id, { expectedRevision: endpoint.revision, reason })`. `management.webhooks.states({ cursor, limit })` pages active and deleted endpoints, and `deliveries(id, query)` retains their history. The CLI provides `domino webhooks get ID`, `domino webhooks states` and `domino webhooks delete ID --expected-revision N --reason TEXT`. Mutation inputs accept an optional action ID for identical retries. These controls retain the existing publish permission and credential rules in Test and Live.
