DEV Community

Keshav Sharma
Keshav Sharma

Posted on Originally published at settlematic.com

invoice.paid is useless if anyone can POST it

Your invoicing API is two endpoints people actually use: create invoice, and invoice.paid. Everything else is CRUD. If invoice.paid is an unsigned POST to a URL in your env file, you have built a “mark customer premium” button for the internet.

Contract

  • HMAC-SHA256 over the raw body, secret rotated, timestamp in the signed payload
  • Replay window measured in minutes, not days
  • Idempotency key = invoice id + tx hash
  • Never take status from the JSON without verifying against chain (or your own indexer)

Why crypto makes this sharper

A fake Stripe event is bad. A fake invoice.paid that flips entitlements after a 0.001 ETH dust payment to a reused address is worse. Unique invoice addresses reduce the dust attack. Signatures reduce the “I am a webhook” attack.

Settlematic: Collect live, webhooks for payment state. Gateway sandbox. We already argued this in the signed-webhooks post; this one is the API object: treat invoice.paid as a privileged transition.

Canonical: crypto invoicing API invoice paid webhook. settlematic.com

Top comments (0)