Skip to main content
A trigger is a durable subscription to one endpoint, plus a cursor. Your agent asks for what it hasn’t seen yet; we hold everything until it does. That’s the whole idea. Three properties fall out of it, and they’re the reason to use one instead of polling events.list yourself:
  • You can’t miss an event. It’s stored the moment it lands, whether or not your agent is running.
  • You can’t process one twice. The cursor only moves when you say so.
  • You can’t be fooled. Events that failed signature verification are never handed to you.

How it runs

Capture is ours: it happens the instant a request lands. Consumption is yours: it happens when your agent calls. Note which way the last arrow points — it starts at your agent.
Nothing calls your agent. triggers.wait is a short poll. webhook.co never opens a connection to your agent, starts a session, or interrupts one. An idle MCP client receives nothing, no matter how many webhooks arrive — they queue up durably and wait to be asked for. If you POST to your ingest URL and nothing happens, this is why: something has to be running the loop below.

1. Register the trigger

triggers.create needs the triggers:write scope and an endpoint id. A trigger covers the whole endpoint — there’s no event-type filter:
It returns a trigger record with an id. That id is durable — the subscription outlives any single agent process. Register once; consume from anywhere.

2. Run the loop

Your agent calls triggers.wait, acts on what comes back, then passes nextCursor forward. The cursor is the acknowledgement — advance it only after the work is done, and a crash re-reads instead of dropping.
While caughtUp is false you’re draining a backlog — call again promptly. Once it’s true you’re at the head, and how fast you react is now just how often you call. The exact contract — cursors, ordering, at-least-once, body inlining — is on trigger semantics.

Why this is safe to hand an agent

triggers.wait creates no outbound egress. It’s read-consumption of events the caller can already read — the same data as events.list, but tracked. That’s exactly why triggers are exposed over MCP when subscriptions.* and replayDestinations.* are not: those redirect where an org’s events go, an egress decision an agent must never make. Reading your own events steers nothing.

Trigger semantics

Cursors, at-least-once, ordering, body limits, and the API mirror.