PayZuDocs
Sandbox

Webhooks in the sandbox

Delivery only after the URL proves ownership: the X-Callback-Challenge, the pending, verified and failed statuses, and how to re-run the check.

In production, a webhook registered with POST /v1/user/webhooks receives deliveries immediately. In the sandbox anyone can generate a credential and point a webhook anywhere, so delivery only starts after the URL proves it is yours:

  1. On registration, the sandbox sends a POST to the URL with the token in the X-Callback-Challenge header and body {}.
  2. The endpoint answers 2xx echoing the token, either as the raw body or as {"challenge":"<token>"}.
  3. Until it passes, the webhook stays pending and no delivery goes out.

The token travels only in the header, so a service that echoes the received body does not pass: only an endpoint that reads the header on purpose does. The URL must be public HTTPS; private addresses and redirects are refused.

SandboxPOST + X-Callback-Challenge
your endpoint echoes the token
verifieddeliveries start
app.post('/webhook', (req, res) => {
  const challenge = req.get('X-Callback-Challenge');
  if (challenge) return res.status(200).json({ challenge });
  return handleCallback(req, res);
});

Register the webhook

Register the URL with a secret to test the signature. The secret comes back only once in the response.

curl -X POST https://pix.sandbox.payzu.dev/v1/user/webhooks \
  -H "Authorization: Bearer $SANDBOX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://sua-app.com.br/webhook","generateSecret":true}'

Confirm ownership was verified before moving on: GET /sandbox/webhooks/{id}/challenge must answer "status": "verified".

Check and re-run the verification

When a delivery does not happen, check the reason:

curl https://pix.sandbox.payzu.dev/sandbox/webhooks/$WEBHOOK_ID/challenge \
  -H "Authorization: Bearer $SANDBOX_TOKEN"
{
  "webhookId": "cmh2k1x9d0001s6bwjb5bez01",
  "url": "https://sua-app.com.br/webhook",
  "status": "failed",
  "detail": "o endpoint respondeu 2xx sem ecoar o token, no corpo ou em {\"challenge\"}",
  "checkedAt": "2026-08-23T12:00:00.000Z"
}

status is pending, verified or failed. After fixing the endpoint, POST /sandbox/webhooks/{id}/challenge runs the check again. Deliveries follow the production format and signature: see HMAC verification.

On this page