Skip to main content

Webhooks

Webhooks deliver invoice-state changes to a merchant-configured URL the moment they happen. Each webhook target is owned by a single address; the endpoints below let the merchant set, read, and clear it.

All three calls are wallet-signed (not session-signed) — the binding is at the owner level, so the canonical wallet signature is what the server uses to authorize the change.

POST /webhook/set

Register or replace the merchant's webhook URL.

{
"ownerAddress": "0xMerchant…",
"url": "https://merchant.example.com/feemaker-webhook",
"signature": "0xWalletSig…"
}

Signed message: set-webhook:{ownerAddressLower}:{url}.

Response: 200 OK with { "ownerAddress": …, "url": … }.

POST /webhook/get

Read the current webhook URL for an owner. Wallet-signed so a third party can't probe what's configured.

{
"ownerAddress": "0xMerchant…",
"signature": "0xWalletSig…"
}

Signed message: get-webhook:{ownerAddressLower}.

Response: 200 OK with { "ownerAddress": …, "url": "<empty if unset>" }.

POST /webhook/clear

Remove the webhook URL.

{
"ownerAddress": "0xMerchant…",
"signature": "0xWalletSig…"
}

Signed message: clear-webhook:{ownerAddressLower}.

Response: 200 OK with { "removed": true }.

Delivery contract

When set, the server POSTs each invoice-state change to the configured URL as JSON — same payload shape as one element of POST /poll/events. The target should respond with a 2xx within the operator-configured timeout. Failed deliveries retry with exponential backoff; events are still queued on the polling endpoint, so a webhook outage doesn't lose data.