Skip to main content
Version: Latest

Endpoint verification

Hub Chatt2.me checks that you control the HTTPS URL you register. When verification succeeds, the webhook is marked as verified (isVerified: true and verifiedAt set in API responses and in the Hub dashboard). This is separate from Verifying webhook signatures (X-hub-Signature), which applies to ongoing event deliveries after you enable Require signature.

When verification runs

Hub sends a verification request when you create a webhook or update one in a way that affects the endpoint (for example changing the URL). Each run uses a fresh validation value.

What Hub sends

Hub issues a POST to your registered endpoint over HTTPS. The request includes an X-Validation-Token header whose value is a secret string Hub generated for that attempt.

If you configured custom headers on the webhook, Hub sends those headers on the verification request the same way it does for event deliveries, so your endpoint can authenticate the call.

What counts as valid

Your server must respond with HTTP 200. Hub compares the response body (UTF-8) to the token from X-Validation-Token.

With Content-Type: application/json, return the token as a JSON string: the body is valid JSON and is the same encoding you get from JSON.stringify(token) in JavaScript or json.dumps(token) in Python (the token characters plus JSON string quoting and escaping rules). That matches what the Webhooks2.me walkthrough below produces when the custom response body is only {{headers.x-validation-token}}.

If the status is not 200 or the body does not match what Hub expects for that attempt, verification fails and isVerified remains false.

Implementing on your server

Node.js / Express
app.post('/webhooks/chatt2me', (req, res) => {
const token = req.get('x-validation-token');
if (token) {
res.status(200).type('application/json').send(JSON.stringify(token));
return;
}
res.status(200).send('OK');
});
Python / Flask
import json
from flask import Flask, request, Response

app = Flask(__name__)

@app.post('/webhooks/chatt2me')
def webhook():
token = request.headers.get('X-Validation-Token')
if token:
return Response(
json.dumps(token),
status=200,
mimetype='application/json',
)
return Response('OK', status=200)

Handle your normal event payloads when X-Validation-Token is absent; only the verification request includes that header.

Using Webhooks2.me (optional)

Webhooks2.me is a third-party webhook testing service. It is not affiliated with Hub Chatt2.me, but you can use it to obtain a public HTTPS URL that returns the correct body for verification without deploying your own server yet.

  1. Open https://webhooks2.me/ and sign in. Step 1 Step 2 Step 3

  2. Open Settings and find Custom response. Step 4

  3. Choose Add rule: give the rule a name, set the method to POST, status 200, content type application/json. Step 5

  4. Set the response body to:

    {{headers.x-validation-token}}

    Step 6 Step 7 Step 8 Step 9 Step 10 so the response body is the JSON string form of the validation token (same idea as json.dumps / JSON.stringify on the header value).

  5. Use the Webhooks2.me endpoint URL as your webhook endpoint when you create or update the webhook.

After Hub receives a 200 response with a matching body, the webhook becomes verified.

If verification fails

isVerified stays false until a later update succeeds or you fix the endpoint and trigger verification again (for example by updating the webhook). Check webhook logs if deliveries fail for other reasons.

Next steps