IpInkpacket

Blog

Webhook retries explained

How Inkpacket delivers signed webhook POSTs: first attempt immediately, pending retries on the hourly envelope job, 5 attempts then failed, the last-12 log, and why there is no replay button.

A webhook is how Inkpacket tells your system that an envelope moved. You set a workspace URL in Settings, or pass webhookUrl on create or send. Inkpacket POSTs a signed JSON body on sent, viewed, signed, completed, expired, declined, voided, and corrected. The envelope send still succeeds if that POST fails. The signing link does not wait on your server.

This guide is the delivery queue: immediate first try, hourly retries, five attempts, then failed. The verify steps and event list live in public API and signed webhooks and Docs. Features is outbound webhooks.

What the queue actually does

The first POST is attempted immediately when the event happens. If your endpoint returns 2xx, the row is done. If it times out, refuses, or returns a non-2xx, the delivery stays pending. The hourly envelope job retries pending rows, up to 5 attempts in total. After 5 failures the row is marked failed. Settings shows the last 12 deliveries with status, attempt count, and last error.

There is no test-send or replay button. Send an envelope after saving a URL if you want a real sent event. A missing URL means no delivery is queued — Inkpacket does not invent a destination. HTTPS is required except on localhost or .test hosts.

Pending is not failed. It means the first try missed and the hourly job still has attempts left. Failed means those five tries are spent. Do not treat a quiet Settings page as “nothing happened” — if the URL was missing, nothing was queued. If the URL was saved after the event, that event will not backfill.

Headers you must verify

Each request 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. Reject stale timestamps. Rotate the secret in Settings if it leaks. Do not trust the JSON until the hex matches in constant time.

Make retries boring

Your endpoint should acknowledge quickly and do slow work after. Return 2xx once you have persisted the event id or the envelope id plus event name. If you return 500 because a downstream CRM write failed, Inkpacket will retry the same POST. Design that write to be safe to see twice.

  1. Read the raw body. Verify the signature before you parse for business logic.
  2. Store a delivery key (envelope id + event + timestamp, or whatever you already unique on).
  3. Return 2xx. Fan out to your own workers after the acknowledge.
  4. If you must fail, fail closed on signature mismatch — do not 2xx a forged body.

A retry is not a second envelope. It is the same event trying to reach you again. Do not create a twin invoice because viewed arrived twice. The desk audit trail is still the human record — how to read an audit trail. Webhooks are for systems. Iframe postMessage is for a parent tab. Those three are not interchangeable.

When a row is marked failed

After five attempts the log stops trying that delivery. There is no replay control in this pass. If you still need the state, read the envelope on the desk or GET it from /api/v1/packets with your Bearer token. Fix the URL or the handler, then wait for the next real event. Do not void an envelope just to generate traffic.

Common failures are predictable: HTTP instead of HTTPS on a public host, a firewall that drops unknown POSTs, a handler that reads a parsed body and cannot recompute the HMAC, a 30-second sync to another vendor that times out. Settings will show the last error. Read it before you rewrite the worker.

Send still works when delivery does not

Operators should not block a send on webhook health. The signer still gets a token — or the desk still copies the URL when Resend is missing. Free allows 5 packets a month on that send path. Free at 5 packets a month is the cap API send shares. Starter is 20 envelopes. Seat counts are planning numbers. Checkout is not open. Drive not configured is an unrelated flag. Text-message (SMS) is coming soon. Neither pauses the webhook queue.

Event order follows the envelope: sent, then viewed, then signed, then completed — or declined, voided, corrected, expired when those happen. A multi-signer envelope can fire signed more than once. Completed is the close. If you only persist completed, you will miss a decline that stopped the deal. What a completed envelope includes is the filed PDF; the webhook is the signal that it exists.

Workspace URL versus per-packet URL

A workspace URL in Settings covers every envelope that does not override it. A per-packet webhookUrl on create or send is for a single envelope — useful when one customer’s app should hear about their envelopes and not yours. Tokens and secrets stay inside the workspace. Staging should not share production’s signing secret or destination.

Save the URL. Send one envelope. Watch the last-12 log. Verify the signature. Return 2xx. That is the whole loop. If you are still choosing who starts the envelope, API vs desk for ops teams is the split. Open a workspace on Free and point a localhost or .test handler at a real send before you promise a production destination.

Open a workspace on Free

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

Open a workspace