AtisboAtisbo Docs
API Reference

Webhook API

Reference for Atisbo's inbound webhook endpoints

Webhook API

Atisbo exposes separate inbound endpoints for signal events, email ingestion, GitHub events, and metric updates. Custom data is split by purpose: signal webhooks create Triage signals, while metric webhooks update map metrics.

Endpoints

Signal Webhook

POST /api/webhooks/custom/{id}

Generic signal webhook for JSON payloads that should become product signals. Your unique id is found in Settings → Sources → Signal Webhook.

Each workspace has one generic signal webhook integration. Multiple systems can send to it; use payload fields like source, source_url, event, and signal_origin to distinguish senders and business meaning.

curl -X POST https://app.atisbo.dev/api/webhooks/custom/<your-id> \
  -H "Content-Type: application/json" \
  -H "X-Atisbo-Signature: sha256=<hmac>" \
  -d '{
    "text": "Users report the payment modal freezes on slow connections",
    "source": "intercom",
    "occurred_at": "2026-05-27T18:30:00Z",
    "signal_origin": "customer",
    "actor_role": "user"
  }'

Request body:

FieldTypeRequiredDescription
textstringYesSignal content (max 50,000 chars)
sourcestringNoSource label
source_urlstringNoLink to original item
occurred_atstring | numberNoWhen the event happened in the source system. ISO 8601 recommended; epoch seconds or milliseconds accepted.
actor_namestringNoName of creator
actor_emailstringNoEmail of creator (PII-scrubbed before storage)
signal_origin"customer" | "internal" | "operational"NoDefault: "customer"
actor_role"user" | "pm" | "designer" | "engineer" | "system"NoDefault: "user"
metadataobjectNoArbitrary key-value pairs

Response:

{ "ok": true, "snippet_id": "uuid" }

Metric Webhook

POST /api/webhooks/metric/{id}

Named endpoint for numeric metric updates. Create as many metric webhooks as you need in Settings → Sources → Metric Webhooks; for example, one for Stripe revenue and another for warehouse activation counts.

curl -X POST https://app.atisbo.dev/api/webhooks/metric/<webhook-id> \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <webhook-secret>" \
  -d '{ "value": 1234, "occurred_at": "2026-05-27T18:30:00Z" }'

Metric webhooks update metric bindings on maps. They do not create Triage signals. If you send occurred_at, timestamp, date, or time, Atisbo uses it for the historical metric point; otherwise it uses the receive date.


Email Ingestion

POST /api/webhooks/email-ingest

Receives emails forwarded to your Atisbo ingestion address. This endpoint is called automatically by Atisbo's email infrastructure — you don't call it directly.


GitHub Webhook

POST /api/webhooks/github/{id}

Receives GitHub events (push, pull_request, release, deployment). Your unique id is in Settings → Sources → GitHub.

GitHub requires HMAC signature verification (X-Hub-Signature-256 header). Atisbo handles this automatically when you copy the secret from the setup dialog.


Authentication

Signal webhook endpoints use secret URL authentication plus the shared secret shown in setup. Treat the URL and secret like API keys:

  • Don't commit it to public repos
  • Regenerate the endpoint if compromised

Metric webhooks use Authorization: Bearer <webhook-secret>. The secret is shown once when the named metric webhook is created.

GitHub uses HMAC-SHA256 signature verification via X-Hub-Signature-256.

Sources connected through your agent arrive on a separate receiver that verifies a Standard Webhooks signature and resolves the tenant from the connection itself — there is nothing for you to configure. See Connect with your agent.


Rate Limits

EndpointLimitWindow
Signal webhook100 requestsper minute per endpoint
Metric webhook60 requestsper minute per endpoint
Email ingest50 emailsper hour per tenant
GitHub webhook500 eventsper minute

Exceeding limits returns 429 Too Many Requests. The pipeline retries automatically within Atisbo's infrastructure — external callers should implement exponential backoff.


Processing Pipeline

Signal-producing inbound webhooks go through the same 9-step pipeline:

1. Validate      → schema check, size limit
2. Normalize     → source format → canonical PipelineInput
3. PII scrub     → redact emails, phones, national IDs, cards, IPs (not names)
4. Cache check   → 0.95 cosine similarity → skip if near-duplicate
5. Classify      → problem / idea / question / unclassified
6. Embed         → Jina v3 vector (1024 dimensions)
7. Dedup         → 0.90 cosine cross-channel dedup
8. Insert        → create Snippet in database
9. Cluster       → group with related evidence, confirmed by a model before merging

Failed steps are logged to the Dead Letter Queue and retried automatically.

Step 9 is not similarity alone. Evidence close enough to be a candidate is passed to a language model, which confirms it is the same root problem before anything merges — two pieces of feedback from one product area share vocabulary without sharing a cause, and distance cannot tell those apart.