Developer portal
Event types
Every event type QEHS emits via webhooks, with payload schema, emitting conditions, and a sample payload. Subscribe to any combination from Settings → Webhooks.
All events share a common envelope: eventId, event, tenantId, firedAt, and a data object specific to the event type. Deliveries are HMAC-signed, see the webhooks docs for signature verification.
| Event | Summary |
|---|---|
| record.created.v1 | A record was created in a module. |
| record.updated.v1 | One or more fields on a record were changed. |
| record.transitioned.v1 | A record advanced between workflow states. |
| record.deleted.v1 | A record was soft-deleted. |
| module.published.v1 | A Composer module version was published to production. |
| user.provisioned.v1 | A new user was added to the tenant. |
| user.deprovisioned.v1 | A user was removed from the tenant. |
| attachment.uploaded.v1 | An attachment was uploaded and passed virus scanning. |
| export.completed.v1 | An async export job finished and a download is ready. |
| billing.subscription.updated.v1 | The tenant plan, seat count, or trial state changed. |
| webhook.test.v1 | Synthetic test event fired from the webhook settings UI. |
Versioning policy
Additive changes (new optional fields, new enum values) stay on the current version. Structural changes (field removal, rename, type narrowing, required-flag flip) create a new version, for example record.created.v2. Subscribers opt in to the new version by updating the event name on their webhook; the old version keeps firing until they migrate. Deprecation gives at minimum 6 months notice.
Delivery envelope
{
"eventId": "11111111-2222-3333-4444-555555555555", // unique per delivery attempt
"event": "record.created.v1", // fully-qualified event name
"tenantId": "00000000-1111-2222-3333-444444444444", // tenant that owns the resource
"firedAt": "2026-04-18T12:34:56.000Z", // ISO-8601 UTC emission time
"data": { ... } // event-specific payload
}