POSThttps://api.veriko.mx/v1/webhooks

Create a webhook endpoint

Audience
public
Auth
API key
Permission
webhooks:create
How-to guide →

Registers an HTTPS endpoint that will receive the subscribed events as webhooks. The URL must resolve to a public address: localhost and private ranges are rejected.

Each endpoint can subscribe to different events, among them:

  • validation.* events: they report each verdict of a validation and each step of its automatic retries (e.g. validation.completed, validation.error, and so on).
  • validation.returned event: it fires when a validation that had already come out valid later moves to returned because Banxico reported the return; it is not emitted when the validation is created, where the event is validation.completed. To receive it, subscribe to it in addition to validation.completed.
  • billing.* events: they produce no delivery until something moves in the user's subscription (e.g. billing.subscription_canceled, billing.payment_succeeded, usage quotas, and so on).

Once the cap of registered endpoints is reached, creation responds with HTTP status 422 (with webhook_limit_reached in the body) and the limit value in the meta.limit field.

Parameters
ParameterTypeRequiredDescription
urlstring (uri) (?–2048)required

URL that receives the webhook. It is rejected if it resolves to a private address or is longer than 2048 characters and, in production, also if it does not use HTTPS.

e.g. https://example.com/webhooks/entregas
eventsarray<string> (items: 1–10)required

Events the endpoint subscribes to, from 1 to 10.

descriptionstring | nullnullable (?–255)optional

Free-form label to tell this endpoint apart from the others. null omits it; more than 255 characters responds 422 webhook_description_too_long.

e.g. Alta de pagos en el ERP
Request
curl -X POST 'https://api.veriko.mx/v1/webhooks' \
  -H 'Authorization: Bearer veriko_••••' \
  -H 'Content-Type: application/json' \
  -d '{
    "url": "https://webhook.example.com/platform",
    "events": [
      "validation.completed",
      "validation.failed",
      "validation.error",
      "billing.payment_succeeded",
      "billing.payment_failed"
    ]
  }'

Python example — coming soon.

JavaScript example — coming soon.

PHP example — coming soon.

Response 201WebhookEndpoint — Endpoint created. The `secret` field appears **in this response only** and cannot be read again: it is what verifies the `X-Platform-Signature: sha256=<hex>` signature carried by every delivery.
FieldTypeDescription
type*string

JSON:API resource type. Always webhook_endpoint.

e.g. webhook_endpoint
id*string (uuid)

Unique identifier of the webhook endpoint (UUID v4).

e.g. a1b2c3d4-e5f6-7890-abcd-ef0123456789
attributes*object

Webhook endpoint data (receiver URL, subscribed events, status, and secret).

url*string (uri)

URL that receives the webhook. In production it is rejected if it does not use HTTPS, if it resolves to a private address, or if it is longer than 2048 characters.

e.g. https://example.com/webhooks/entregas
events*array (items: 1–10, unique items)

Events the endpoint subscribes to, from 1 to 10.

description*string | nullnullable

Free-form label to tell this endpoint apart from the others.

e.g. Alta de pagos en el ERP
status*string

active receives deliveries. disabled was manually turned off. auto_disabled was turned off by the platform after exceeding the consecutive-failure threshold.

e.g. active
consecutive_failures*integer

Number of consecutive failures. Resets on the first success.

e.g. 0
last_delivery_at*TimestampUTC | null

Date and time of the last successful delivery, in ISO 8601 UTC. null when the endpoint has not completed a delivery yet.

secretstring

Shared secret for signature verification. Only present in the create and rotate-secret responses; omitted from every other response. It is used to validate the X-Webhook-Signature and X-Webhook-Signature-Timestamped headers on each delivery.

e.g. a0b1c2d3e4f5061728394a5b6c7d8e9f00112233445566778899aabbccddeeff
secret_hintstring

Last 4 characters of the secret, prefixed with .... Present on any response where the full secret is hidden.

e.g. ...4f2a
created_at*string (date-time)

ISO 8601 timestamp in UTC with an explicit Z suffix; for example, "2026-05-01T05:14:38Z". The *_at, *_end, *_start, and *_date fields follow this format. meta.datetime describes the same contract in the response.

e.g. 2026-05-01T05:14:38Z
updated_at*string (date-time)

ISO 8601 timestamp in UTC with an explicit Z suffix; for example, "2026-05-01T05:14:38Z". The *_at, *_end, *_start, and *_date fields follow this format. meta.datetime describes the same contract in the response.

e.g. 2026-05-01T05:14:38Z
Response status codesPOST /v1/webhooks
StatusClassDescriptionBody
2012xxEndpoint created. The secret field appears in this response only and cannot be read again: it is what verifies the X-Webhook-Signature: sha256=<hex> signature carried by every delivery.WebhookEndpoint
4004xxThe request body is empty or is not valid JSON, or the URL points to a non-public address.ErrorResponse
4014xxAuthentication is required or the provided credentials are invalid.ErrorResponse
4034xxInsufficient permissions.ErrorResponse
4134xxThe request body exceeds the maximum accepted size (body_too_large).ErrorResponse
4224xxThe URL, the event list, or description failed validation, or the account has reached its endpoint cap. webhook_url_invalid_type and webhook_description_invalid_type fire when the field arrives as a type other than a string; webhook_description_too_long when description exceeds 255 characters. Every field-level error carries source.pointer.ErrorResponse
4294xxRate limit exceededErrorResponse
Errors from POST /v1/webhooks
StatusCodeExample
400body_empty

The request body is empty.

Envelope
meta.request_id
e6f7a2b3c4d55d4c3b2a7f6e
400invalid_json

The body is not valid JSON.

Envelope
meta.request_id
f7a2b3c4d5e66e5d4c3b2a7f
400url_dns_failed

The host name could not be resolved.

Envelope
meta.request_id
d4e5f6a1b2c44c2b1a6f5e4d
400url_ssrf_blocked

The given URL resolves to a non-public address.

Envelope
meta.request_id
d4e5f6a1b2c55c2b1a6f5e4d
401unauthorized

Invalid or missing authentication credentials.

Envelope
meta.request_id
c4d5e6f7a8b99b8a7f6e5d4c
403permission_denied

You do not have permission to access this resource.

Envelope
meta.request_id
d5e6f7a8b9c00c9b8a7f6e5d
413body_too_large

The request body is too large.

Envelope
meta.request_id
1a2b3c4d5e6ff6e5d4c3b2a1
422validation_error

The url field is required.

Envelope
source.pointer
/data/attributes/url
meta.request_id
b4c5d6e7f8a99a8f7e6d5c4b
422webhook_description_too_long

The description field must not exceed 255 characters.

Envelope
source.pointer
/data/attributes/description
meta.request_id
e6f7a2b3c4d55d4c3b2a7f6e
422webhook_event_invalid

The given event does not exist. The rejected event is in meta.event.

Envelope
source.pointer
/data/attributes/events
meta.request_id
c4d5e6f7a2b33b2a7f6e5d4c
422webhook_events_required

The endpoint must subscribe to at least one event.

Envelope
source.pointer
/data/attributes/events
meta.request_id
a2b3c4d5e6f77f6e5d4c3b2a
422webhook_events_too_many

An endpoint accepts at most 10 events.

Envelope
source.pointer
/data/attributes/events
meta.request_id
b3c4d5e6f7a22a7f6e5d4c3b
422webhook_limit_reached

The maximum number of allowed endpoints has been reached. The applied cap is in meta.limit.

Envelope
meta.request_id
d5e6f7a2b3c44c3b2a7f6e5d
422webhook_url_invalid_format

The URL is not a valid URL.

Envelope
source.pointer
/data/attributes/url
meta.request_id
c3d4e5f6a1b22b1a6f5e4d3c
422webhook_url_not_https

The URL must use HTTPS.

Envelope
source.pointer
/data/attributes/url
meta.request_id
d4e5f6a1b2c33c2b1a6f5e4d
422webhook_url_required

The url field is required.

Envelope
source.pointer
/data/attributes/url
meta.request_id
a1b2c3d4e5f66f5e4d3c2b1a
422webhook_url_too_long

The URL cannot exceed 2,048 characters.

Envelope
source.pointer
/data/attributes/url
meta.request_id
b2c3d4e5f6a11a6f5e4d3c2b
429rate_limit_exceeded

Rate limit exceeded. Try again in 45 seconds.

Envelope
meta.request_id
f7a8b9c0d1e22e1d0c9b8a7f
Response headers
  • Retry-After: integer — Seconds to wait before retrying. Matches the endpoint's rate-limit window (typically 60s for list endpoints, 1-5s for in-flight idempotent operations).
  • X-RateLimit-Limit: integer — Configured request cap for this bucket. It is emitted on every 429 and, on the authenticated API, also on successful responses, where it is the per-key cap of the account plan.
  • X-RateLimit-Remaining: integer — Requests remaining in the current window. Always 0 at the moment of the 429; on a successful response of the authenticated API it is what is left of the per-key cap.
  • X-RateLimit-Reset: integer — Absolute Unix epoch (seconds) when the window resets. Emitted on every 429, alongside Retry-After, and on successful responses of the authenticated API. Per-endpoint overrides exist (e.g. `rate_limited_login`).