# Destinations and events

## Holding is the default

A bucket needs no destination. Every capture is stored and readable over MCP and HTTP (`list_captures`, `get_capture`), so the ordinary way to use the platform is for your agent to query when it wants to. Add a webhook only when something else must be told the moment a capture applies. Two more destinations, an email forward and a per-bucket digest, follow once sending is enabled.

## Failed deliveries

Because holding is the default, a failed webhook is not a lost capture: the capture is intact and the failure is a row under its `deliveries`. Find them with `list_captures` and `delivery: "failed"`, fix the endpoint, and `deliver_capture` sends again. There is no separate queue to drain.

## Webhooks

`add_destination` registers a webhook. Attach it to buckets by name or id. When a capture in that bucket is applied (by policy or by approval), it is POSTed:

```json
{
  "version": 1,
  "event": "capture.applied",
  "tenant_id": "…",
  "capture": { "id": "…", "bucket": "customer-orders", "status": "applied", "fields": { "order_number": "A10234", "total": 86.5 }, "confidence": { "order_number": 1, "total": 1 }, "created_at": "…" },
  "message": { "id": "…", "from": "noreply@shop.example", "subject": "New order #A10234", "to": "orders@…", "received_at": "…", "auth": { "spf": "pass", "dkim": "pass", "dmarc": "pass" }, "flags": [] }
}
```

Headers: `X-Mximp-Delivery` (a unique id), `X-Mximp-Event`, and when the destination has a secret, `X-Mximp-Signature: sha256=<hex HMAC-SHA256 of the raw body>`. Verify the signature before trusting the body.

Delivery is one attempt, with the outcome (status code or error) recorded on the capture under `deliveries`; `deliver_capture` tries again on request. The payload carries a `version`; a change to its shape bumps it.

## Events

Every state change is an event: `message.received`, `message.flagged`, `test.promoted`, `test.retired`, `capture.applied`, `capture.task`, `capture.corrected`, `task.created`, `task.resolved`, `bucket.created`, `bucket.updated`, `destination.added`, `delivery.succeeded`, `delivery.failed`, `message.reprocessed`, `policy.updated`. Each carries its actor and a small payload.

`list_events` returns newest first. To catch up from a point you have seen, pass `after=<event id>` and you get the events since, oldest first. An agent that wakes up periodically can use this as its inbox.
