1. Webhooks in — any system, zero plugins

Every automation platform on earth can POST a webhook: Stripe, Shopify, n8n, Zapier, Make, IFTTT, GitHub Actions, cron + curl, your own backend. Point them all at one endpoint:

POST https://your-callhook.example.com/api/events
Authorization: Bearer <CALLHOOK_INTAKE_TOKEN>

{
  "id": "evt_stripe_8472",          // your idempotency key — replays never double-dial
  "type": "payment.failed",
  "customer_id": "cus_2003",
  "callback_url": "https://your-app.example.com/hooks/callhook",
  "payload": { "amount": "the monthly charge", "reason": "card declined" }
}

Typical wiring: Stripe → failed-payment webhook → callhook payment.failed. Shopify → fulfillment event → delivery.window. Your CRM → overdue job → invoice.due. Calendly-style bookings → appointment.reminder with not_before.

2. Native adapters — the platforms call you directly

Prefer zero glue code? 19 platform adapters ship in the binary: point the platform's native webhook at /integrations/<platform>/webhook and callhook verifies the platform's own signature scheme — checked line-by-line against each vendor's docs — then maps the payload to the right event type. Stdlib only, zero dependencies.

PlatformRouteVerification (per official docs)
Stripe/integrations/stripe/webhookStripe-Signature t=.body HMAC-SHA256, 5-min replay window
Slack/integrations/slack/slashX-Slack-Signature v0:ts:body HMAC-SHA256
Shopify/integrations/shopify/webhookX-Shopify-Hmac-Sha256 base64 HMAC-SHA256
HubSpot/integrations/hubspot/webhookX-HubSpot-Signature-V3 method+URI+body+ts HMAC-SHA256
PagerDuty/integrations/pagerduty/webhookX-PagerDuty-Signature HMAC-SHA256
GitHub/integrations/github/webhookX-Hub-Signature-256 sha256= HMAC-SHA256 (their test vector passes)
Calendly/integrations/calendly/webhookCalendly-Webhook-Signature t=.body HMAC-SHA256
Typeform/integrations/typeform/webhookTypeform-Signature sha256= base64 HMAC-SHA256
WooCommerce/integrations/woocommerce/webhookX-WC-Webhook-Signature base64 HMAC-SHA256 (matches plugin source)
Xero/integrations/xero/webhookX-Xero-Signature base64 HMAC-SHA256, 200/401 intent
QuickBooks/integrations/quickbooks/webhookX-Intuit-Signature hex HMAC-SHA256
Paddle/integrations/paddle/webhookPaddle-Signature ts;h1 HMAC-SHA256 of ts:body
Grafana/integrations/grafana/webhookX-Grafana-Alerting-Signature hex HMAC-SHA256
Datadog/integrations/datadog/webhookshared-secret header / basic auth (Datadog doesn't sign)
Intercom/integrations/intercom/webhookX-Hub-Signature sha1= hex HMAC-SHA1
Chargebee/integrations/chargebee/webhookHTTP Basic auth (webhook settings)
Pipedrive/integrations/pipedrive/webhookHTTP Basic auth or URL token
AWS SNS/integrations/sns/webhookfull RSA cert verification (SigV2), CloudWatch alarms auto-mapped
Generic HTTP/integrations/generic/webhookbearer / shared-secret — callhook event JSON passthrough

Unconfigured platforms answer 401 loudly on every delivery. The war-room Integrations page shows live status (GET /api/integrations). Per-platform setup guides (dashboard steps, env vars, mappings): integrations/ in the repo. Outbound packages ship too: an n8n community node, a Zapier app, agent tools for OpenAI / LangChain / AutoGen / CrewAI, and recipes for Salesforce, Airtable and Google Forms.

# prove an integration end-to-end, no platform account needed:
$ callhookctl test-webhook stripe # signs a real fixture, fires the pipeline

3. Outcome callbacks — the loop closes

When each call finishes, the structured outcome POSTs back to your callback_url:

{
  "event_id":   "evt_stripe_8472",
  "outcome":    { "outcome": "payment_promised", "promise_date": "2026-09-12" },
  "actions":    ["write.mark_promise(...)"],
  "confidence": { "score": 0.93, "label": "high" },
  "transcript":  [ ... ]
}

Your system updates its own records — the conversation's result lands where your business logic lives. Verify authenticity with the shared X-Callhook-Secret header pattern on your side, and dedupe by event_id (we deliver once; redeliveries carry the same id).

4. MCP — AI agents operate the voice channel

Point any MCP client (Claude Code, Cursor, agents) at POST /mcp. Six tools: fire_event, launch_campaign, get_campaign, list_sessions, list_event_types, run_demo.

# Claude Code / any MCP client:
> "Collect 5 payment promises from the overdue list"
→ agent calls launch_campaign → waves fire → early-stop at the goal

5. business.Store — your CRM/billing adapter

The mock store ships for demos; production implements one interface against your real systems — customers, invoices, promises, escalations, contact history. Read tools feed the call context; writes land only from structured outcomes, policy-gated and audit-logged.

type Store interface {
    GetCustomer(id string) (*Customer, error)
    GetOpenInvoice(customerID string) (*Invoice, error)
    ListOverdueCustomers() ([]*Customer, error)   // campaign auto-audiences
    MarkPromise(customerID, invoiceID string, date time.Time) error
    Escalate(customerID, reason string) error
    RecordContact(customerID, channel, outcome string) error
}

6. SSE stream — live in your own tooling

GET /api/stream pushes every session and campaign mutation as Server-Sent Events — wire your own dashboards, alerting, or analytics to the live feed.

Why no per-platform plugins? Every "Stripe integration" is the same POST with different field names. callhook's event schema is the universal adapter — one endpoint, idempotency built in, and every automation tool already speaks it. New platform? It's a curl command, not a codebase.