client.webhooks verifies the HMAC signature on an inbound webhook and returns a typed WebhookEvent. See Webhooks for the conceptual model and signing algorithm.
No network call is made — verification is local crypto against the whsec_... secret you saved in the developer portal.
Verifying a delivery
| Argument | Type | Default | Description |
|---|---|---|---|
payload | bytes | str | required | Raw request body. bytes is preferred. |
sig_header | str | required | Value of the Spine-Signature request header. |
secret | str | required | The whsec_... secret from the developer portal. |
tolerance | int | 300 | Replay window in seconds. |
WebhookEvent. Raises WebhookSignatureError on any verification failure.
FastAPI example
Flask example
Async
AsyncSpineClient.webhooks.construct_event(...) has the same signature. Verification is CPU-only, so the async variant exists for API-parity with the rest of the client rather than for performance.
WebhookEvent
| Field | Type | Notes |
|---|---|---|
id | str | evt_<uuid>. Use for idempotency. |
type | str | e.g. "run.completed", "run.failed", "webhook.ping". |
created | int | Unix seconds. |
livemode | bool | True in production. |
api_version | str | None | Envelope schema version. |
data | dict | Event payload. data["object"] carries the primary entity. |
Notes
- Clock skew matters. If your server drifts more than 5 minutes from Spine’s clock, deliveries will be rejected as stale. Run NTP.
- Rotation invalidates the previous secret immediately. Update your env var before rotating if you care about strict uptime.
- The SDK accepts multiple
v1=values in one header, so a future dual-signing rotation strategy will be forward-compatible.