Skip to content
Pathwize API

Webhooks

Get a signed HTTP call when items finish instead of polling for results.

Register an HTTPS endpoint and Pathwize POSTs a JSON event to it whenever something you care about happens. Each delivery is signed with your endpoint’s secret, retried with backoff for up to 24 hours if your server does not answer with a 2xx, and carries a stable event id so you can ignore duplicates.

Events

EventWhendata
item.labeledAn item reached its final answer (all raters done, or a reviewer decided).task_id, item (same shape as a results row)
item.flaggedThe experts could not label an item: unreadable, wrong data or unresolved disagreement.task_id, item with flags
task.completedThe last open item of a task was finished. Fires again after every new batch that completes.task_id, items_done
pingSent when you press Send test in the dashboard or call the test endpoint.message

Payload

{
  "id": "evt_6f1c2d9a3b4e5f6a7b8c9d0e",
  "type": "item.labeled",
  "created": 1790400000,
  "data": {
    "task_id": "9ecd8b0a-342a-4b9c-a3dc-4cd69e5c5caf",
    "item": {
      "id": "werk-nord-2026-09-25-000871",
      "status": "labeled",
      "result": { "label": "Cardboard", "labels_all": ["Cardboard", "Cardboard"], "agreement": 1, "raters": 2, "flags": [] },
      "group": "werk-nord",
      "captured_at": "2026-09-25T07:12:04+02:00",
      "meta": { "site": "Werk Nord" }
    }
  }
}

Verifying the signature

Every request carries Pathwize-Signature: t=<unix seconds>,v1=<hex> where v1 is HMAC-SHA256 of <t>.<raw body> with your secret. Recompute it over the raw bytes, compare in constant time, and reject timestamps older than five minutes. Pathwize-Event repeats the event type and Pathwize-Delivery identifies the attempt.

import { createHmac, timingSafeEqual } from "node:crypto";

export function verify(rawBody, signatureHeader, secret) {
  const parts = Object.fromEntries(signatureHeader.split(",").map((p) => p.split("=")));
  const expected = createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest("hex");
  const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
  return fresh && timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}

Managing endpoints

Add endpoints under Developers in the dashboard or through the API. The signing secret is returned once, on creation. Up to 10 endpoints per workspace.

POST/webhooks
urlstringrequired
HTTPS endpoint that accepts POST.
eventsstring[]required
One or more of item.labeled, item.flagged, task.completed.
descriptionstring
Free text shown in the dashboard.
curl https://www.gopathwize.com/api/v1/webhooks \
  -H "Authorization: Bearer pw_live_..." \
  -H "Content-Type: application/json" \
  -d '{"url":"https://api.example.com/pathwize/webhook","events":["item.labeled","task.completed"]}'
GET/webhooks

Lists your endpoints with their last delivery status (never the secret).

POST/webhooks/{id}

Sends a signed ping event to the endpoint and returns whether it answered 2xx.

DELETE/webhooks/{id}
Answer fast (2xx within 10 seconds) and do the work afterwards. Deliveries can arrive more than once in rare cases; use id to deduplicate. Results stay available through the results endpoint whether or not a webhook was delivered.