Skip to main content

The official Python SDK for the webhook.co API — a typed client with retries, cursor pagination, idempotency, and secret redaction.

Project description

webhook.co Python SDK

The official Python SDK for the webhook.co API. A typed client with the hardening you'd otherwise hand-roll: bearer auth, bounded retries with jitter, cursor pagination, idempotency, and secret redaction — with pydantic v2 models generated from the same OpenAPI contract the API is built on.

Python 3.10+. Built on httpx.

Install

pip install webhook-co

Quickstart

import os
from webhook_co import WebhookClient

client = WebhookClient(api_key=os.environ["WEBHOOK_API_KEY"])

# Create an endpoint. The ingest URL is a credential, but it is NOT one-time.
endpoint = client.endpoints.create(name="orders-prod")
print(endpoint.ingest_url)

# Lost it? Read it back — the token is sealed at rest, so there is nothing to lose and no need to
# rotate (rotating would revoke the live URL and break every sender still posting to it).
revealed = client.endpoints.reveal_ingest_url(endpoint.id)
print(revealed.ingest_url)

# List events for that endpoint (auto-paginates).
for event in client.events.list(endpoint.id):
    print(event.id, event.provider, event.verification_state)

The API key is a whk_-prefixed token from your dashboard. Keep it server-side — this SDK never prints it, but it's still a credential.

Responses come back as validated pydantic models, so attributes are typed and snake_cased (endpoint.org_id, endpoint.created_at).

Pagination

List methods return a Paginator you can iterate directly — it follows the cursor for you:

for endpoint in client.endpoints.list(name="prod"):
    print(endpoint.id)

# Collect everything (careful with large result sets):
failed = client.deliveries.list(status=["failed"]).collect()

# One page at a time (e.g. to build your own UI):
page = client.endpoints.list_page(limit=50)
print(page.items, page.next_cursor)

Errors

Every failure is a WebhookError subclass, so you can narrow with except — no string matching:

from webhook_co import (
    WebhookRateLimitError,
    WebhookNotFoundError,
    WebhookAuthenticationError,
)

try:
    client.endpoints.get(endpoint_id)
except WebhookNotFoundError:
    ...  # 404 — no such endpoint
except WebhookRateLimitError as err:
    print(f"retry after {err.retry_after_s}s")
except WebhookAuthenticationError:
    ...  # 401 — the key is invalid, expired, or revoked

Each error carries code (a stable capability-error string), status (the HTTP status), and request_id when the server sent one.

Retries & idempotency

The client retries idempotent requests on transient failures (429/502/503/504 and network errors) with capped exponential backoff and jitter, honouring Retry-After. It never blind-retries a non-idempotent write — creating an endpoint, rotating a secret, or an un-keyed replay won't be sent twice by the SDK. Replays carry an idempotency key (auto-generated if you don't pass one), so those are safe:

import uuid

client.events.replay(
    event.id,
    target={"kind": "destination", "destinationId": destination_id},
    idempotency_key=str(uuid.uuid4()),
)

Tune the budget per client:

client = WebhookClient(api_key, max_retries=4, timeout_s=15)  # defaults: 2 retries, 30s

Payloads

events.get_payload decodes the wire envelope and hands you the exact bytes (length-checked, so a truncated body raises rather than silently short-reading):

payload = client.events.get_payload(event.id)
print(payload.content_type, len(payload.body))  # payload.body is bytes

Configuration

Argument Default Notes
api_key Required. A whk_ API key.
base_url https://api.webhook.co Must be https (loopback http allowed for self-host / dev).
http_client a new httpx.Client Pass your own for custom transports/proxies.
max_retries 2 Retries after the first attempt, idempotent requests only.
timeout_s 30 Per-request timeout (seconds), per httpx connect/read/write phase.
refresh_auth Hook returning a rotated bearer on a 401 (OAuth flows).
on_debug Redacted, single-line diagnostics — never the raw key.

Use it as a context manager to close the underlying connection pool:

with WebhookClient(api_key) as client:
    client.whoami()

API surface

endpoints (list · list_page · get · create · delete · rotate · provider_secrets add/list/revoke) · events (list · list_page · get · get_payload · tail · replay) · deliveries (list · list_page · get) · replay_destinations (create · list · delete · enable · set_ordered · rotate_signing_secret · list_signing_secrets) · subscriptions (create · list · delete) · audit.verify · whoami.

License

Apache-2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

webhook_co-0.2.1.tar.gz (38.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

webhook_co-0.2.1-py3-none-any.whl (25.7 kB view details)

Uploaded Python 3

File details

Details for the file webhook_co-0.2.1.tar.gz.

File metadata

  • Download URL: webhook_co-0.2.1.tar.gz
  • Upload date:
  • Size: 38.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for webhook_co-0.2.1.tar.gz
Algorithm Hash digest
SHA256 4fd0eae06e1d5a4444468df362626c862c89d37db750ec75dea88424c24286a9
MD5 175da88a9e582361652db88b74738b07
BLAKE2b-256 2d43f2ea7b0c87d4e3f2eead5565db30cde621bfa8801b2ec58fdceafd3463ba

See more details on using hashes here.

File details

Details for the file webhook_co-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: webhook_co-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 25.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for webhook_co-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 33cf482dd248e9bd8f9ca0c5990547a2f6b3078e8d92e82a9cd2e45584b0fc97
MD5 2748482cda15a4e676e1127872f104f4
BLAKE2b-256 cc0fea7dab3b4b5da407d2fd14b1db4be26496225b3441baee61443b5d2fd769

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page