client.webhook_endpoints
Register, manage, test, and replay webhook endpoints. Use this resource to let the server push notifications when an async resource finishes, so you don't have to poll. For verifying incoming deliveries on the receiving side, see webhook signature verification.
Methods
| Method | Endpoint | Returns |
|---|---|---|
client.webhook_endpoints.create(url=..., events=[...]) | POST /v1/webhook_endpoints | New endpoint with signing secret (one-time) |
client.webhook_endpoints.list() | GET /v1/webhook_endpoints | CursorPager of endpoints |
client.webhook_endpoints.retrieve(endpoint_id) | GET /v1/webhook_endpoints/{id} | Single endpoint |
client.webhook_endpoints.update(endpoint_id, **fields) | PATCH /v1/webhook_endpoints/{id} | Updated endpoint |
client.webhook_endpoints.delete(endpoint_id) | DELETE /v1/webhook_endpoints/{id} | None |
client.webhook_endpoints.rotate_secret(endpoint_id) | POST /v1/webhook_endpoints/{id}/rotate_secret | Endpoint with new secret (one-time) |
client.webhook_endpoints.test(endpoint_id) | POST /v1/webhook_endpoints/{id}/test | Test delivery |
client.webhook_endpoints.list_events() | GET /v1/events | CursorPager of event occurrences (the durable event log, not a type catalog) |
client.webhook_endpoints.list_deliveries(endpoint_id, status=..., event_type=..., created_at_gte=..., cursor=...) | GET /v1/webhook_endpoints/{id}/deliveries | CursorPager of past delivery attempts |
client.webhook_endpoints.retry_delivery(endpoint_id, delivery_id) | POST .../deliveries/{did}/retry | The new delivery attempt |
Register an endpoint
The signing secret is returned exactly once in the create response.
Store it in your secrets manager — it's required to verify deliveries.
from thrustlab import Client
client = Client()
endpoint = client.webhook_endpoints.create(
url="https://your-app.example.com/webhooks/thrustlab",
events=["simulation.completed", "simulation.failed",
"sweep.completed", "sweep.failed"],
description="prod handler",
)
print(endpoint["id"]) # wh_2c5tQ...
print(endpoint["secret"]) # whsec_... — store immediately, can't recover
To subscribe to every event, pass events=["*"]. New event types added
later will start delivering automatically.
List events
list_events() hits GET /v1/events — the durable log of every event
occurrence on your account, newest first. There's no separate catalog
endpoint that returns event type names and descriptions; that static list
lives in the event types table in the events guide.
for evt in client.webhook_endpoints.list_events():
print(evt["id"], evt["type"], evt["created_at"])
# evt_2c5tQ... simulation.completed 2026-04-25T18:42:11Z
# evt_2c5sK... simulation.failed 2026-04-25T18:40:02Z
# ... etc.
See the events guide for the full payload shape and
filters (type, resource_id, created_at range).
Update an endpoint
client.webhook_endpoints.update(
"wh_2c5tQ...",
events=["simulation.completed", "sweep.completed"],
description="prod handler — success only",
)
You can patch url, events, description, and enabled (soft pause / re-enable).
Rotate the signing secret
Rotating replaces the endpoint's signing secret immediately — the old secret stops validating signatures the instant this call returns. There's no grace window, so plan the rotation for a low-traffic period and redeploy your handler with the new value right away:
rotated = client.webhook_endpoints.rotate_secret("wh_2c5tQ...")
print(rotated["secret"]) # whsec_... — new value, store + deploy immediately
Deliveries signed with the old secret that arrive after rotation will fail your handler's signature check; the server's normal retry/backoff schedule redelivers them once you're verifying against the new secret. See signature verification for handler-side guidance.
Send a test delivery
delivery = client.webhook_endpoints.test("wh_2c5tQ...")
print(delivery["id"], delivery["status"]) # whd_... pending|succeeded|failed|permanently_failed
The test event has type: "webhook.test" and a synthetic payload; useful
for smoke-testing your handler in staging.
Audit deliveries
for d in client.webhook_endpoints.list_deliveries(
"wh_2c5tQ...",
status="failed",
event_type="simulation.completed",
created_at_gte="2026-04-24T00:00:00Z",
):
print(d["id"], d["created_at"], d["response_status_code"], d["error_message"])
status filter values: pending, succeeded, failed, permanently_failed.
Also filter by event_type (the underlying event's type) and
created_at_gte (ISO-8601); pass cursor= from a prior page's
next_cursor to page forward.
Every dispatch also sends Webhook-Id (the source event ID) and
Webhook-Attempt (1-based attempt number) headers with the POST — see the
webhooks guide for the full
header contract.
Replay a delivery
The server retries failed deliveries automatically on a fixed backoff schedule (immediate, +1 min, +30 min, +2 h, +24 h), permanently failing after the 5th attempt — roughly 26.5 hours after the first. To force an immediate retry (e.g. you just shipped the fix), call:
client.webhook_endpoints.retry_delivery("wh_2c5tQ...", "whd_2c5tQ...")
Only terminal deliveries (succeeded or permanently_failed) can be
replayed — retrying a pending delivery returns 409 delivery_not_terminal.
Delete an endpoint
client.webhook_endpoints.delete("wh_2c5tQ...")
The server stops sending new deliveries; in-flight retries are cancelled.
See also
- Webhook signature verification — verifying incoming requests on your handler
- Webhooks guide — delivery semantics, retry policy, signing scheme
- Event types guide — every event the API emits