Skip to main content

Webhooks

Webhooks let your application receive real-time notifications when events occur in Qarion, eliminating the need to poll the API for changes. Instead of your application asking "has anything changed?" repeatedly, Qarion pushes an HTTP POST request to your endpoint whenever something happens that you've subscribed to.

This push-based approach is more efficient, more timely, and consumes no API rate limit quota — making webhooks the preferred integration pattern for event-driven architectures, alerting pipelines, and external system synchronization.

Setup

Register a Webhook

To start receiving events, register a webhook by providing the URL of your receiving endpoint, the list of events you want to subscribe to, and a secret key that will be used for signature verification:

POST /webhooks
{
"url": "https://your-app.com/webhooks/qarion",
"events": ["quality.check.failed", "issue.created"],
"secret": "your-webhook-secret"
}

The secret is never sent in webhook payloads — it's used only to compute the HMAC signature that accompanies each delivery, so your handler can verify that the payload genuinely came from Qarion.

Event Types

Qarion emits events across several domains. Each event type follows a domain.action naming convention:

EventDescription
quality.check.passedQuality check succeeded
quality.check.failedQuality check failed
quality.alert.createdNew alert triggered
issue.createdIssue opened
issue.resolvedIssue closed
product.createdNew product registered
product.updatedProduct metadata changed
request.submittedAccess request submitted
request.approvedAccess request approved
request.rejectedAccess request rejected
meeting.scheduledMeeting created
contract.violatedSLA breach detected

Wildcard Events

If you want to subscribe to all events within a domain without listing each one individually, use a wildcard pattern:

{
"events": ["quality.*", "issue.*"]
}

You can also subscribe to all events across the entire platform — which is useful for audit logging or data lake ingestion — by using a single wildcard:

{
"events": ["*"]
}

Payload Format

Standard Structure

Every webhook delivery follows the same top-level structure, regardless of event type. The payload includes a unique event ID, the event type, a creation timestamp, and a data object whose contents vary by event type:

{
"id": "evt_abc123",
"type": "quality.check.failed",
"created_at": "2026-01-15T10:30:00Z",
"data": {
"check_id": "...",
"check_name": "Freshness Check",
"product_id": "...",
"product_name": "Customer Events",
"space_id": "...",
"details": {
"expected": "24 hours",
"actual": "36 hours"
}
}
}

Issue Created

When an issue is created, the payload includes the issue title, priority, and references to the associated product and reporter:

{
"id": "evt_def456",
"type": "issue.created",
"created_at": "2026-01-15T11:00:00Z",
"data": {
"issue_id": "...",
"title": "Missing transactions",
"priority": "high",
"product_id": "...",
"reporter_id": "...",
"space_id": "..."
}
}

Access Request Approved

Approval events include references to the requester, the product, the role granted, and the approver:

{
"id": "evt_ghi789",
"type": "request.approved",
"created_at": "2026-01-15T14:00:00Z",
"data": {
"request_id": "...",
"requester_id": "...",
"product_id": "...",
"role_id": "...",
"approver_id": "..."
}
}

Verification

Signature Validation

Every webhook delivery includes a X-Qarion-Signature header containing an HMAC-SHA256 signature computed from the payload using your webhook secret. You should always verify this signature before processing the event to ensure the payload hasn't been tampered with and genuinely originates from Qarion:

X-Qarion-Signature: sha256=abc123...

Python Verification

import hmac
import hashlib

def verify_webhook(payload, signature, secret):
expected = hmac.new(
secret.encode(),
payload.encode(),
hashlib.sha256
).hexdigest()

provided = signature.replace("sha256=", "")
return hmac.compare_digest(expected, provided)

# In your webhook handler
@app.post("/webhooks/qarion")
def handle_webhook(request):
payload = request.body.decode()
signature = request.headers.get("X-Qarion-Signature")

if not verify_webhook(payload, signature, WEBHOOK_SECRET):
return Response(status=401)

event = json.loads(payload)
process_event(event)
return Response(status=200)

JavaScript Verification

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');

const provided = signature.replace('sha256=', '');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(provided)
);
}

Note the use of hmac.compare_digest (Python) and crypto.timingSafeEqual (Node.js) — these constant-time comparison functions prevent timing attacks that could otherwise be used to forge signatures.

Retry Policy

If your endpoint doesn't respond with a 2xx status code within 5 seconds, Qarion considers the delivery failed and retries it with exponential backoff:

AttemptDelay
1Immediate
21 minute
35 minutes
430 minutes
52 hours
612 hours

After 6 consecutive failures, the webhook is automatically disabled to prevent further delivery attempts to an apparently unreachable endpoint. You can re-enable it from the API once the underlying issue is resolved.

Managing Webhooks

List Webhooks

Retrieve all webhooks registered for your account:

GET /webhooks

Update Webhook

Modify the event subscriptions or URL of an existing webhook:

PATCH /webhooks/{id}
{
"events": ["quality.*", "issue.*", "request.*"]
}

Disable Webhook

Temporarily disable a webhook without deleting it. This is useful during maintenance windows when your endpoint might not be available:

PATCH /webhooks/{id}
{
"active": false
}

Delete Webhook

Permanently remove a webhook registration:

DELETE /webhooks/{id}

Best Practices

Your webhook handler should respond to deliveries as quickly as possible — ideally within a few hundred milliseconds and no more than 5 seconds. If processing an event takes longer than that, return a 200 response immediately and queue the event for asynchronous background processing. This ensures that delivery timeouts don't cause retries and duplicate processing.

Because the retry mechanism means events may be delivered more than once, your handler should be idempotent — processing the same event twice should produce the same result as processing it once. Use the event id field to detect and deduplicate repeat deliveries.

Always validate the X-Qarion-Signature header before processing a webhook payload. Without signature verification, an attacker could send fabricated events to your endpoint and trigger unintended actions in your system.

Finally, log every incoming webhook event, including whether it was processed successfully or skipped. This audit trail is invaluable for debugging integration issues, understanding event ordering, and diagnosing failed deliveries.