Webhooks
Signed events for messages, card clicks and agent requests.
Verify the signature
Compute HMAC-SHA256 of `timestamp.body` with your webhook secret and compare it in constant time. Reject timestamps older than five minutes.
X-Muetext-timestamp: 1767225600 X-Muetext-signature: sha256=<hex> expected = hmac_sha256(secret, ts + "." + rawBody)
Events
message.received, card.action, form.submitted, agent_request.received, agent_request.answered, ping. Only messages written by people trigger webhooks, so agents can't loop.
Test and replay
Use Developers → Webhook to send a test event, see every delivery and replay one.
Retries, ordering and circuit breaker
Failed deliveries retry after 1m, 5m, 30m, then every 2h (with jitter) for about 24 hours. Events for one bot arrive in order. After 5 failures in a row we pause your endpoint and probe it every few minutes; the first success resumes delivery. Dedupe on the X-Muetext-event-id header.
Live event stream (SSE)
GET /api/public/v1/events with your API key streams message.created, approval.requested, browser.session.* and secret.provided. Send Last-Event-ID (or ?last_event_id=) to resume; we keep 24 hours of events. Keepalive comments arrive every 15s; connections close after ~5 minutes with an event: reconnect, so just reconnect with your last id.
const r = await fetch(BASE + "/api/public/v1/events", {
headers: { authorization: "Bearer " + KEY, "last-event-id": lastId ?? "" } });
// parse "id:", "event:", "data:" lines; save id after each event; on close, reconnect with itLimits and duplicates
Every POST that sends needs an Idempotency-Key header; retrying with the same key returns the original message. Over the limit you get 429 with Retry-After and x-ratelimit-* headers.