Webhooks and triggers
Two machine surfaces connect Reactor to the rest of your stack without an AI client in the loop: outbound webhooks (Reactor calls your endpoint when something happens) and schedule trigger URLs (your systems call Reactor to start a generation run). Both pair directly with Zapier, Make, or n8n.
Outbound webhooks
Managers add endpoints under Settings → API. Each endpoint subscribes to any subset of six events:
| Event | Fires when |
|---|---|
content.ready | a piece flips to Ready from an auto-generation flow |
content.published | a piece goes live (manual publish, scheduled publish, or a confirmed aggregator hand-off) |
publish.failed | a publish attempt fails |
guard.blocked | the Guard holds a ready piece back from auto-publish |
schedule.generated | a recurring schedule finishes generating an occurrence |
campaign.built | a campaign plan fans out into briefs and calendar cards |
Delivery format
Events arrive as a JSON POST:
{
"id": "<delivery id>",
"event": "content.published",
"createdAt": "2026-07-07T15:04:05.000Z",
"workspace": { "id": "<workspace id>" },
"data": { "contentId": "…", "title": "…", "platform": "x", "url": "…" }
}
data is lean by design: ids plus the human fields needed to render a message without a follow-up call. Two identifying headers ride along: X-Reactor-Event (the event name) and X-Reactor-Delivery (the delivery id, stable across retries).
Verify the signature
Each generic endpoint gets a secret, shown once at creation. Every delivery is signed: X-Reactor-Signature is sha256= followed by the hex HMAC-SHA256 of the exact raw request body. Verify over the raw bytes before parsing:
import { createHmac, timingSafeEqual } from 'crypto';
function verifyReactorWebhook(rawBody, signatureHeader, secret) {
const expected =
'sha256=' + createHmac('sha256', secret).update(rawBody, 'utf8').digest('hex');
const a = Buffer.from(expected);
const b = Buffer.from(signatureHeader ?? '');
return a.length === b.length && timingSafeEqual(a, b);
}
Reject anything that fails verification; the signature is the only proof the event came from Reactor.
Retries and the delivery log
Delivery is attempted immediately with a 10-second timeout, and redirects are not followed. Any 2xx response counts as delivered. Failures retry on a backoff ladder - 1 minute, 5 minutes, 30 minutes, 2 hours - for 5 attempts total. Every attempt lands in the per-endpoint delivery log on Settings → API, with status, response code, and error, so a misbehaving consumer is diagnosable from the UI.
Slack
Pick the Slack kind and paste a Slack incoming-webhook URL. The same events arrive as one-line human messages ("Guard blocked Tuesday's X thread") instead of signed JSON. No Slack app of your own needed.
Schedule trigger URLs
Every recurring schedule can expose a signed trigger URL: POST to it and the schedule generates one occurrence now, through the same path its cron slot uses, guard checks included.
POST https://reactor.tools/api/schedules/<id>/trigger
Authorization: Bearer <token>
(The legacy ?token=<token> query form still works but is deprecated: query strings leak into proxy and CDN logs. Send the token as a Bearer header.)
- Minting and rotating (manager role): from the schedule's menu on the Generate page. The full URL, carrying a 256-bit token, is shown once per rotation; only its hash is stored. Rotating invalidates the old URL. Revoking disables triggering entirely until a new token is minted.
- Response:
202with{ "queued": true, "cardId": "…" }. Generation runs in the background; the draft appears on that calendar card when it finishes. A 202 means accepted, not done. - Overrides: an optional JSON body
{ "topic": "…", "briefMd": "…" }steers just this run. - Limits and errors: 6 triggered runs per schedule per hour. A bad token is
401, a revoked or never-minted URL is404, a paused schedule is409, and a workspace without an active subscription is402.
With Zapier, Make, or n8n
Both directions use the tools these platforms already have. To start generation from your stack, point a plain "webhook request" action at a trigger URL (a launch ticket moves in Jira, n8n POSTs, announcement drafts appear guard-checked on the calendar). To react to Reactor, receive the outbound events with a catch-hook trigger and route them anywhere. For richer control than either, use the MCP server.