Webhooks
Archlet can notify your systems when important events happen in your tenant. When an event occurs, Archlet sends an HTTP POST request to the webhook URLs you configure in the Archlet application.
Use the webhook reference for payload schemas and request examples. This page explains how deliveries work in practice.
Configuring webhooks
Webhook endpoints are managed in the Archlet application under Admin → Webhooks. There you can:
- Register one or more HTTPS URLs
- Choose which events each webhook should receive
- Set a signing key when creating a webhook or use the auto-generated one
- Optionally configure OIDC client credentials so Archlet can authenticate to your endpoint
Webhook management is part of the Archlet browser application, not the Customer API.
Request format
Every delivery is an HTTP POST with a JSON body and the headers below.
| Header | Always present | Description |
|---|---|---|
Content-Type | Yes | Always application/json. |
X-Archlet-Notification-Event | Yes | Event type, for example ProjectClosed. |
X-Archlet-Notification-ID | Yes | Stable UUID for this delivery. Automatic retries reuse the same value. |
X-Archlet-Notification-Timestamp | Yes | UTC time when Archlet first sent this delivery (ISO 8601). Automatic retries reuse the same value. |
X-Archlet-Notification-Signature | Yes | HMAC-SHA256 signature of the raw request body (hex-encoded). |
Authorization | Only when OIDC is configured | Bearer access token obtained via your configured client credentials. |
Respond with any 2xx status code to acknowledge successful processing.
Verifying the signature
Each webhook has a signing key. Archlet never sends this key in notification requests; copy it when you create the webhook and store it securely on your side.
To verify a delivery:
- Read the raw request body bytes (before JSON parsing).
- Compute
HMAC-SHA256(signingKey, rawBody). - Hex-encode the digest.
- Compare the result with the
X-Archlet-Notification-Signatureheader.
A plain string comparison is usually enough for webhook verification. Using a constant-time comparison (for example Node.js timingSafeEqual) is optional but reduces the risk of timing attacks that could help an attacker guess the expected signature byte by byte.
Example in Node.js:
import { createHmac, timingSafeEqual } from 'node:crypto';
function isValidSignature({ signingKey, rawBody, signatureHeader }) {
const expected = createHmac('sha256', signingKey).update(rawBody).digest('hex');
const received = Buffer.from(signatureHeader, 'utf8');
const expectedBuffer = Buffer.from(expected, 'utf8');
return received.length === expectedBuffer.length && timingSafeEqual(received, expectedBuffer);
}
Reject requests with an invalid or missing signature.
Optional OIDC authentication
If you configure OIDC client credentials for a webhook, Archlet obtains an access token from your authorization server and sends it in the Authorization: Bearer … header.
Your endpoint should validate that token according to your identity provider's rules (issuer, audience, expiry, scopes, and so on).
In order to decrease the load on your authorization server, Archlet might cache the token in memory for the number of seconds described by the expires_in field of your token response. If your authorization server does not return expires_in, Archlet will request a new token for every delivery.
Example configuration in Admin → Webhooks:
| Field | Example value |
|---|---|
| Access token URL | https://auth.example.com/oauth/token |
| Client ID | {Client ID generated by your IdP for the Archlet App} |
| Client secret | {Client Secret generated by your IdP for the Archlet App} |
| Scope (optional) | webhooks:receive |
| Audience (optional) | https://api.example.com |
When a delivery is sent, Archlet requests a token from your access token URL using the client credentials grant, then calls your webhook URL with:
Authorization: Bearer eyJ...
Content-Type: application/json
X-Archlet-Notification-Event: ProjectClosed
...
Idempotency
Archlet retries failed deliveries automatically. Retries for the same delivery share the same X-Archlet-Notification-ID and X-Archlet-Notification-Timestamp.
Design your handler to be idempotent: if you have already processed a notification ID, return 2xx without performing the side effect again.
Retry behavior
Archlet retries automatic event deliveries when processing fails with a retryable outcome. Manual test sends and manual resends from Admin → Webhooks are never retried automatically.
When Archlet retries
A delivery is retried when all of the following are true:
- The delivery failed (non-2xx HTTP response, network error, or timeout)
- It was triggered automatically by an Archlet event (not a manual test or resend)
- Fewer than 5 total attempts have been made for the same
X-Archlet-Notification-ID - The HTTP status is retryable
Retryable HTTP status codes
Archlet retries deliveries that fail with:
- Any status 500 or above
- These 4xx statuses:
408,409,425,429 - Network errors and request timeouts (no HTTP status)
Archlet does not retry other 4xx responses (for example 400, 401, 403, or 404). Please address the underlying issue.
Backoff schedule
Retries use linear backoff from the attempt that failed:
| Failed attempt | Delay before next try |
|---|---|
| 1 | 5 minutes |
| 2 | 10 minutes |
| 3 | 15 minutes |
| 4 | 20 minutes |
After the fifth failed attempt, Archlet stops automatically retrying that notification ID. You can still send a new delivery manually from Admin → Webhooks → Notification history.
Timeouts
Each HTTP request times out after 30 seconds.
Supported events
See the webhook reference for the list of documented events and their payload schemas.
Currently available:
- Project closed — sent when a project is closed. Payload:
{ "projectId": "<uuid>" }.