Reference
Zapier, Make and n8n
Zapier, Make and n8n connect Wavefront to tools it doesn't publish to directly. All three use the REST API with a workspace API key for actions, and event webhooks for triggers.
The API key
An owner creates a key under Settings → API and MCP. Give it the scopes for what your automations do:
| To use | Scopes |
|---|---|
| Any trigger | webhooks and generations:read |
| Start a generation, draft a calendar post, message the strategist | generations:write |
| Publish an approved version | publish |
| Add a workspace document | context:write |
| Export a version | generations:read (a draft that isn't approved also needs generations:write) |
GET /v1/me with the key returns its scopes and workspace, which is how to test a connection. Approval is never available to a key: a person approves in the web app, and the version.approved trigger fires then.
Triggers
| Trigger | Event | Notes |
|---|---|---|
| Draft ready for review | generation.ready_for_review | A draft or revision finished |
| Version approved | version.approved | Carries version_id for publishing and exporting |
| Published | publication.published | Carries publication.url |
| Draft needs input | generation.needs_input | Answer in the web app or over the API |
| New comment | comment.created | Carries comment.excerpt |
| Plan saved | plan.saved | Carries strategy and context_version |
| Suggestions ready | suggestions.ready | New strategy suggestions wait for approval |
A trigger subscribes the platform's URL with POST …/webhooks and removes it with DELETE …/webhooks/{id}. Owners see these subscriptions in Settings → Integrations and can pause or delete them. For test data, use GET …/webhooks/sample?event=.
Actions
| Action | Request |
|---|---|
| Start a generation | POST /v1/workspaces/{ws}/generations |
| Draft a calendar post | POST …/calendar/draft |
| Message the strategist | POST …/studio/messages |
| Add a workspace document | PUT …/context/file |
| Publish an approved version | POST …/versions/{vid}/publish |
| Export a version | GET …/versions/{vid}/export?format=json |
Generation, drafting and the strategist's reply are asynchronous: the action returns an id at once, and a later trigger (Draft ready for review, Plan saved) picks up the result.
Zapier and Make
Wavefront apps for Zapier and Make are not in their public directories yet. Until they are, connect either platform with its own webhook trigger and HTTP request steps: the same subscription, signature check and requests as the n8n recipe below.
n8n
n8n's Webhook, Code and HTTP Request nodes cover every trigger and action.
- Create a Header Auth credential: name
Authorization, valueBearer wf_live_…. Every HTTP Request node uses it. - Add a Webhook node (method
POST, respond immediately) and turn on Raw Body under Options, so the signature can be checked against the exact bytes. Activate the workflow and copy its public production URL. - Subscribe that URL once:
curl -s -X POST "https://wavefront.adwave.com/v1/workspaces/{ws}/webhooks" \
-H "Authorization: Bearer $WAVEFRONT_API_KEY" -H "content-type: application/json" \
-d '{"url":"https://you.app.n8n.cloud/webhook/wavefront-approved","events":["version.approved"],"description":"n8n: approved"}'- Store the returned
secretas an n8n variable,WAVEFRONT_WEBHOOK_SECRET. - Add a Code node after the Webhook node that verifies the signature before anything else runs (self-hosted n8n needs
NODE_FUNCTION_ALLOW_BUILTIN=crypto):
const crypto = require("crypto");
const SECRET = $vars.WAVEFRONT_WEBHOOK_SECRET; // or $env.WAVEFRONT_WEBHOOK_SECRET
const key = Buffer.from(SECRET.replace(/^whsec_/, ""), "base64");
const TOLERANCE_S = 5 * 60;
const out = [];
const items = $input.all();
for (let i = 0; i < items.length; i++) {
const headers = items[i].json.headers;
const id = headers["webhook-id"];
const timestamp = headers["webhook-timestamp"];
const signatures = String(headers["webhook-signature"] || "").split(" ");
const raw = (await this.helpers.getBinaryDataBuffer(i, "data")).toString("utf8");
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > TOLERANCE_S) {
throw new Error("Wavefront webhook: timestamp too old or in the future");
}
const expected = crypto.createHmac("sha256", key).update(`${id}.${timestamp}.${raw}`).digest();
const ok = signatures.some((part) => {
const [version, sig] = part.split(",");
if (version !== "v1" || !sig) return false;
const given = Buffer.from(sig, "base64");
return given.length === expected.length && crypto.timingSafeEqual(given, expected);
});
if (!ok) throw new Error("Wavefront webhook: signature doesn't match");
const body = JSON.parse(raw);
if (body.type === "webhook.test") continue;
out.push({ json: { id, type: body.type, timestamp: body.timestamp, data: body.data } });
}
return out;- Add HTTP Request nodes for the actions, for example
POST https://wavefront.adwave.com/v1/workspaces/{ws}/versions/{{ $json.data.version_id }}/publishwith{"destination_id": "dst_…"}. Turn on Retry On Fail for429and5xx.
webhook-id. If running twice would do harm, deduplicate on id, for example with n8n's Remove Duplicates node.