> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.fluveo.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.fluveo.com/_mcp/server.

# Webhook verification practices

> Events GET list/retrieve are merchant-public contracted-test. Unsupported
> Events methods remain unsupported. WebhookEndpoints and top-level
> PaymentMethods remain unavailable; this is not an endpoint-registration guide.

## Verify raw bytes

Verify the exact request bytes before parsing or re-serializing JSON. Use a
constant-time comparison, enforce the timestamp tolerance, and load the secret
from a secret manager rather than source code.

## Return 2xx quickly

When integrating with any at-least-once webhook provider, acknowledge a valid
request quickly and enqueue slow work. Do not tie request acknowledgement to a
long-running business transaction.

## Make handlers idempotent

Deduplicate on the provider's stable event identifier before applying a side
effect. A retry must not create a second refund, fulfillment, or ledger action.

## Test locally

Check the signature yourself: HMAC-SHA256 over `<t>.<raw body>` with the
endpoint secret, compared in constant time with the `v1=` value of
`Stripe-Signature`, inside a timestamp tolerance (see
[Verify a webhook signature](/cookbooks/verify-a-webhook)). A locally built
fixture proves only your verifier; it does not prove that Fluveo issued a public
endpoint secret or delivered an Event.

See [Webhooks](/webhooks) for the current quarantine and promotion boundary.