Vai al contenuto

Webhooks

v1 · Last updated 2026-07-17

Questa documentazione è disponibile solo in inglese.

Register URLs in the Webhooks page to receive events. Each delivery is a JSON POST with this envelope:

{
  "type":      "<event-type>",
  "timestamp": "<ISO-8601 timestamp, e.g. 2026-06-06T12:34:56.789Z>",
  "data":      { /* event-specific fields */ }
}

and the following headers:

  • Pluma-Event — event type (matches type in the body)
  • Pluma-Signature: sha256=<hex> — HMAC-SHA256 of the raw body
  • Pluma-Delivery-Id — unique per attempt; safe to dedupe on

Event catalog

The complete list of event types we currently emit. Subscribe each webhook to a subset (the dashboard exposes a checkbox per event), or leave it empty to receive every event.

EventWhenAvailability
job.completedAsync bulk job finished and the ZIP is ready to download.Hosted + self-hosted
job.failedAsync bulk job aborted. data.error carries a sanitised, customer-safe message — never URLs or stack traces.Hosted + self-hosted
render.url_expiringFires ~24 h before a download URL closes while the artifact still has retention left. Call data.refreshUrl for a fresh URL.Hosted + self-hosted
signature.requestedA sign request was created and the invite email sent.Hosted paid tiers, self-hosted enterprise
signature.signedA signer submitted their signature.Hosted paid tiers, self-hosted enterprise
signature.declinedA signer declined. data.declineReason carries their reason, or null.Hosted paid tiers, self-hosted enterprise
signature.expiredA pending request passed expiresAt unsigned.Hosted paid tiers, self-hosted enterprise
publish.completedA workspace publish job finished. data.imageDigest is the canonical reference for the published artifact.Self-hosted only

Example payload

Every event follows the same envelope — here's job.completed; the data fields per event are listed in the catalog above:

{
  "type":      "job.completed",
  "timestamp": "2026-06-06T12:34:56.789Z",
  "data": {
    "jobId":      "5e4a0a32-8b91-4d8f-9b56-0c2b1ef8d3a1",
    "templateId": "7b1c3f10-6a08-4b97-9f1a-12e6e0c7f0a8",
    "itemsTotal": 100
  }
}

Verify the signature

const crypto = require('crypto');
function verify(rawBody, headerSig, secret) {
  const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(headerSig));
}

Same HMAC-SHA256 pattern in any language. Non-2xx deliveries are retried up to 5 times with exponential backoff (30 s, 2 min, 8 min, 32 min), then marked failed — the dashboard shows every attempt.

Need help?

Open a ticket from the in-app Support page, or email [email protected].