ClousDocs
API Reference

Webhooks

Register signed webhook endpoints, receive monitor-matched events in real time, verify the HMAC signature, and read the delivery log.

Webhooks

Webhooks are how monitors reach you in real time. Register an endpoint, attach it to a monitor, and Clous POSTs each matching event to your URL with an HMAC signature you can verify.

  • Base URL: https://api.clous.ai
  • Auth: Authorization: Bearer clous_live_...

Register an endpoint

POST /v1/webhooks/endpoints

Prop

Type

curl -s -X POST "https://api.clous.ai/v1/webhooks/endpoints" \
  -H "Authorization: Bearer clous_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://api.acme.com/webhooks/clous", "description": "Production events" }'
import requests
resp = requests.post(
    "https://api.clous.ai/v1/webhooks/endpoints",
    headers={"Authorization": "Bearer clous_live_..."},
    json={"url": "https://api.acme.com/webhooks/clous", "description": "Production events"},
)
endpoint = resp.json()["data"][0]
secret = endpoint["secret"]  # store this — used to verify signatures

Example response

{
  "data": [
    {
      "id": "7b1ff0c8-fe92-421f-b8ed-ffa246d394de",
      "url": "https://api.acme.com/webhooks/clous",
      "secret": "9bccb20ea569…",
      "description": "Production events",
      "status": "active",
      "created_at": "2026-06-13T16:27:30.569725+00:00"
    }
  ],
  "source": "clous_monitoring",
  "warnings": []
}

The secret is returned once on creation. Store it — it signs every delivery to this endpoint and is what you verify against.

Receiving a webhook

When a monitor matches, Clous POSTs the event to your URL with these headers:

HeaderValue
Clous-Event-IdThe event id.
Clous-Delivery-IdUnique per delivery attempt — use it for idempotency.
Clous-TimestampISO-8601 timestamp, part of the signed payload.
Clous-Signaturesha256=<hex> — HMAC-SHA256 of "{timestamp}.{raw_body}" keyed by your endpoint secret.

Body:

{
  "type": "sec.filing.new",
  "monitor_id": "9107bc79-2e59-40f1-905e-7d3267563ecc",
  "delivery_id": "…",
  "event": { "id": "535754cd-…", "event_type": "sec.filing.new", "importance": "medium",
             "entity_name": "NVIDIA Corp", "entity_cik": "0001045810", "accession": "…",
             "summary": "…", "evidence": [  ] }
}

Verify the signature

Recompute the HMAC and compare in constant time. Reject if it doesn't match or the timestamp is stale.

import hmac, hashlib

def verify(secret: str, headers, raw_body: bytes) -> bool:
    ts = headers["Clous-Timestamp"]
    expected = "sha256=" + hmac.new(
        secret.encode(), f"{ts}.{raw_body.decode()}".encode(), hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, headers["Clous-Signature"])

Delivery log & retries

Deliveries that don't get a 2xx are retried with backoff (1 min → 5 min → 30 min → 2 h, then marked failed). Inspect the log:

GET /v1/webhooks/deliveries

Returns recent deliveries for your endpoints with status (pending / success / failed), attempts, response_status, and last_error.

Status codes

StatusMeaning
200 / 201Endpoint registered or deliveries returned.
400url is not https://.
401Missing or invalid API key.

On this page