IpInkpacket

Blog

Webhook signature verify checklist

Verify Inkpacket webhooks as t=<unix>,v1=<hex> with HMAC-SHA256 of timestamp.body and the workspace signing secret. Reject a mismatch. That is signature-verify honesty — not a test-send button.

Each Inkpacket webhook POST includes X-Inkpacket-Event and X-Inkpacket-Signature as t=<unix>,v1=<hex>. Verify with HMAC-SHA256 of timestamp.body using the workspace signing secret. Compare the header you received to the header you compute. Reject a mismatch. Reject a body you re-serialized. That is signature-verify honesty: the hex is the proof the POST is ours, Settings has no test-send, and a 200 on an unverified body is not an envelope status you can file.

Which events to persist is listen for envelope status webhooks. The retry queue is webhook retries explained and when webhook delivery fails. The Bearer loop is mint and revoke API Bearer tokens. Desk help is Docs. This guide is the verify checklist itself.

The FAQ points at signed webhooks. Features lists the same POST under outbound webhooks. Ask Inkpacket for webhook signature verify checklist to open this article. Ask how do webhooks work to open help. Ask test webhook to open Settings. Those phrases stay on the product screens. This article is the public version of the HMAC.

The checklist

  1. Read the raw body bytes. Do not JSON.parse and stringify before the HMAC.
  2. Parse X-Inkpacket-Signature as t=<unix>,v1=<hex>.
  3. Compute HMAC-SHA256 of `${timestamp}.${rawBody}` with the workspace signing secret.
  4. Build t=<unix>,v1=<hex> from that digest. Compare it to the header you received.
  5. Reject a mismatch. Reject a missing header. Optionally reject a stale timestamp.
  6. Then read X-Inkpacket-Event and the JSON. Persist the envelope id plus the event name.

Settings shows the signing secret and the last 12 deliveries with status, attempt count, and last error. Rotate the secret in Settings if it leaks. A rotated secret does not replay failed rows. There is no test-send or replay button — send an envelope after saving a URL. HTTPS is required except on localhost or .test hosts. A missing URL means no delivery is queued. Envelope send still succeeds if the webhook fails. Do not treat a delivery-log row as a second envelope. Do not mint a twin envelope because the first POST missed — fix the URL or the verify, then wait for the hourly retry.

What verify is not

  • Not iframe postMessage. The parent tab can be forged. Wait for this POST, or GET the envelope with a Bearer token.
  • Not a Stripe billing webhook. Checkout is not open. This signature is the envelope lifecycle.
  • Not HTTP 429. Access-code lockout is a PIN. The send guard is HTTP 402 ENVELOPE_LIMIT.
  • Not a second envelope. A replayed delivery is the same envelope id.

Embedded signing posts viewed, signed, and completed to the parent. That is UI. Embedded iframe parent page checklist is that frame. Your backend should wait for a verified webhook. API fill then send is how a worker creates the envelope that will later fire these events.

Events you prove

  • envelope.sent, envelope.viewed, envelope.signed, envelope.completed.
  • envelope.expired, envelope.declined, envelope.voided, envelope.corrected.

A decline or a void can arrive instead of completed. A multi-signer envelope can fire signed more than once. Completed means the stamped PDF exists. Treat corrected as an update to an id you already stored. The first POST is immediate. Failed deliveries stay pending and retry on the hourly envelope job, up to 5 attempts, then the row is marked failed. Fix the URL or the verify. Do not send a twin envelope to “retry the webhook.” If you only persist completed, you will miss a decline that stopped the deal and a void you triggered yourself. Read reading an audit trail for the human copy of the same lifecycle the signature is proving.

Workspace URL or per-packet URL

A workspace URL covers every envelope that does not override it. A per-packet webhookUrl on create or send is for one envelope. Staging should not share production’s signing secret or destination. Members cannot mint API tokens; they also should not hold the webhook secret. Owners and admins open /desk/settings#webhooks.

Caps and what is not open yet

A verified POST is not a send. The send that created the envelope already counted. Free allows 5 packets a month. Free at 5 packets a month is the live cap desk send, bulk rows, Web Form fills, and API send share. Hitting it returns HTTP 402 ENVELOPE_LIMIT. Starter is 20 envelopes — more than Free — plus 3 published Web Forms. Seat counts are planning numbers; invite does not refuse when a workspace is full.

Billing is published, not charging. Checkout is not open. Text-message (SMS) is coming soon. Drive missing: Drive not configured. Stripe off: Payments not live. Those flags do not skip the HMAC or invent a test-send. The FAQ and Webhooks use HMAC-SHA256 of timestamp.body in the same words.

Verify first. Persist second. File the stamped PDF when completed arrives. Open a workspace on Free — see published pricing — and send one throwaway so signature-verify honesty is a hex you have checked before a production destination trusts the body.

Open a workspace on Free

Billing is published, not charging. Send an envelope from the desk without a card.

Open a workspace