Use signed webhooks to learn about payments and subscription changes. Verify the exact request bytes before parsing or changing anything. Register delivery URLs separately with webhook endpoints.
This function accepts the raw HTTP body, Vatly-Signature header and your endpoint
secret. It returns a validated event; your route must persist it transactionally.
from vatly.webhooks import construct_webhook_event
def example(raw_body: bytes, signature: str, secret: str):
event = construct_webhook_event(raw_body, signature, secret)
return event.id, event.event_name, event.known| Input | Meaning |
|---|---|
raw_body |
Original bytes, not re-serialized JSON |
signature |
Vatly-Signature header: t=<seconds>,v1=<HMAC-SHA256> |
secret |
Endpoint secret, or a sequence of secrets during rotation |
tolerance |
Default 300 seconds of absolute clock skew; keep clocks synchronized |
Invalid/missing signatures or invalid signed JSON raise VatlyInvalidSignatureError.
construct_event() accepts only currently known event names;
construct_webhook_event() also preserves future events with known=False.
from vatly.webhooks import is_valid_webhook_signature
def example(raw_body: bytes, signature: str, secret: str):
return is_valid_webhook_signature(raw_body, signature, secret)| Event field | Meaning |
|---|---|
id |
Signed deduplication authority |
event_name |
For example order.paid or subscription.started |
object |
Full resource snapshot; inspect its resource discriminator |
testmode, created_at |
Mode and event creation time |
Deduplicate signed event.id in the same transaction as business writes and an
outbox. The unsigned Vatly-Event-Id header is only diagnostic. Return success
after commit; let failures produce 5xx for retry. Freshness checks do not replace
deduplication, and deduplication does not establish event ordering.
The SDK supplies no database or route. Use Fluent or Django for storage integration. Do not grant access merely because a browser visited a checkout success URL.