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:

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

This page as Markdown.