Build an app

Webhooks

When an app is installed on a workspace and has a webhook URL, Invoist POSTs signed JSON events to that URL.

Events

TypeWhen
document.createdA document was uploaded (API or dashboard).
extraction.completedExtraction finished successfully.
extraction.failedExtraction failed.
review_item.createdAn item was added to the review queue.
review_item.resolvedA review item was resolved.

Payload

JSON
{
  "id": "01a0…",
  "type": "extraction.completed",
  "created_at": "2026-08-20T09:14:11Z",
  "data": {
    "document_id": "…",
    "extraction_id": "…",
    "status": "done"
  }
}

Signature

Header X-Invoist-Signature: t=TIMESTAMP,v1=HMAC_HEX where HMAC-SHA256 is computed over timestamp + "." + raw_body with your webhook secret (shown once when you create or rotate the secret).

Verify (Node)
const crypto = require("crypto");

function verify(header, body, secret) {
  // header: t=1710000000,v1=hex
  const parts = Object.fromEntries(
    header.split(",").map((p) => p.trim().split("="))
  );
  const signed = parts.t + "." + body;
  const expected = crypto
    .createHmac("sha256", secret)
    .update(signed)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(parts.v1)
  );
}

Retries

Failed deliveries (network error or non-2xx) retry up to 3 times with exponential backoff. Use id as an idempotency key.

Headers

  • X-Invoist-Event — event type
  • X-Invoist-Delivery — delivery id
  • X-Invoist-Signature — timestamped HMAC