Validates MercadoPago webhook signatures (HMAC-SHA256).
Call validate/5 on every incoming webhook. It returns {:ok, ts} on success
and {:error, %InvalidSignatureError{}} on failure — an invalid signature is
an expected outcome for any public endpoint, so it is reported as data, not by
raising. Use validate!/5 when you prefer a raising variant.
QR Code notifications are not signed by MercadoPago — do not call this validator for those events.
Example
case Mercadopago.Webhook.Validator.validate(
conn.req_headers |> Map.new() |> Map.get("x-signature"),
conn.req_headers |> Map.new() |> Map.get("x-request-id"),
conn.params["data"]["id"],
webhook_secret,
tolerance_seconds: 300
) do
{:ok, _ts} -> send_resp(conn, 200, "")
{:error, %InvalidSignatureError{} = e} -> send_resp(conn, 401, e.message)
endRaising variant:
:ok = Mercadopago.Webhook.Validator.validate!(x_sig, x_req, data_id, secret)
Summary
Functions
Validates the signature of a MercadoPago webhook notification.
Like validate/5, but returns :ok on success and raises
InvalidSignatureError on failure.
Functions
@spec validate( String.t() | nil, String.t() | nil, String.t() | nil, String.t(), keyword() ) :: {:ok, String.t()} | {:error, Mercadopago.Webhook.Validator.InvalidSignatureError.t()}
Validates the signature of a MercadoPago webhook notification.
Arguments
x_signature- raw value of thex-signaturerequest headerx_request_id- value of thex-request-idheader (may be nil)data_id- value of thedata.idquery parameter (may be nil)secret- HMAC key configured in Tus Integraciones
Options
:tolerance_seconds- max allowed drift between header timestamp and now:supported_versions- list of accepted signature versions (default:["v1"]):now- zero-arity function returning current time in milliseconds (for testing)
Returns
{:ok, ts} on success (where ts is the verified timestamp string),
{:error, %InvalidSignatureError{}} on failure. Raises ArgumentError
when secret is missing — that is a caller misconfiguration, not webhook
input.
@spec validate!( String.t() | nil, String.t() | nil, String.t() | nil, String.t(), keyword() ) :: :ok
Like validate/5, but returns :ok on success and raises
InvalidSignatureError on failure.