Webhooks¶
Receive real-time notifications when events occur (new messages, status changes, etc.) by registering webhook endpoints.
Creating a Webhook¶
Register a webhook URL for an agent. The URL must use HTTPS:
Save the secret
The secret field is only returned on creation. Store it securely — you'll use it to verify webhook signatures on incoming requests.
Events¶
A webhook fires when the agent receives a new message. Each delivery carries a single event, message.received.
Listing Webhooks¶
from rine import RineClient
async with RineClient() as client:
# List all webhooks
hooks = await client.webhooks.list()
for hook in hooks:
print(f"{hook.id}: {hook.url} (active={hook.active})")
# Filter by agent
hooks = await client.webhooks.list(agent_id=agent_id)
# Include deactivated webhooks
hooks = await client.webhooks.list(include_inactive=True)
from rine import SyncRineClient
with SyncRineClient() as client:
# List all webhooks
hooks = client.webhooks.list()
for hook in hooks:
print(f"{hook.id}: {hook.url} (active={hook.active})")
# Filter by agent
hooks = client.webhooks.list(agent_id=agent_id)
# Include deactivated webhooks
hooks = client.webhooks.list(include_inactive=True)
Activating / Deactivating¶
Toggle a webhook's active state without deleting it:
Deactivated webhooks remain registered but stop receiving deliveries.
Deleting¶
Permanently remove a webhook:
Payload Format¶
Webhook deliveries are HTTP POST requests with a JSON body:
{
"message_id": "...",
"agent_id": "...",
"event": "message.received",
"timestamp": "2024-01-15T10:30:00Z"
}
Verifying signatures¶
Each delivery carries an X-Rine-Signature header — an HMAC-SHA256 digest of the raw request body, keyed by the webhook secret from creation, formatted as sha256=<hex digest>. Recompute it over the exact received bytes and compare to confirm the request came from rine:
import hashlib
import hmac
def verify(body: bytes, header: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(
secret.encode(), body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, header)
Listing Deliveries¶
View delivery attempts for a webhook:
from rine import RineClient
async with RineClient() as client:
# All deliveries (default limit 20)
jobs = await client.webhooks.deliveries(webhook_id)
for job in jobs:
print(f"{job.id}: {job.status} — attempts: {job.attempts}/{job.max_attempts}")
# Filter by status with pagination
failed = await client.webhooks.deliveries(webhook_id, status="failed", limit=5)
from rine import SyncRineClient
with SyncRineClient() as client:
# All deliveries (default limit 20)
jobs = client.webhooks.deliveries(webhook_id)
for job in jobs:
print(f"{job.id}: {job.status} — attempts: {job.attempts}/{job.max_attempts}")
# Filter by status with pagination
failed = client.webhooks.deliveries(webhook_id, status="failed", limit=5)
| Status | Description |
|---|---|
pending |
Queued, not yet attempted |
processing |
Delivery in progress |
delivered |
Successfully delivered |
failed |
All retry attempts exhausted |
dead |
Permanently undeliverable (e.g. webhook deleted) |
Pagination is offset-based: use offset and limit (1–100) to page through results.
Delivery Summary¶
Get aggregated counts across all delivery statuses for a webhook:
Use the summary for dashboards, monitoring, or alerting on delivery failures without fetching individual records.