Skip to main content

hooka-relay-python

Python 3.11+ client for Hooka Relay.

pip install hooka-relay-python
import os
from hooka_relay import HookaRelay
relay = HookaRelay(os.environ["HOOKA_API_KEY"])
event = relay.send_event({
    "type": "order.created", "payload": {"orderId": "123"},
    "idempotencyKey": "order-123-created",
})
print(event["id"])

Use an ingest-only or existing unscoped application key. Optional base_url and timeout (seconds, default 30) configure the client. Remote URLs require HTTPS; redirects are rejected to avoid credential forwarding. There are no implicit retries. Retry ambiguous network failures with the same explicit idempotencyKey; omitted keys are generated by the server, so resending without one can create another event.

HookaError exposes status, parsed body, and retry_after. Rate limits return 429, oversized requests 413, and schema failures 400 with failures: [{path, message}]. Payload limits: 256 KiB / JSON depth 32. TypedDict models are generated from the repository's OpenAPI contract; runtime server validation remains authoritative.

Verify and queue, then drain

verify_webhook(raw_body, headers, secret) uses the Standard Webhooks reference library. It raises on invalid signatures, a changed ID/body, or timestamps outside five minutes. Pass raw bytes and the displayed whsec_ secret. During rotation either old or new key verifies the dual signatures. Existing LEGACY endpoints must explicitly migrate after their receiver supports Standard Webhooks.

Minimal queue-and-drain receiver using the standard library (put a production HTTP server/reverse proxy in front of a real deployment). A bounded queue rejects overload with 503; accepted work is processed outside the request.

import os
import logging
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from queue import Queue, Full
from threading import Thread
from hooka_relay import verify_webhook

queue = Queue(maxsize=1000)

def process_event(item):
    print(item["id"], item["payload"])

def drain():
    while True:
        item = queue.get()
        try:
            process_event(item)
        except Exception:
            logging.exception("Persist failed item to your dead-letter store: %s", item["id"])
        finally:
            queue.task_done()

class Receiver(BaseHTTPRequestHandler):
    def do_POST(self):
        if self.path != "/webhook":
            self.send_error(404)
            return
        try:
            length = int(self.headers.get("Content-Length", "-1"))
        except ValueError:
            self.send_error(400)
            return
        if length < 0 or self.headers.get("Transfer-Encoding"):
            self.send_error(411)
            return
        if length > 262144:
            self.send_error(413)
            return
        try:
            headers = {k: self.headers.get(k, "") for k in ("webhook-id", "webhook-timestamp", "webhook-signature")}
            payload = verify_webhook(self.rfile.read(length), headers, os.environ["HOOKA_SIGNING_SECRET"])
        except Exception:
            self.send_error(400)
            return
        try:
            queue.put_nowait({"id": headers["webhook-id"], "payload": payload})
        except Full:
            self.send_error(503)
            return
        self.send_response(202)
        self.end_headers()

Thread(target=drain, daemon=True).start()
ThreadingHTTPServer(("127.0.0.1", 8080), Receiver).serve_forever()

The queue is volatile: a crash loses already acknowledged work. For production, persist to a durable inbox/queue before acknowledging. Atomically deduplicate the authenticated webhook-id with business changes. Persist processing failures for retry or dead-letter handling; a log entry is not durable recovery.

Event ordering

Ordering is not guaranteed across retries or replay generations. The queue-and-drain example above separates acknowledgement from slow processing and isolates failures. It cannot restore producer order; apply per-entity sequence/version checks if required.

Interactive API reference · Security and migration

Release files for hooka-relay-python 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hooka-relay-python 1.0.0
File Size Uploaded
hooka_relay_python-1.0.0.tar.gz 6.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hooka-relay-python 1.0.0
File Interpreter ABI Platform
hooka_relay_python-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 12.7 kB

Release files / hooka_relay_python-1.0.0.tar.gz

Download URL hooka_relay_python-1.0.0.tar.gz
Size 6.5 kB
Tags Source
SHA-256 checksum
How to use checksums
1b864bc82a6b543b53fb63911990c32f8e6472b8778df2c0cc45ae5418655eb6
BLAKE2b-256 checksum
How to use checksums
ae780c9c0f14af8fbf4e7d6aaa58e42e675eacc991698b6ee917d2dd9f77885e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / hooka_relay_python-1.0.0-py3-none-any.whl

Download URL hooka_relay_python-1.0.0-py3-none-any.whl
Size 6.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ad994ac9fae986d3cbb7e3d71d863355cf334e186f9db87244f12fb8c8694561
BLAKE2b-256 checksum
How to use checksums
f360e73f83c217eef2a1a8ffe6269b63d1ea3ac4d113e5c194697f6c5f4f50e1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

2.0.0

2 release files

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page