Skip to main content

Webhooks API

The Webhooks API manages outbound webhook subscriptions for platform events in a space. Qarion sends JSON payloads to HTTPS endpoints, signs each delivery with HMAC-SHA256, and records delivery attempts for troubleshooting.

All paths below are under /api/v1.0. Webhook administration is space-scoped and feature-gated by webhooks.retry.

Endpoints

MethodEndpointDescription
GET/spaces/{slug}/webhooks/event-typesList supported event types with categories and descriptions.
GET/spaces/{slug}/webhooksList webhook subscriptions for a space.
POST/spaces/{slug}/webhooksCreate a webhook subscription.
PATCH/spaces/{slug}/webhooks/{webhook_id}Update a webhook subscription.
DELETE/spaces/{slug}/webhooks/{webhook_id}Delete a webhook and its delivery history.
POST/spaces/{slug}/webhooks/{webhook_id}/testSend a synthetic test event.
GET/spaces/{slug}/webhooks/{webhook_id}/deliveriesList delivery attempts for one webhook.

Creating a webhook also enforces the webhooks.max_webhooks tier limit for the space.

Supported Events

GET /api/v1.0/spaces/{slug}/webhooks/event-types

Returns the canonical event catalog. Current event types include:

CategoryEvent types
Productsproduct.created, product.updated, product.deleted, product.archived
Alertsalert.created, alert.resolved
Qualityquality_check.passed, quality_check.failed
Governanceaccess_request.created, access_request.approved, access_request.rejected, access.auto_revoked
Issuesissue.created, issue.updated, issue.closed
Contractscontract.created, contract.updated, contract.archived
Workflowsworkflow.completed, workflow.failed
Recertificationrecertification.cycle_created, recertification.cycle_completed, recertification.access_revoked

Use event_types: ["*"] to subscribe to every supported event.

List Webhooks

GET /api/v1.0/spaces/{slug}/webhooks

Returns subscriptions ordered by creation time descending.

[
{
"id": "1e5a3bbb-4b8e-4c38-8f04-f4db1b520f4f",
"space_id": "2a2423bd-c759-48cf-9588-7f21c12fba8c",
"name": "Governance Event Sink",
"url": "https://hooks.example.com/qarion",
"secret_last4": "****a1b2",
"is_active": true,
"event_types": [
"product.created",
"quality_check.failed"
],
"headers": {
"Authorization": "****"
},
"created_by": {
"id": "67b1bc7e-90d4-4df0-b232-fbb6b947e8cf",
"email": "admin@example.com",
"full_name": "Admin User"
},
"created_at": "2026-06-29T09:00:00Z",
"updated_at": "2026-06-29T09:00:00Z"
}
]

Secrets and custom header values are never returned in plaintext. Custom header names are preserved with masked values.

Create Webhook

POST /api/v1.0/spaces/{slug}/webhooks

Request Body

{
"name": "Governance Event Sink",
"url": "https://hooks.example.com/qarion",
"secret": "receiver-signing-secret",
"event_types": [
"product.created",
"quality_check.failed"
],
"headers": {
"Authorization": "Bearer receiver-token"
}
}
FieldRequiredDescription
nameYesDisplay name for the subscription.
urlYesPublic HTTPS endpoint. Unsafe, private, or non-HTTPS URLs are rejected.
secretNoHMAC signing secret. If omitted, Qarion generates one, but the raw generated value is not returned. Provide a known secret when the receiver must verify signatures.
event_typesNoEvent type list. Defaults to ["*"]. Must contain at least one supported type or *.
headersNoExtra outbound headers. Values are encrypted at rest and masked in responses.

Custom headers cannot override Qarion-controlled headers: Content-Type, X-Qarion-Event, or X-Qarion-Signature.

Update Webhook

PATCH /api/v1.0/spaces/{slug}/webhooks/{webhook_id}

Request Body

{
"name": "Governance Event Sink",
"url": "https://hooks.example.com/qarion-v2",
"is_active": true,
"event_types": [
"*"
],
"headers": {
"Authorization": "****",
"X-Receiver-Tenant": "qarion-prod"
}
}

All fields are optional. Omitted fields are unchanged. Masked header values preserve the existing encrypted value for that header name, which lets clients round-trip masked responses without erasing stored credentials.

Delete Webhook

DELETE /api/v1.0/spaces/{slug}/webhooks/{webhook_id}

Deletes the webhook and its delivery history. The response is 204 No Content.

Test Webhook

POST /api/v1.0/spaces/{slug}/webhooks/{webhook_id}/test

Sends a synthetic test event to the configured URL and records a delivery attempt.

{
"success": true,
"status_code": 200,
"error": null
}

The test payload has this shape:

{
"event": "test",
"message": "This is a test event from Qarion to verify your webhook endpoint.",
"webhook_name": "Governance Event Sink"
}

Delivery Log

GET /api/v1.0/spaces/{slug}/webhooks/{webhook_id}/deliveries?skip=0&limit=50

Query Parameters

ParameterTypeDescription
skipintegerNumber of delivery records to skip. Default 0.
limitintegerNumber of delivery records to return. Default 50, maximum 200.

Deliveries are ordered by delivered_at descending.

[
{
"id": "8e4e5bb4-a26d-4ace-9043-521e2ed78e50",
"webhook_id": "1e5a3bbb-4b8e-4c38-8f04-f4db1b520f4f",
"event_type": "quality_check.failed",
"payload": {
"quality_check_id": "check-uuid",
"status": "failed"
},
"status_code": 200,
"response_body": "ok",
"success": true,
"attempt": 1,
"error": null,
"delivered_at": "2026-06-29T09:30:00Z"
}
]

Response bodies are truncated to 500 characters.

Delivery Signing

Every outbound delivery includes these headers:

HeaderDescription
Content-TypeAlways application/json.
X-Qarion-EventEvent type being delivered.
X-Qarion-Signaturesha256=<hex digest> HMAC-SHA256 signature of the raw JSON request body using the webhook secret.

To verify a delivery, compute HMAC-SHA256 over the raw request body bytes with the shared secret, hex-encode it, and compare it to the value after sha256=.

Errors

StatusDescription
401Authentication is missing or invalid.
403Caller cannot administer the target space, the feature is unavailable, or the space exceeded the configured webhook subscription limit.
404Webhook or space was not found.
422Invalid event type, unsafe URL, invalid HTTPS URL shape, or reserved custom header.