Skip to content
Developer guide

OXXO

Mexico México oxxo paymentData paymentFormUrl

These guides use the existing API. Direct integration keeps Key2Pay-Version: 2026-05-01 (also the default when omitted): HTTP 200, transactionId and payment instructions or paymentFormUrl. Opting into 2026-10-12 returns HTTP 201 awaiting_consent and checkoutUrl first. Hosted checkouts always collect buyer acceptance. Keep your current version and handle its response; a retry keeps the original contract.

Create with the selected method

Select paymentMethodId from your shop's catalogue. Submit the real buyer details required by that route. Use your shop's permitted input currency and display the returned local amount and currency without recalculating them.

javascript
// Backend only. Example amounts: use your shop's permitted input currency.
const response = await fetch("https://sandbox.key2pay.ai/api/v1/payments", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PAYMENT_SECRET}`,
    "Content-Type": "application/json",
    "Key2Pay-Version": "2026-05-01",
    "Idempotency-Key": "your-order-attempt-1"
  },
  body: JSON.stringify({
  "amount": 500,
  "currency": "MXN",
  "country": "MX",
  "paymentMethodId": "PAYMENT_METHOD_ID_FROM_YOUR_CATALOGUE",
  "merchantOrderId": "your-unique-order-id",
  "hostedCheckout": false,
  "userName": "Buyer Fullname",
  "userEmail": "buyer@example.com",
  "userPhone": "+525512345678",
  "documentId": "BUYER_DOCUMENT"
})
});
const result = await response.json();
if (!response.ok) throw new Error("Review the API error before retrying");
// Keep transactionId; render returned paymentData or open paymentFormUrl.

What to display in your checkout

For the OXXO sandbox method sbx_cash, barcode and digitableLine intentionally contain the same numeric string. They are two presentations of one payment code, not two payments. The example below is simulated and cannot be paid at a store.

json
{
  "paymentData": {
    "method": "oxxo",
    "reference": "SBX1XBET0001",
    "barcode": "93022833525773",
    "digitableLine": "93022833525773",
    "amountLocal": 50,
    "currencyLocal": "MXN"
  }
}
FieldHow to display it
barcodeThe value to encode as a Code 128 barcode for OXXO. It is a string, not an image or an image URL.
digitableLineDisplay the returned string as readable, copyable text beneath the barcode. In this sandbox example it matches barcode. If the OXXO response omits it, display barcode as the readable value.
referenceShow separately as Reference / tracking ID. The SBX-prefixed sandbox reference identifies the test order; do not encode it instead of the numeric barcode. In production, preserve the provider-returned reference and barcode without inventing either value.
text
[Code 128 graphic encoding 93022833525773]
93022833525773  [Copy]
Reference / tracking ID: SBX1XBET0001
Amount to pay: MXN 50.00
Keep all three fields as strings to preserve leading zeros. Never generate production codes from a transaction ID, copy a sandbox example into production, or assume barcode and digitableLine are identical for other payment methods. Display amountLocal and currencyLocal, respect paymentData.dueDate when provided, and stop offering payment once the voucher expires. Confirm payment using the signed webhook or authenticated payment status, not the presence of a barcode.

Confirm the payment

Keep transactionId as the platform identifier and merchantOrderId as your order identifier. Query GET /payments/{transactionId} or handle signed POST webhooks idempotently. Creating instructions, opening a bank link or returning to your site does not confirm a payment. Keep the same Idempotency-Key and request body if an attempt needs recovery.

Webhook contract and signatures →
Key2Pay Developer documentationAPI v1
Documentation
Dashboard