Skip to main content
Register a URL once and Penbox calls it every time a case of the workspace changes: created, renamed, moved to another status, new data, a new task, an email received… No polling. Each call says which case changed and what changed, with the new values: the new title, the data values written, the new status. For anything else, read the case again with Get Case: Penbox stays the source of truth.

Set up

  1. Create a webhook with the workspace and an HTTPS URL.
  2. Store the secret of the response on your server: it signs every call.
  3. Answer each call with a 2xx within 10 seconds, then do your work.
Endpoints belong to one workspace. A partner managing several workspaces registers one endpoint per workspace, with the token of each. Workspace admins can also add, inspect and delete webhooks, and read their delivery log, in Penbox under Settings → Webhooks.

Events

Case templates never send events, only real cases.

Payload

Everything written in one operation comes in one event: renaming a case and moving its status in the same call sends one case.updated with both changes. Within one event, each field appears once with its value at the end of the operation.

Changes

New change types will be added. Ignore the types you do not know instead of failing: a new type never changes the meaning of the existing ones. version only moves for a breaking change to the envelope.

Verify the signature

Every call carries a Penbox-Signature header:
v1 is the HMAC-SHA256, keyed with your secret, of the timestamp, a dot, and the raw request body. Compute it on the raw body, before any JSON parsing, and reject calls older than 5 minutes.
Node.js (Express)

Delivery and retries

Delivery is at least once: the same event can arrive twice, for example after a retry. Its id never changes, so keep the ids you processed and skip the ones you already have. Penbox sends an endpoint its events one at a time, in the order the changes happened: you get case.created before the updates of that case. When your endpoint fails a call, every later event waits for that one’s retry, so the order holds through outages too. Because delivery is at least once, an event you already processed can still come again: skip it by its id, and before applying a value, check that the event’s occurred_at is newer than the last one you applied for that case. See every event sent to an endpoint, its status and the last error in the delivery log. Entries are kept 30 days.