DocumentationFeaturesPart 1 of 4

    Webhooks: Send Cogny Events to Slack, Zapier or Your Own Server

    Configure an outbound webhook, pick from eight events, verify the X-Cogny-Signature header and handle retries. Included on Cogny Cloud and AppSumo Tier 3 and Tier 4.

    Cogny pushes events to an https URL you choose, the moment they happen. Use it to post loop results and alerts into Slack, start a Zapier or Make flow, or feed your own systems — without polling and without asking the AI for an update.

    Which plans include webhooks

    PlanWebhooks
    Cogny CloudIncluded
    AppSumo Tier 3 and Tier 4Included
    Free, Solo, Cogny AI, Cogny Pro, AppSumo Tier 1 and Tier 2Not included

    On plans without webhooks the Settings tab is hidden and the API returns 403 with the plan that would include them. If a workspace moves to a plan without webhooks, its endpoints are kept but nothing is sent until it moves back.

    Events

    EventFires when
    report.completedA scheduled report or audit finishes.
    alert.triggeredA budget-pacing or metric-target alert crosses its threshold.
    alert.resolvedThat alert returns to normal.
    ticket.createdCogny files a new recommendation.
    ticket.status_changedA recommendation moves on the board.
    campaign.updatedAn agent writes a change to a connected platform — one event per write.
    loop_run.completedA loop run has been evaluated: outcome, summary, measured metrics and estimated USD impact.
    task.shippedAn agent published something on a connected platform: a campaign, ad, post, page or site.

    Subscribe to specific events, or to * for every event including ones added later. The full machine-readable contract — every event's data schema, the signature scheme and the retry schedule — is at /api/webhook-events with no authentication.

    The envelope

    {
      "id": "5f8b1c2e-…",
      "event": "loop_run.completed",
      "created_at": "2026-10-02T08:14:22.104Z",
      "warehouse_id": "9c1e…",
      "text": "🟢 Loop \"Pause losing ads\" run: success (est. impact $420). → https://app.cogny.com/warehouse/9c1e…/tickets?ticket=…",
      "data": {
        "loop": { "id": "…", "name": "Pause losing ads", "url": "https://app.cogny.com/warehouse/9c1e…/scheduled-prompts/…" },
        "run": { "id": "…", "ticket_id": "…", "run_at": "…", "outcome": "success", "summary": "…", "url": "…" },
        "impact": { "usd": 420, "metrics": { "cpa_change_pct": -12 } },
        "workspace": { "id": "9c1e…", "url": "https://app.cogny.com/warehouse/9c1e…" }
      }
    }
    
    • text is a one-line summary with a link. A Slack incoming webhook posts it as the message, so Slack needs no relay.
    • data is event-specific. Every variant has a workspace object and a deep link to the thing that happened.

    Verifying the signature

    Each request carries:

    X-Cogny-Signature: t=1800000000,v1=<hex hmac-sha256>
    X-Cogny-Event: loop_run.completed
    X-Cogny-Delivery: 5f8b1c2e-…
    X-Cogny-Webhook-Id: 7a3d…
    

    The signed message is ${t}.${rawBody}, keyed with the endpoint's signing secret. Verify against the raw body before parsing JSON, compare in constant time, and reject a t more than 300 seconds from now.

    import { createHmac, timingSafeEqual } from 'crypto';
    
    export function verifyCogny(rawBody, header, secret) {
      const parts = Object.fromEntries(header.split(',').map((p) => p.split('=', 2)));
      const t = Number(parts.t);
      if (!Number.isFinite(t) || Math.abs(Date.now() / 1000 - t) > 300) return false;
      const expected = Buffer.from(createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex'));
      const given = Buffer.from(parts.v1 ?? '');
      return expected.length === given.length && timingSafeEqual(expected, given);
    }
    

    Responses and retries

    • Any 2xx is success. Respond quickly and do your work afterwards.
    • 410 Gone disables the endpoint.
    • Anything else, or no response within 10 seconds, is retried after about 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours and 12 hours — seven attempts over roughly 20 hours.
    • After 20 consecutive failed deliveries the endpoint is disabled, with the reason shown in Settings. Re-enabling it clears the count.

    Every attempt is listed in the endpoint's delivery log with the status code your server returned.

    Endpoint requirements

    Targets must be public https URLs. Plain http, credentials in the URL, private and reserved addresses and internal hostnames are rejected, and redirects are not followed. If your receiver is on a private network, put a public relay in front of it.

    Not covered in this version

    • No built-in email or CRM connectors. For HubSpot, Salesforce, Klaviyo or email, point the endpoint at a Zapier or Make catch hook and map the fields there.
    • No per-event payload customisation. Every subscriber of an event receives the same body.
    • task.shipped doesn't include impact yet. Impact is measured days later and shows on the workspace's Tasks board; loop_run.completed is where measured impact arrives for loops.

    Managing endpoints over the API

    /api/warehouse/{warehouseId}/webhooks (GET, POST), /{webhookId} (PATCH, DELETE) and /{webhookId}/test (POST). Bearer auth with a workspace owner or admin session.

    Reading this with an AI agent? Fetch the raw markdown at /docs/webhooks/index.md or see llms.txt.

    Ready to set this up?
    Start with Solo at $9/mo or talk to us about Cloud.