Webhooks
Set a webhook URL under Project Settings › Notifications and Backwire sends a JSON POST for every report and every status change. One URL per project; the Pro plan.
Events
submission.created— a visitor sent feedback (spam never reaches the webhook).submission.status_changed— someone on the dashboard changed the status;changecarriesfromandto.
Payload
{
"event": "submission.created",
"sent_at": "2026-09-17T10:30:00+00:00",
"project": { "id": "…", "name": "Acme" },
"submission": {
"id": "…", "intent": "bug", "rating": null, "status": "new",
"message": "Checkout button does nothing on mobile",
"page_url": "https://acme.com/checkout", "page_title": "Checkout",
"device": "mobile", "country": "US", "created_at": "…",
"has_contact": true,
"meta": { "version": "1.4.2" },
"dashboard_url": "https://backwire.io/p/…/inbox?s=…",
"prompt": "# Bug report from end user — Acme …"
}
}The reporter's contact details, the visit trail and anything hashed stay in the dashboard; prompt is the same Markdown as “Copy as agent prompt”, ready to paste into an issue body.
Verifying a delivery
Each request carries X-Backwire-Event, a unique X-Backwire-Delivery, and X-Backwire-Signature: sha256=…, an HMAC-SHA256 of the raw body with the signing secret shown next to your webhook URL. One attempt per event; the dashboard is the source of truth.
import { createHmac, timingSafeEqual } from "node:crypto";
export function verify(rawBody: string, header: string, secret: string): boolean {
const expected = "sha256=" + createHmac("sha256", secret).update(rawBody).digest("hex");
return header.length === expected.length && timingSafeEqual(Buffer.from(header), Buffer.from(expected));
}Zapier and Make
Add a Webhooks by Zapier › Catch Hook (or Make Custom webhook) step, paste its URL into Project Settings, send yourself a test report, and map submission.message, submission.page_url and submission.prompt into Jira, Linear, Trello, Notion or wherever the team works.