Webhooks
Webhooks allow Tenuo Cloud to notify your systems when important events occur, such as key creation, revocations, or SRL regeneration.
Supported Events
| Event | Description |
|---|---|
key.created | A new key was created |
key.rotated | A key was rotated |
key.revoked | A key was revoked |
key.suspended | A key was suspended |
key.enabled | A suspended key was re-enabled |
revocation.created | A warrant was revoked |
revocation.deleted | A revocation was removed |
srl.regenerated | The SRL was regenerated |
api_key.created | An API key was created |
api_key.revoked | An API key was revoked |
Creating a Webhook
Navigate to Webhooks
Click Webhooks in the sidebar
Create Webhook
Click Create Webhook
Configure
- URL: The HTTPS endpoint to receive events
- Events: Select which events to receive
- Secret: A shared secret for signature verification
Create
Click Create to enable the webhook
Webhook Payload
Webhook requests are sent as HTTP POST with JSON body:
{
"id": "evt_abc123",
"type": "key.created",
"created_at": "2024-01-15T10:30:00Z",
"data": {
"key_id": "tnu_key_xyz",
"key_type": "issuer",
"name": "Production Issuer"
}
}Signature Verification
All webhook requests include a signature header for verification:
X-Tenuo-Signature: sha256=abc123...Verify the signature in your handler:
import hmac
import hashlib
def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)Always verify webhook signatures before processing events. This prevents attackers from sending fake events to your endpoint.
Managing Webhooks
Test a Webhook
Send a test event to verify your endpoint:
- Click on the webhook
- Click Send Test Event
- Check that your endpoint received the event
View Delivery History
See recent delivery attempts:
- Timestamp
- Event type
- Response status
- Response time
Disable a Webhook
Temporarily stop sending events:
- Click on the webhook
- Toggle Enabled to off
Retry Policy
Failed webhook deliveries are retried with exponential backoff:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | 1 minute |
| 3 | 5 minutes |
| 4 | 30 minutes |
| 5 | 2 hours |
After 5 failed attempts, the webhook is marked as failing and no further retries are attempted for that event.
Best Practices
Use HTTPS endpoints
Always use HTTPS for webhook endpoints to protect event data in transit.
Respond quickly
Return a 2xx response within 30 seconds. Process events asynchronously if needed.
Handle duplicates
Use the event id to deduplicate. Events may be delivered more than once.
Rotate secrets periodically
Update your webhook secret every 90 days for security.
Monitor delivery failures
Set up alerts for webhook delivery failures to catch integration issues.
Example Handler
from flask import Flask, request, abort
import hmac
import hashlib
app = Flask(__name__)
WEBHOOK_SECRET = "your-webhook-secret"
@app.route("/webhooks/tenuo", methods=["POST"])
def handle_webhook():
# Verify signature
signature = request.headers.get("X-Tenuo-Signature")
if not verify_signature(request.data, signature, WEBHOOK_SECRET):
abort(401)
# Process event
event = request.json
if event["type"] == "srl.regenerated":
# Trigger authorizer refresh
refresh_authorizers()
return "", 200