Quick Start
1. Create a webhook
From the dashboard, open Webhooks under the Account section and click Add webhook:- Paste your HTTPS endpoint (
https://your-app.example.com/anchor/webhooks). - Pick the events you want to subscribe to. See Events for the full catalog.
- Click Create webhook.
secret field - store it, it never appears in any subsequent API response.
2. Receive events
Each event arrives as aPOST with a JSON body and a few Anchor-* headers:
2xx status code within 10 seconds - that’s how Anchor knows the event was delivered. Anything else triggers a retry (see Retries).
3. Verify the signature
Compute an HMAC-SHA256 ofv0:{Anchor-Timestamp}:{raw_body_bytes} using your signing secret and compare it to the v1= value in the Anchor-Signature header in constant time. Reject anything you can’t verify.
Full code examples (Node.js, Python, Go) are on the Signature verification page.
Slack integration
Every event includes a top-leveltext field with a one-line human-readable summary. That’s the same shape Slack incoming webhooks expect, so you can register a Slack URL as a webhook receiver with no relay:
-
In Slack, create an Incoming Webhook for the channel you want events posted to. Slack gives you a URL like
https://hooks.slack.com/services/T.../B.../.... - In Anchor, Webhooks → Add webhook, paste the Slack URL, pick the events.
-
Done. Each delivery posts a message in the channel — for example:
✅ Task
tsk_4f8w9n2bcompleted in 4.2s
data and posts the message you want; the structured fields stay machine-readable while text covers the simple case.
Testing your endpoint
The dashboard’s Send test event button fires a synthetic event of the type you choose through the real signing + retry path. Use it during development:- Pick the event type from the dropdown next to the payload preview.
- Click Send test event.
- Inspect the request at your endpoint.
503 from your endpoint.
You can also trigger via the API:
Retries and delivery guarantees
Anchor retries failed deliveries with exponential backoff:| Attempt | Time since first attempt | Schedule (after the previous) |
|---|---|---|
| 1 (initial) | 0 s | immediate |
| 2 | 5 s | +5 s |
| 3 | 15 s | +10 s |
| 4 | 30 s | +15 s |
| 5 | 50 s | +20 s |
| 6 | 80 s | +30 s |
- The HTTP request errors (DNS failure, timeout, TLS handshake failure).
- Your endpoint returns
5xx,408, or429.
4xx. Use that intentionally for events you’ve already processed (409 Conflict after de-dupe is a common pattern).
After 6 attempts (~80 s elapsed since the first attempt), the delivery is marked dead and won’t be retried automatically. You can still see it in Webhooks → Events in the dashboard for 7 days.
At-least-once delivery. Because we retry on transient errors, your endpoint may receive the same event more than once. Always de-dupe by id (the envelope’s top-level id, not data.execution_id).
Idempotency and ordering
- Each delivery has a unique top-level
id(evt_...). The same logical event will always carry the sameid, so storing(id, status)in your database and checking before processing is enough to make your handler idempotent. - Anchor does not guarantee delivery order. A retry may arrive after a later event for the same task. Use the
createdtimestamp to order events on your side if you care about sequencing. - An event delivered to multiple webhook endpoints carries the same
idto every endpoint, so you can correlate deliveries across consumers.
Inspecting deliveries
Every delivery - succeeded, failed, or dead - is visible in the dashboard’s Webhooks → Events view for 7 days. The same data is available via the API:event_type, status, attempt, response_status, error_message, scheduled_at, and completed_at. Use this to debug failing endpoints or to confirm a missed event made it through.
Sensitive data and what we never send
Anchor sanitizes every webhook payload before it leaves our infrastructure:- Whitelist via schema. Only fields explicitly declared in each event’s schema are sent. Anything else is stripped.
- Schema-driven secret redaction. Task inputs marked
secretin your task schema are masked as*****before they appear inoutput.value. - Free-text scrubbing. Error messages and self-heal explanations are scanned for credential patterns and masked.
- Identity credential values (passwords, API tokens).
- Raw
inputsfrom task executions.
Best practices
Verify the signature on every request
Verify the signature on every request
Even if you trust your network perimeter - Anchor’s signature is a proof that the request really came from us.
Acknowledge fast, work later
Acknowledge fast, work later
Return
2xx within 10 seconds. If processing takes longer (e.g. you write to a slow downstream system), enqueue the event in your own queue and process it asynchronously.De-dupe by `id`
De-dupe by `id`
Anchor delivers at-least-once. Persist
(id, status) in your database and short-circuit duplicates with a 200 OK.Rotate secrets without downtime
Rotate secrets without downtime
Click Rotate signing secret to get a new one. The old secret remains valid for 24 hours so you can deploy at your own pace. Update both, then drop the old one once your deploys are out.
Use the events log to spot regressions
Use the events log to spot regressions
Filter by
status=failed or status=dead in the dashboard or API. Anything that lingers there is either an endpoint bug, a network blip, or a real automation issue worth digging into.API reference
| Method | Path | Purpose |
|---|---|---|
POST | /v1/webhooks | Create a webhook (returns the signing secret once). |
GET | /v1/webhooks | List webhooks for the project. |
GET | /v1/webhooks/{id} | Fetch a single webhook config. |
PATCH | /v1/webhooks/{id} | Update url, description, subscribed events, or enabled. |
POST | /v1/webhooks/{id}/rotate-secret | Rotate the signing secret. Old secret valid for 24 h. |
DELETE | /v1/webhooks/{id} | Soft-delete a webhook. |
POST | /v1/webhooks/{id}/test | Fire a synthetic event of a given type. |
GET | /v1/webhooks/{id}/events | Paginated delivery history (last 7 days). |
anchor-api-key header (or the dashboard session cookie) and scoped to the current project.
Limits
- Up to 5 webhook endpoints per project.
- HTTPS only. The following hosts are rejected at create/update time:
- Loopback / private / link-local IPs (
127.0.0.0/8,10.0.0.0/8,192.168.0.0/16,172.16.0.0/12,169.254.0.0/16, IPv6 ULAfc00::/7and link-localfe80::/10). - Cloud metadata services (
169.254.169.254,metadata.google.internal,metadata.azure.com). - Internal-only TLDs (
*.local,*.internal). - Cloud control-plane endpoints — AWS STS (
sts.*.amazonaws.com, including FIPS, GovCloud, and China regions), AWS IAM, EKS auth. - URLs with embedded basic-auth credentials.
- Loopback / private / link-local IPs (
- Maximum URL length: 2048 characters.
- Maximum payload size: 64 KB. Larger
output.valueis replaced with"__truncated__"; fetch the full result via the REST API. - HTTP timeout: 10s per attempt.
- Maximum 6 delivery attempts (1 initial + 5 retries) over ~80 seconds.
- Delivery history retention: 7 days.

