FINANCE API IMPLEMENTATION GUIDE

Invoice webhook security: signatures, retries, deduplication, and minimized payloads

Implement a production receiver for signed invoice events without exposing documents or processing duplicate deliveries twice.

Verify before parsing or acting

Compute HMAC-SHA256 over the exact request bytes using the signing secret shown when the webhook is created. Compare the expected and received signatures with a timing-safe operation. Reject missing or invalid signatures before queueing work or parsing the payload into a business object.

  • Read the raw request body once.
  • Use the exact bytes; re-serializing JSON changes the signature.
  • Keep the signing secret in a secret store.
  • Rotate by creating a replacement hook before disabling the old one.

Assume every delivery can repeat

Network timeouts make at-least-once delivery normal. A sender can deliver successfully and still miss the receiver's response. Deduplicate on the event type and invoice ID or a delivery ID when supplied. Store the receipt before starting side effects, then make the downstream workflow idempotent too.

Acknowledge quickly and process separately

Verify, persist, and return a 2xx response quickly. Do not hold the webhook request open while calling an ERP or sending a long chain of messages. A background job can load the full invoice result from the authenticated API when needed.

Keep the event minimal

A completion event needs only the invoice ID, status, and decision; a failure may add a stable error code. Do not send the source document, extracted line items, bank details, or a full review packet to every webhook destination. The receiver can fetch authorized details by ID.

REPRESENTATIVE CONTRACT

Signed minimal webhook

The values below are synthetic. Use a tenant-scoped key stored as a secret, and evaluate the documented status, decision, evidence, and next action before continuing a workflow.

Representative request
POST https://workflow.example.com/ap-control
Content-Type: application/json
X-AP-Control-Event: invoice.review_required
X-AP-Control-Signature: sha256=<HMAC of the exact body>

{"id":"inv_1042","status":"COMPLETED","decision":"REVIEW_REQUIRED"}
Representative response
HTTP/1.1 204 No Content

# Verify the signature before returning success.
# Store the invoice ID as the delivery deduplication key.

IMPLEMENTATION CHECKLIST

Ship the control with its safety boundary intact.

  • Use HTTPS.
  • Verify the raw-body HMAC.
  • Use a timing-safe comparison.
  • Persist a delivery deduplication key.
  • Return 2xx after durable receipt.
  • Fetch detailed records through the authenticated API.
  • Handle retries and dead-letter alerts.

FREQUENTLY ASKED QUESTIONS

Questions workflow builders ask

Why must verification use the raw body?

Parsing and re-serializing JSON can change whitespace or key order, producing a different HMAC even when the data looks identical.

Should a webhook call the ERP directly?

Prefer durable receipt followed by a background workflow. This keeps acknowledgement fast and makes retries and failures easier to control.

Why are documents omitted from webhook payloads?

Minimized events reduce exposure. An authenticated caller can fetch the retained result or a short-lived document link only when needed.

Test the control with your own authorized workflow.

Start with synthetic or non-sensitive data, inspect the structured evidence, and keep every ERP, vendor, approval, and payment write in your own authorized system.