> ## Documentation Index
> Fetch the complete documentation index at: https://docs.invokehq.run/llms.txt
> Use this file to discover all available pages before exploring further.

# webhooks

> Use Invoke state verification to confirm webhook delivery before downstream actions run, so your agent never notifies customers about incomplete events.

Webhooks can arrive out of order, be delivered multiple times, or be missed entirely. When your agent triggers downstream actions based on webhook data, Invoke verifies current state before any side effect lands.

## The problem

Your agent receives a webhook for `payment.succeeded` and begins notifying the customer and updating records. But the webhook was a retry of an event that was already processed — or worse, the payment was later reversed. Acting on stale webhook state causes duplicate notifications and incorrect records.

## Solution: verify state before acting on webhooks

Before executing downstream actions triggered by a webhook, use `POST /state/verify` to confirm the event state still matches:

```typescript theme={null}
const result = await invoke.call({
  tool: "notify.send_confirmation",
  params: { customer_id: "cust_123", event: "payment_succeeded" },
  agentId: "notification-agent",
  idempotencyKey: "notify:payment:cust_123:evt_abc"
})

if (result.status === "replan_required") {
  // payment state changed — don't send confirmation
}
```

## Verify payment state before notification

```bash theme={null}
curl -X POST https://api.invokehq.run/state/verify \
  -H "X-API-Key: your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "intent": "send_payment_confirmation",
    "required_fields": ["payment_status"],
    "assumed_state": { "payment_status": "succeeded" },
    "current_state": { "payment_status": "refunded" },
    "conditions": { "payment_status": "succeeded" },
    "on_mismatch": "replan"
  }'
```

Invoke detects the `payment_status` mismatch and returns `replan_required`. The notification never sends.

## Handling duplicate webhook delivery

Use idempotency keys scoped to the webhook event ID to prevent duplicate processing:

```typescript theme={null}
idempotencyKey: `webhook:${event.type}:${event.id}`
```

If the same webhook fires twice, Invoke's idempotency enforcement blocks the second execution.

## Next steps

* [POST /state/verify](/api/state-verify) — full API reference
* [Reconciliation](/concepts/reconciliation) — handle unknown outcomes in webhook-triggered flows
* [Execution Records](/concepts/execution-records) — track every webhook-triggered action
