Register, test, and monitor webhook deliveries
Goal
Confirm that your webhook endpoints are healthy, diagnose failed deliveries, and export delivery logs for audit. It covers the full lifecycle from the API: register an endpoint, change it, rotate its secret and retire it, plus the monitoring and testing operations.
Prerequisites
- An active API key (
veriko_…). Reading needswebhooks:readand testing needswebhooks:create; registering, changing and retiring needwebhooks:create,webhooks:updateandwebhooks:delete. - A reachable HTTPS receiver. If you do not have an endpoint registered yet, step 2 creates one.
- Your receiver must respond with HTTP 2xx and optionally validate the
X-Webhook-SignatureHMAC-SHA256 header.
Steps
1. List your endpoints
GET /v1/webhooks returns all registered endpoints with their status and subscribed events. The signing secret is not included — it is shown only once at creation time.
curl 'https://api.veriko.mx/v1/webhooks' \
-H 'Authorization: Bearer veriko_••••'{
"data": [
{
"type": "webhook_endpoint",
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"attributes": {
"url": "https://myapp.veriko.mx/hooks/payments",
"status": "active",
"events": ["validation.completed", "validation.failed"],
"created_at": "2025-02-01T12:00:00Z"
}
}
]
}2. Register, update or retire an endpoint
These four operations can be called with your API key — they need the matching permission (webhooks:create, webhooks:update, webhooks:delete).
# Register
curl -X POST 'https://api.veriko.mx/v1/webhooks' -H 'Authorization: Bearer veriko_••••' -H 'Content-Type: application/json' -d '{ "url": "https://myapp.veriko.mx/hooks/payments", "events": ["validation.completed"] }'
# Change the URL or the subscribed events
curl -X PUT 'https://api.veriko.mx/v1/webhooks/f47ac10b-58cc-4372-a567-0e02b2c3d479' -H 'Authorization: Bearer veriko_••••' -H 'Content-Type: application/json' -d '{ "events": ["validation.completed", "validation.failed"] }'
# Retire
curl -X DELETE 'https://api.veriko.mx/v1/webhooks/f47ac10b-58cc-4372-a567-0e02b2c3d479' -H 'Authorization: Bearer veriko_••••'The signing secret is returned only once, at registration. If you lose it or suspect it leaked, rotate it:
curl -X POST 'https://api.veriko.mx/v1/webhooks/f47ac10b-.../regenerate-secret' -H 'Authorization: Bearer veriko_••••'3. Send a test event
After registering or updating an endpoint, send a synthetic test event to confirm your receiver is reachable and processes the signature correctly. Test deliveries do not count toward the consecutive-failure counter that auto-disables endpoints.
curl -X POST \
'https://api.veriko.mx/v1/webhooks/f47ac10b-58cc-4372-a567-0e02b2c3d479/test' \
-H 'Authorization: Bearer veriko_••••'Successful response:
{
"data": {
"type": "webhook_test_result",
"attributes": {
"delivered": true,
"http_status": 200,
"response_time_ms": 143
}
}
}If delivered is false, the error field explains the problem (SSRF block, non-2xx response, etc.).
The delivery received by your endpoint includes these headers:
| header | content |
|---|---|
X-Webhook-Signature | sha256= followed by the HMAC in hexadecimal |
X-Webhook-Signature-Timestamped | t=<seconds>,v1=<hex>: signature of <t>.<body> with the attempt time |
X-Veriko-Event | Event type that originated the delivery |
X-Veriko-Delivery-Id | Stable identifier for deduplicating retries |
X-Veriko-Timestamp | Send time, in ISO 8601 with a Z suffix |
The signature header is generic and configured independently of the service name. The timestamped signature one adds the -Timestamped suffix to that same name. The other three are formed from the service identifier. The different prefixes are deliberate.
Verify the timestamped signature
The X-Webhook-Signature-Timestamped header signs the attempt time together with the body, so the receiver can discard an old delivery that someone sends again. The X-Webhook-Signature header does not change.
import { createHmac, timingSafeEqual } from 'node:crypto';
const WINDOW_SECONDS = 300; // 5 minutes
function verify(header, rawBody, secret) {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
const expected = createHmac('sha256', secret).update(`${parts.t}.${rawBody}`).digest('hex');
const equal =
expected.length === parts.v1.length &&
timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
const recent = Math.abs(Date.now() / 1000 - Number(parts.t)) <= WINDOW_SECONDS;
return equal && recent;
}The 5-minute window is measured against t, the time of that attempt, and not against the timestamp field of the body. A retry arrives up to about 8.6 hours after the event, but with a fresh t; measuring against the body's timestamp would reject legitimate retries. To discard duplicates, X-Veriko-Delivery-Id still applies, as it stays the same across retries: keep it for at least 24 hours.
The amount and account Banxico confirms
When the event is validation.completed and Banxico confirmed the CEP, the delivery body carries an attributes.banxico_confirmed block with the amount, the operation date and time, the tracking key, the sending and receiving bank, and the beneficiary account masked to the last 4 digits. See Webhooks architecture for the full field-by-field body shape.
Learn about a later return
A valid is the verdict of the moment of the query: Banxico can report the return of the payment hours or days later. When that happens, the validation changes to returned and validation.returned is emitted, with the same body as validation.completed plus attributes.payment_status. The endpoint receives only the events it subscribed to, so add that event to the ones it already has:
curl -X PUT 'https://api.veriko.mx/v1/webhooks/f47ac10b-58cc-4372-a567-0e02b2c3d479' -H 'Authorization: Bearer veriko_••••' -H 'Content-Type: application/json' -d '{ "events": ["validation.completed", "validation.returned"] }'The return is detected in a follow-up check: the service rechecks only the valid validations of the last 72 hours, and POST /v1/validations/{id}/recheck requests it on the spot. The full event body is in Webhooks architecture.
3. Inspect delivery logs for one endpoint
View the 50 most recent delivery attempts for a specific endpoint:
curl 'https://api.veriko.mx/v1/webhooks/f47ac10b-.../deliveries?per_page=50' \
-H 'Authorization: Bearer veriko_••••'Each entry shows the HTTP status code, response time, and a truncated response body — enough to diagnose most delivery failures without exposing full response payloads.
4. View deliveries across all endpoints
For a consolidated view of all delivery attempts regardless of endpoint:
curl 'https://api.veriko.mx/v1/webhooks/deliveries' \
-H 'Authorization: Bearer veriko_••••'5. Export delivery logs
Export logs for a specific endpoint or for all endpoints:
# One endpoint — CSV
curl 'https://api.veriko.mx/v1/webhooks/f47ac10b-.../deliveries/export?format=csv' \
-H 'Authorization: Bearer veriko_••••' \
--output webhook-deliveries-f47ac10b.csv
# All endpoints — XLSX
curl 'https://api.veriko.mx/v1/webhooks/deliveries/export?format=xlsx' \
-H 'Authorization: Bearer veriko_••••' \
--output all-webhook-deliveries.xlsxWhat's next
- Monitor API quota and billing-cycle consumption: see Monitor usage.
- Analyze validation trends and counterparty patterns: see Analyze insights.