Zum Hauptinhalt springen

REST API & webhooks

On the Pro plan and above you can integrate KNX Clarity with your own systems: pull data over a read-only REST API, and receive webhooks when things change. Both are managed under Settings.

Plan requirement

The REST API and webhooks are Pro / Enterprise features — see Plans & billing. Pro includes up to 5 API keys and 5 webhooks; Enterprise raises both to 50.

API keys​

Open Settings → API-Schlüssel and click Neuer API-Key. Give it a name and an expiry (never, 30 days, 90 days, or 1 year). The key is issued with the four read scopes — me:read, projects:read, devices:read, groupaddresses:read. Write access is not available yet.

The plaintext token (kx_…) is shown exactly once at creation — copy it then, because only a hash is stored and it can never be shown again. Revoke a key any time with the trash icon; the row stays for the audit trail but the token stops working immediately.

Using the REST API​

Send the token as a bearer header:

Authorization: Bearer kx_your_token_here

The base URL is issued per environment (the RestApiUrl value for your stack). Every response is scoped to the token's organisation — you never pass an org id. Endpoints:

Method & pathScopeReturns
GET /v1/healthnone{ "ok": true }
GET /v1/meme:readthe org, the user, and the key
GET /v1/projectsprojects:reada list of projects
GET /v1/projects/:idprojects:reada single project
GET /v1/projects/:id/devicesdevices:readthe project's devices
GET /v1/projects/:id/groupaddressesgroupaddresses:readthe project's group addresses

The device and group-address endpoints are addressed per project rather than per organisation, because that is how the data is indexed — and how you almost certainly want to pull it. Use GET /v1/projects to get the ids.

Every list returns { items, count, hasMore } and stops at 100 items. hasMore: true means there were more than that: v1 has no cursor yet, so treat it as a signal to narrow your query rather than to page.

Errors come back as { "error": { "code", "message" } } — a 401 for a missing/invalid/expired key, a 403 (scope_required) when the key lacks the scope, and a 404 for a project your key's organisation does not own (the same 404 as for one that does not exist, so the API cannot be used to probe for project ids). The API is intentionally minimal for now: read-only, no cursor pagination, no per-key rate limiting, no CORS.

Webhooks​

Open Settings → Webhooks and click Neuer Webhook. Provide a name, an HTTPS endpoint URL, and the events to subscribe to:

  • project.created, project.updated, project.archived
  • service_case.created, service_case.status_changed

A signing secret (whsec_…) is shown once at creation. Use the Test-Event senden button to fire a webhook.test delivery while you build your receiver.

Payloads and signatures​

Each delivery is a POST with these headers:

  • X-KNX-Event — the event type.
  • X-KNX-Delivery — a per-attempt UUID (use it as an idempotency key).
  • X-KNX-Signature — t=<unix-seconds>,v1=<hex>, a Stripe-style HMAC.

The body is JSON: { id, type, orgId, eventId, createdAt, triggeredByUserId, data }.

To verify a delivery, compute the HMAC over "<t>.<rawBody>". The HMAC key is the SHA-256 hash (hex) of your signing secret, not the secret itself:

import crypto from "node:crypto";

function verify(signingSecret, header, rawBody) {
const parts = Object.fromEntries(header.split(",").map(p => p.split("=")));
const key = crypto.createHash("sha256").update(signingSecret).digest("hex");
const expected = crypto
.createHmac("sha256", key)
.update(`${parts.t}.${rawBody}`)
.digest("hex");
const ok = crypto.timingSafeEqual(
Buffer.from(parts.v1),
Buffer.from(expected)
);
const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
return ok && fresh;
}

Reject anything where the signature doesn't match or the timestamp is more than a few minutes old (replay protection).

Retries and auto-disable​

A delivery is attempted up to 3 times (immediately, after 5 s, after 30 s). Network errors, 5xx, and 429 are retried; any other 4xx is treated as permanent. If a webhook fails 5 batches in a row it is automatically disabled and the creator is notified — re-enable it with Aktivieren once your endpoint is healthy. Every attempt is recorded in the delivery log (Zustellungen anzeigen), kept for 30 days.