Skip to main content

Webhooks

Zazpay webhooks allow you to receive automatic real-time notifications about important events that occur in the payment system. This functionality is particularly useful for keeping point-of-sale systems synchronized with transaction status without the need for constant API queries.

Webhooks are delivered as HTTP requests to a URL configured by the merchant. Each notification includes contextual data about the event and headers to help you verify authenticity.

How to configure a webhook

Step 1: Access the Webhooks Dashboard

  1. Navigate to hub.zazpay.mx/webhooks
  2. Ensure you are logged in with an admin or developer user account

Step 2: View Current Webhooks

  • You will see a list of all available webhooks
  • Each webhook displays:
    • Brief description of the event
    • Current status (enabled/disabled)
    • Configuration details

Step 3: Configure a Webhook

  1. Click on the webhook you want to configure

  2. You will be taken to the configuration page where you can set up:

    Basic Settings:

    • Enable/Disable Switch: Toggle the webhook on or off
    • Webhook URL: Enter the endpoint URL where notifications will be sent
    • Request Method: Choose one of: GET, HEAD, POST, PUT, PATCH, DELETE

    Advanced Settings:

    • Custom Headers: Add any additional HTTP headers required by your endpoint
    • Body Structure: Define the fields included in the request body
    • Content Type: Select one of: text/plain, application/json, application/xml, application/x-www-form-urlencoded

Step 4: Save Configuration

  • Review your settings
  • Click save to activate the webhook configuration
  • The webhook will immediately start sending notifications to your specified endpoint

Security and verification

To verify that webhook requests originate from zazpay, implement one of the following:

  • Bearer token: Configure a static token and validate it from the Authorization: Bearer <token> header.

If both are configured, verify both. Reject requests that fail verification with HTTP 401.

Events and payload variables

Different events expose different payload variables. Select the event to see which variables are available to include in the payload.

Transaction Created

The event is emitted when a transaction is created.

Available variables:

VariableTypeDescription
foliostringTransaction folio
statusstringCurrent status at creation time
clientEmailstringClient email
clientPhoneNumberstringClient phone number
amountnumberTransaction amount
ticketstringOptional reference/ticket
storeNamestringStore name
storeIdstringExternal store identifier
createdAtstringCreation timestamp (ISO 8601)
approvedAtstringApproval timestamp if available (ISO 8601)
salesmanReferencestringSalesman reference/identifier
salesmanNamestringSalesman name

Transaction Status Change

The event is emitted when a transaction status changes (e.g., IN_PROGRESS → APPROVED/REJECTED/CANCELED).

Available variables:

VariableTypeDescription
foliostringTransaction folio
statusstringNew status
clientEmailstringClient email
clientPhoneNumberstringClient phone number
amountnumberTransaction amount
ticketstringOptional reference/ticket
storeNamestringStore name
storeIdstringExternal store identifier
createdAtstringCreation timestamp (ISO 8601)
approvedAtstringApproval timestamp if available (ISO 8601)
salesmanReferencestringSalesman reference/identifier
salesmanNamestringSalesman name

Transaction Returned

The event is emitted when a sale is returned (devolución) via /commerce/return-transaction, or in sandbox when a sale is force-returned via /commerce/resolve-transaction with status: "RETURNED". A return also emits Transaction Status Change with status: RETURNED — configure whichever fits your integration (or both).

Available variables: the same 12 variables as Transaction Status Change, plus:

VariableTypeDescription
returnedAtstringReturn timestamp (ISO 8601)
returnReasonstringReason provided by the commerce (empty string when omitted)
returnedAmountnumberTotal amount returned
settlementImpactstringNOT_YET_SETTLED or DISCOUNT_NEXT_SETTLEMENT

Client Affiliated

The event is emitted when a client is created/affiliated in your company.

Available variables:

VariableTypeDescription
namestringClient given name
firstSurnamestringClient paternal surname
secondSurnamestringClient maternal surname
fullNamestringFull name
emailstringClient email
phoneNumberstringClient phone number
affiliationDatestringAffiliation timestamp (ISO 8601)
zipCodestringZIP/postal code

Client Updated

The event is emitted when client data is updated.

Available variables:

VariableTypeDescription
namestringClient given name
firstSurnamestringClient paternal surname
secondSurnamestringClient maternal surname
fullNamestringFull name
emailstringClient email
phoneNumberstringClient phone number
affiliationDatestringOriginal affiliation timestamp (ISO 8601)
zipCodestringZIP/postal code

Payment Received (Conciliación)

The event is emitted when your weekly settlement (corte / conciliación) is paid out and the bank transfer is confirmed. Unlike the other events, this webhook has a fixed, versioned payload — the body structure is not customizable and any configured body template is ignored.

Payload contract (version: "1.0"; future changes will be additive):

{
"event": "PAYMENT_RECEIVED",
"version": "1.0",
"paymentId": 123,
"period": { "startDate": "2026-06-22", "endDate": "2026-06-28" },
"company": {
"name": "My Commerce",
"razonSocial": "My Commerce SA de CV",
"rfc": "MCO010101AAA"
},
"paymentAccount": { "clabe": "**************1234" },
"summary": {
"transactionCount": 42,
"subtotal": 100000.0,
"commission": 3500.0,
"commissionIva": 560.0,
"grossPaid": 95940.0,
"returnCount": 1,
"returnedTotal": 1500.0,
"totalPaid": 94440.0
},
"files": {
"json": { "url": "https://…", "expiresAt": "2026-07-03T18:30:00-06:00" },
"xlsx": { "url": "https://…", "expiresAt": "2026-07-03T18:30:00-06:00" }
},
"sentAt": "2026-07-02T18:30:00-06:00",
"test": false
}
FieldTypeDescription
eventstringAlways PAYMENT_RECEIVED
versionstringPayload contract version (1.0)
paymentIdnumberSettlement identifier — use it as your idempotency key to deduplicate retries
period.startDate/endDatestringSettlement period (YYYY-MM-DD, America/Mexico_City)
companyobjectCommerce name, legal name (razón social) and RFC
paymentAccount.clabestringPayout CLABE masked to the last 4 digits
summaryobjectTransaction count, subtotal, commission, commission VAT, and settlement totals
summary.grossPaidnumberAmount paid before subtracting returns
summary.returnCountnumberNumber of returned sales (devoluciones) in the period
summary.returnedTotalnumberTotal amount of returns subtracted from grossPaid
summary.totalPaidnumberNet amount received: grossPaid − returnedTotal
files.json / files.xlsxobjectSigned download links for the settlement detail. Links expire 24 hours after emission (expiresAt). Contact support or your account manager if you need them re-issued
sentAtstringDelivery timestamp (ISO 8601, America/Mexico_City)
testbooleantrue only for sandbox test deliveries

Settlement detail file (files.json)

The JSON file contains the full settlement detail: { period, company, summary, transactions[], returns[] }. period, company and summary match the webhook payload above. Each entry in transactions[] looks like:

{
"transactionId": "tx-1",
"folio": "1001",
"folioExternal": "EXT-A1",
"ticket": "T-1",
"date": "2026-06-23",
"storeName": "Main Store",
"storeId": "ext_store_456",
"salesmanName": "John Doe",
"amount": 1000.0,
"commission": 35.0,
"commissionIva": 5.6,
"totalPaid": 959.4
}
FieldTypeDescription
transactionIdstringZazPay transaction identifier
foliostringZazPay folio
folioExternalstring | nullYour transaction identifier, as sent when creating the sale (null if none)
ticketstringTicket reference (- if none)
datestringSale date
storeNamestringStore name
storeIdstring | nullYour external store identifier — same meaning as in the transaction webhooks
salesmanNamestringSalesman name
amountnumberSale amount
commissionnumberCommission
commissionIvanumberVAT on the commission
totalPaidnumberNet amount paid for this sale

Returns (devoluciones) that occurred within the settlement period are listed under returns[]. Each returned sale's full amount is subtracted from grossPaid to produce the net totalPaid. Each entry looks like:

{
"transactionId": "55",
"folio": "900",
"folioExternal": "EXT-900",
"ticket": "T-900",
"returnedAt": "2026-06-24T10:00:00-06:00",
"storeName": "Main Store",
"storeId": "ext_store_456",
"salesmanName": "John Doe",
"amount": 400.0,
"returnReason": "Producto defectuoso",
"settlementImpact": "NOT_YET_SETTLED"
}
FieldTypeDescription
foliostringZazPay folio of the returned sale
folioExternalstring | nullYour transaction identifier (null if none)
returnedAtstringWhen the return was registered (ISO 8601, America/Mexico_City)
storeName/storeIdstringStore name and your external store id
amountnumberFull amount of the returned sale (subtracted from grossPaid)
returnReasonstring | nullReason given at return time
settlementImpactstringNOT_YET_SETTLED (sale had not been paid yet) or DISCOUNT_NEXT_SETTLEMENT (sale was paid in a prior corte)

The XLSX file contains the same detail in spreadsheet form: a Transacciones sheet (with the Folio externo and ID externo de tienda columns) and, when there are returns, a Devoluciones sheet.

Notes:

  • Delivery may be retried, so the same paymentId can arrive more than once — deduplicate on it.
  • totalPaid is net of returns (grossPaid − returnedTotal). It reflects the settlement figure reported here; reconcile against your own records using grossPaid and the returns[] detail.
  • To try this webhook end to end without waiting for a real settlement, see Testing the Payment Received (Conciliación) webhook in sandbox.

HTTP methods and content types

  • Allowed methods: GET, HEAD, POST, PUT, PATCH, DELETE
  • For GET and HEAD, no request body is sent. Use headers and query string if needed.
  • For POST, PUT, PATCH, and DELETE, the request body is sent using the configured content type.
  • Supported content types: text/plain, application/json, application/xml, application/x-www-form-urlencoded

Example payload (Transaction Status Change)

{
"folio": "12345678",
"status": "APPROVED",
"clientEmail": "customer@example.com",
"clientPhoneNumber": "9999999999",
"amount": 1500.0,
"ticket": "TCK-12345",
"storeName": "Main Store",
"storeId": "ext_store_456",
"createdAt": "2024-01-15T10:30:00Z",
"approvedAt": "2024-01-15T10:32:15Z",
"salesmanReference": "9999999999",
"salesmanName": "John Doe"
}

Notes:

  • For GET/HEAD deliveries, the same fields can be provided as query parameters, depending on your configuration.
  • Store the idempotency key header we include to deduplicate retries.