Endpoint consent
Pickware never sends webhook deliveries without confirming that the receiver wants to be pinged. Anyone with a token could otherwise point a subscription at any URL and turn Pickware into a source of unwanted traffic.
Consent is checked when a subscription is created, re-checked every six hours, and asked for again when a disabled subscription is re-activated. While the check does not succeed, the subscription's consentState is Pending, Refused or Lost, and delivery is suspended: notifications keep waiting within their 72-hour retry window and go out once the next check succeeds. A failed check is retried after 15 minutes, then with doubling intervals up to eight hours.
Two proofs are accepted. Pickware tries the first and falls back to the second.
1. Answer the OPTIONS handshake
This is the CloudEvents abuse-protection handshake. Pickware sends
OPTIONS /your/endpoint HTTP/1.1
WebHook-Request-Origin: pickware.com
WebHook-Request-Rate: 120
User-Agent: Pickware-Webhooks/1 (+https://pickware.dev/docs/webhooks)
X-Pickware-Webhook-Subscription-Id: <subscription id>
Consent is granted when the response carries
WebHook-Allowed-Origin: pickware.com
WebHook-Allowed-Rate: 120
The handshake always asks for a rate, so answer WebHook-Request-Rate with WebHook-Allowed-Rate: <requests per minute>, the ceiling Pickware honours per subscription, or * for no limit.
A response without an affirmative WebHook-Allowed-Origin header is not a refusal but an inconclusive answer, whatever its status code. The common case is a framework or CDN that answers every OPTIONS request with 200 and CORS headers before your code runs, then the first proof cannot succeed and Pickware moves on to the second.
2. Echo the signed challenge
Pickware sends a GET to your endpoint with a random challenge in the query string:
GET /your/endpoint?pickware_webhook_challenge=3f6c9c0e1b2a4d5e6f708192a3b4c5d6 HTTP/1.1
X-Pickware-Timestamp: 1756890723123
X-Pickware-Signature: v1=<hmac>
User-Agent: Pickware-Webhooks/1 (+https://pickware.dev/docs/webhooks)
WebHook-Request-Origin: pickware.com
X-Pickware-Webhook-Subscription-Id: <subscription id>
Respond with a 2xx status and the challenge value as the plain response body. The request is signed with the subscription's signing secret exactly like a delivery, over the path including the query string and an empty body, so you can verify that the challenge really came from Pickware before echoing it, see Verifying the signature.
If neither proof succeeds, the subscription's consentState becomes Refused (or Lost, when it had consented before) and lastErrorMessage reports what the last attempt saw, for example The challenge echo answered with status 404. lastErrorStatusCode stays null for a failed consent check, it only reports the status of a failed delivery.
Re-activation after an automatic disable
A subscription that was disabled after ten consecutive abandoned deliveries can only be re-activated with reactivateWebhookSubscription, which performs a fresh handshake. It fails with a CONFLICT error while a cooldown is running (reactivationBlockedUntil): 10 minutes after the first automatic disable, then 1 hour, 6 hours and 24 hours with each further one; a week without an automatic disable resets the escalation. An endpoint that does not consent cannot be resumed.