Webhook endpoints
Reference for /v1/webhook-endpoints: create, list, retrieve and delete the URLs that receive Constaia events, with their whsec_ secret and mode.
A webhook endpoint is a URL of yours to which Constaia sends signed events: finished analyses, completed batches, low balance. You can manage them from the dashboard or with this API, which is handy to automate environments (staging, previews, per-customer deployments).
How to receive and verify events: Webhooks.
| Method and route | What it does |
|---|---|
POST /v1/webhook-endpoints | Creates an endpoint. Returns the secret only once. |
GET /v1/webhook-endpoints | Lists the account's endpoints. |
GET /v1/webhook-endpoints/{id} | Retrieves one. |
DELETE /v1/webhook-endpoints/{id} | Deletes it. |
Create an endpoint
POST /v1/webhook-endpoints
Content-Type: application/json| Field | Type | Description |
|---|---|---|
url | string | https:// URL that will receive the events (max 2048 characters). Required. |
events | string[] | Events you subscribe to (at least one). Required. |
description | string | Free text to identify it (max 500 characters). Optional. |
Available events:
| Event | When |
|---|---|
analysis.completed | An analysis or classification that is not part of a batch finishes. |
analysis.failed | An analysis fails, also inside a batch. |
analysis.review_required | An analysis finishes with a review verdict (in addition to analysis.completed). |
batch.completed | Every document of a batch has finished. |
credits.low | The balance drops below the threshold set in the dashboard (live only). |
* | Every event, including those added in the future. |
curl https://api.constaia.com/v1/webhook-endpoints \
-H "Authorization: Bearer $CONSTAIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhooks/constaia",
"events": ["analysis.completed", "analysis.review_required", "analysis.failed", "batch.completed"],
"description": "Production"
}'{
"id": "we_01J9Z8Q3K4M5N6P7Q8R9S0T1V2",
"object": "webhook_endpoint",
"url": "https://example.com/webhooks/constaia",
"description": "Production",
"events": ["analysis.completed", "analysis.review_required", "analysis.failed", "batch.completed"],
"status": "active",
"enabled": true,
"mode": "test",
"created_at": "2026-09-29T10:00:00.000Z",
"secret": "whsec_…"
}The secret is only shown now
secret only comes in the creation response. Store it in your secret manager (for example, as CONSTAIA_WEBHOOK_SECRET). Constaia stores it encrypted and never shows it again: if you lose it, delete the endpoint and create another one.
Test and live mode
The endpoint inherits the mode of the key you create it with (mode: "test" or "live") and only receives events of that mode. To receive real events, create it with a ck_live_ key. It is common to have two endpoints: a test one pointing at staging and a live one pointing at production.
Errors
| HTTP | code | When |
|---|---|---|
400 | invalid_url | The URL does not use https. |
400 | invalid_json | The body is not valid JSON. |
422 | invalid_parameter | url is not a valid URL, events is empty or contains an unknown event (param says which, e.g. events.0). |
It supports Idempotency-Key: if you retry a creation you are unsure went through with the same key and body, you get the original response (with the same secret) and the Idempotent-Replayed: true header, without creating a duplicate endpoint. See Idempotency.
List endpoints
curl https://api.constaia.com/v1/webhook-endpoints \
-H "Authorization: Bearer $CONSTAIA_API_KEY"Returns every endpoint of the account, of both modes (check mode), newest first, without secret:
{
"object": "list",
"data": [
{
"id": "we_01J9Z8Q3K4M5N6P7Q8R9S0T1V2",
"object": "webhook_endpoint",
"url": "https://example.com/webhooks/constaia",
"description": "Production",
"events": ["analysis.completed", "analysis.review_required", "analysis.failed", "batch.completed"],
"status": "active",
"enabled": true,
"mode": "test",
"created_at": "2026-09-29T10:00:00.000Z"
}
],
"has_more": false,
"url": "/v1/webhook-endpoints"
}| Field | Description |
|---|---|
id | Prefix we_. |
url, description, events | What you set when creating it. |
status | active or disabled. A disabled endpoint receives no events. |
enabled | true if status is active. |
mode | test or live. |
created_at | Creation date. |
Retrieve and delete
curl https://api.constaia.com/v1/webhook-endpoints/we_01J9Z8Q3K4M5N6P7Q8R9S0T1V2 \
-H "Authorization: Bearer $CONSTAIA_API_KEY"
curl -X DELETE https://api.constaia.com/v1/webhook-endpoints/we_01J9Z8Q3K4M5N6P7Q8R9S0T1V2 \
-H "Authorization: Bearer $CONSTAIA_API_KEY"{ "id": "we_01J9Z8Q3K4M5N6P7Q8R9S0T1V2", "object": "webhook_endpoint", "deleted": true }When you delete an endpoint, pending deliveries to it are no longer retried. If it does not exist or was already deleted, 404 resource_missing.
Dashboard only
API v1 has no PATCH. These actions are done in the dashboard, in the webhooks section:
- Edit the URL, events or description.
- Disable and re-enable an endpoint.
- Send a test event (
type: "test") to check your URL and your signature verification. - See the last 100 deliveries with their response code and retries.
SDK examples
import { Constaia } from "@constaia/sdk";
const constaia = new Constaia();
const url = "https://staging.example.com/webhooks/constaia";
const existing = (await constaia.webhookEndpoints.list()).find(
(e) => e.url === url && e.mode === (constaia.livemode ? "live" : "test"),
);
if (!existing) {
const endpoint = await constaia.webhookEndpoints.create({
url,
events: ["analysis.completed", "analysis.failed", "batch.completed"],
description: "Staging",
});
console.log("Store this secret:", endpoint.secret);
}Next steps
Balance and usage
Reference for GET /v1/balance and GET /v1/usage: pack credits, free tier, reservations and daily usage by document type, with examples.
Webhooks
Receive signed events from Constaia: each event's body, Standard Webhooks signature verification in seven languages, retries, idempotency and testing.