Slack API · error code

Slack error url_verification: Request URL fails verification / events stop

ConfigurationEvents API & webhooks

Last verified against Slack API reference - chat.postMessage errors

What Slack returns
{"type": "url_verification", "challenge": "..."}

What error url_verification means

Not a Web API error string, but the failure mode that silences more Slack bots than any other: your event endpoint fails Slack's verification, so events never start — or stop — arriving. When you set a Request URL for the Events API, Slack immediately POSTs a JSON body with "type": "url_verification", a token, and a challenge string, and your endpoint must answer HTTP 200 echoing that challenge value back (plain text, form-encoded, or JSON — all three are documented as acceptable). Until the handshake succeeds, the URL cannot be saved; if your handler times out, errors, or returns anything but the challenge, the configuration UI shows the failure and offers a Retry.

Once verified, ongoing health is governed by hard rules. The documentation requires that "Your app should respond to the event request with an HTTP 2xx within three seconds" — otherwise the delivery counts as failed and Slack retries up to three times ("nearly immediately", after 1 minute, after 5 minutes), marking retries with x-slack-retry-num and x-slack-retry-reason headers (reasons include http_timeout, connection_failed, ssl_error, http_error). And the enforcement clause with real teeth: when failures exceed "95% of delivery attempts" within 60 minutes, "your application's event subscriptions will be temporarily disabled." A dead endpoint doesn't just miss events — it gets your subscription turned off.

The third leg is request signing. Slack sends an X-Slack-Signature header (an HMAC-SHA256 over the basestring v0:timestamp:request_body using your app's signing secret) plus X-Slack-Request-Timestamp; you verify by recomputing and comparing with a constant-time function, rejecting stale timestamps (the docs' example rejects anything more than five minutes off) to block replays. Two classic self-inflicted wounds: verifying against the wrong app's signing secret after recreating an app, and computing the HMAC over a parsed-and-reserialized body instead of the raw bytes — both make you reject every genuine Slack request, which then cascades into the 95% disablement.

What it looks like

POST /slack/events
{
  "token": "Jhj5dZrVaK7ZwHHjRyZWjbDl",
  "challenge": "3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P",
  "type": "url_verification"
}

HTTP 200 OK
Content-type: application/json
{"challenge": "3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P"}

Why it happens

  • The endpoint isn't publicly reachable when the URL is saved (localhost, firewall, auth layer, expired tunnel).
  • Cold starts or slow handlers exceed the 3-second acknowledgment budget, failing verification and later deliveries.
  • The handler doesn't echo the challenge value (wrong field, wrong content type, middleware consuming the body).
  • Signature verification uses the wrong signing secret or a re-serialized body, rejecting all real requests.
  • SSL problems — Slack validates the certificate before delivering (ssl_error retry reason).

How to fix Slack error url_verification

  1. 1Make the endpoint publicly reachable over valid HTTPS; during development use a tunnel and re-verify when its URL changes.
  2. 2Handle type url_verification first in the request path: immediately return 200 with the challenge value.
  3. 3Acknowledge every event with 200 within 3 seconds and process asynchronously (queue, worker).
  4. 4Verify signatures against the raw request body with the current app's signing secret, allowing the documented ~5-minute timestamp window.
  5. 5Log x-slack-retry-num / x-slack-retry-reason and deduplicate retried deliveries by event_id.
  6. 6If subscriptions were disabled after sustained failures, fix the endpoint and re-enable/re-verify in the app config.

How to stop it recurring

Separate acknowledgment from processing permanently — a queue between the HTTP handler and your logic keeps you inside 3 seconds forever — and monitor retry headers as an early-warning signal before the 95% disablement trips. Keep the signing secret deployment-managed and rotated with the app. The full delivery contract is tabulated in Slack Events API limits, and endpoint debugging is covered step by step in the webhook debugging guide and Slack bot not responding.

Official reference: Slack API reference - chat.postMessage errors. See all Slack error codes or the Slack limits and quotas.

Related codes

Error url_verification - quick answers

What does Slack error url_verification mean?

Not a Web API error string, but the failure mode that silences more Slack bots than any other: your event endpoint fails Slack's verification, so events never start — or stop — arriving.

How do I fix Slack error url_verification?

1. Make the endpoint publicly reachable over valid HTTPS; during development use a tunnel and re-verify when its URL changes. 2. Handle type url_verification first in the request path: immediately return 200 with the challenge value. 3. Acknowledge every event with 200 within 3 seconds and process asynchronously (queue, worker). 4. Verify signatures against the raw request body with the current app's signing secret, allowing the documented ~5-minute timestamp window. 5. Log…

Stop debugging Slack by hand

Connect the channel through Conferbot: tokens, webhooks and retries are handled, failures show as readable status.