# Webhooks API

Webhooks deliver durable notifications to an HTTPS endpoint owned by the organization. Delivery is at least once: consumers must verify signatures, tolerate duplicates and reordering, and fetch current resource state when correctness matters.

## Ownership and Roles

An API Client may create and manage only its own webhook endpoints. Events are filtered through the same license, Role, field, and resource rules as API reads. Changing the client's Roles immediately changes what future deliveries may contain.

## Create an endpoint

`POST /v1/webhook-endpoints`

Operation ID: `createWebhookEndpoint`. Required header: `Idempotency-Key`.

```json
{
  "url": "https://integrations.example.com/eos/webhooks",
  "events": ["task.updated", "invoice.sent", "run.completed"],
  "description": "Production Eos listener"
}
```

The response returns a signing secret exactly once. Store it in a secret manager. Eos accepts only HTTPS endpoints, blocks private or unsafe network destinations, and may require a verification challenge before activation.

## List, get, and update endpoints

- `GET /v1/webhook-endpoints` — `listWebhookEndpoints`
- `GET /v1/webhook-endpoints/{endpoint_id}` — `getWebhookEndpoint`
- `PATCH /v1/webhook-endpoints/{endpoint_id}` — `updateWebhookEndpoint`, `If-Match`
- `POST /v1/webhook-endpoints/{endpoint_id}/rotate-secret` — `rotateWebhookEndpointSecret`, `Idempotency-Key`
- `POST /v1/webhook-endpoints/{endpoint_id}/disable` — `disableWebhookEndpoint`, `Idempotency-Key`
- `POST /v1/webhook-endpoints/{endpoint_id}/enable` — `enableWebhookEndpoint`, `Idempotency-Key`

Secret rotation returns the new secret once and supports a short documented overlap window so consumers can deploy safely.

## Event envelope

```json
{
  "id": "evt_01J8RK6KS3SXQ1R5C2NW9N1N6J",
  "type": "invoice.sent",
  "api_version": "v1",
  "created_at": "2026-08-22T12:00:00Z",
  "organization_id": "org_01J8PZZRJBBG2AX1SQA6ZVY6QY",
  "data": {
    "object": {"type": "invoice", "id": "inv_01J8R6MB55Q2BEY9NE7NQE3J4S", "version": 4}
  }
}
```

Events carry stable identifiers and a minimal authorized resource projection. Consumers should retrieve the resource for its current full representation.

## Verify signatures

Each request includes:

- `Eos-Webhook-Id`: the event ID
- `Eos-Webhook-Timestamp`: Unix seconds
- `Eos-Webhook-Signature`: one or more versioned HMAC-SHA256 signatures

`Eos-Webhook-Signature` contains comma-separated `v1=<lowercase hexadecimal digest>` values. Compute HMAC-SHA256 over `timestamp + "." + raw_request_body` with the endpoint secret, compare at least one `v1` digest in constant time, and reject timestamps more than five minutes from the receiving system's clock. Verify the raw bytes before JSON parsing. Deduplicate on event ID.

Published SDK fixtures will include valid, invalid, rotated-secret, stale-timestamp, and modified-payload test vectors.

## Delivery, retries, and responses

Return any `2xx` response within ten seconds. Redirects are not followed. Timeouts, network failures, `429`, and `5xx` responses are retried with exponential backoff for 72 hours. Most other `4xx` responses are treated as permanent. Events and delivery diagnostics remain available for 30 days. Repeated failures may automatically disable an endpoint and emit an administrator notification.

## Inspect and replay deliveries

- `GET /v1/webhook-endpoints/{endpoint_id}/deliveries` — `listWebhookDeliveries`
- `GET /v1/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}` — `getWebhookDelivery`
- `POST /v1/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}/replay` — `replayWebhookDelivery`, `Idempotency-Key`
- `POST /v1/webhook-endpoints/{endpoint_id}/test` — `testWebhookEndpoint`, `Idempotency-Key`

Replay is available only inside the event retention window and creates a new delivery attempt for the same event ID.

## Initial event families

- `project.*`, `task.*`, `time_entry.*`, and `ticket.*`
- `invoice.*`, `payment.*`, and `file.*`
- `approval.created` and `approval.updated`
- `report_run.*`, `run.*`, and `conversation.message.created`
- `integration_connection.updated`

The endpoint-creation API returns the exact supported event names. Unknown names are rejected.

## Common errors

`WEBHOOK_ENDPOINT_NOT_FOUND`, `WEBHOOK_EVENT_NOT_SUPPORTED`, `WEBHOOK_URL_UNSAFE`, `WEBHOOK_VERIFICATION_FAILED`, `WEBHOOK_SECRET_NOT_AVAILABLE`, `WEBHOOK_DELIVERY_NOT_FOUND`, and `WEBHOOK_REPLAY_EXPIRED`.

Back to [Eos API v1 overview](index.html).
