Skip to main content
OXXO is a cash payment method in Mexico that allows buyers to pay at physical OXXO convenience stores using a unique reference code. Due to being a physical payment method, there may be a delay in processing the payment.

Setup

To create an OXXO account, request credentials.

Credentials

When setting up OXXO in the dashboard, configure the following credentials:
  • Private key - The private key from OXXO.
  • Child company ID (optional) - The child company ID if applicable.
  • Webhook public key (optional) - The public key used to verify webhook signatures.
  • Approval URL (optional) - A custom frontend URL for rendering your own barcode page. See Custom voucher page below.
  • Company name (optional) - The company name displayed on the voucher.
  • RFC (optional) - The RFC (tax ID) displayed on the voucher.

Capabilities

Supported countries

Supported currencies

Limitations

  • Cart items required - Cart items must be included with every transaction and must match the transaction amount. If they do not match, a single cart item for the correct amount replaces the original items.

Integration

The default integration for OXXO uses a hosted payment page where the charge is created once the buyer accepts. The payment reference expires after 7 days. Start by creating a new transaction with the following required fields.
var transaction = await client.Transactions.CreateAsync(
  transactionCreate: new TransactionCreate()
  {
    Amount = 1299,
    Currency = "MXN",
    Country = "MX",
    PaymentMethod =
      TransactionCreatePaymentMethod.CreateRedirectPaymentMethodCreate(
        new RedirectPaymentMethodCreate()
        {
          Method = "oxxo",
          Country = "MX",
          Currency = "MXN",
          RedirectUrl = "https://example.com/callback",
        }
      ),
  }
);
amount := int64(1299)
currency := "MXN"
country := "MX"
method := components.RedirectPaymentMethodCreateMethodOxxo
redirectUrl := "https://example.com/callback"

redirectPaymentMethodCreate := components.RedirectPaymentMethodCreate{
  Method: method,
  Country: country,
  Currency: currency,
  RedirectURL: redirectUrl,
}
paymentMethod := components.CreateTransactionCreatePaymentMethodRedirectPaymentMethodCreate(redirectPaymentMethodCreate)

transactionCreate := components.TransactionCreate{
  Amount:        amount,
  Currency:      currency,
  Country:       &country,
  PaymentMethod: &paymentMethod,
}

transaction, err := client.Transactions.Create(ctx, transactionCreate, nil, nil, nil)
CreateTransactionResponse transactionResponse = gr4vyClient.transactions().create()
  .transactionCreate(TransactionCreate.builder()
    .amount(1299L)
    .currency("MXN")
    .country("MX")
    .paymentMethod(TransactionCreatePaymentMethod.of(RedirectPaymentMethodCreate.builder()
      .method(RedirectPaymentMethodCreateMethod.OXXO)
      .country("MX")
      .currency("MXN")
      .redirectUrl("https://example.com/callback")
      .build()))
    .build())
  .call();

Transaction transaction = transactionResponse.transaction().orElse(null);
$transactionCreate = new TransactionCreate(
  amount: 1299,
  currency: 'MXN',
  country: 'MX',
  paymentMethod: new RedirectPaymentMethodCreate(
    method: 'oxxo',
    country: 'MX',
    currency: 'MXN',
    redirectUrl: 'https://example.com/callback'
  )
);
$response = $client->transactions->create($transactionCreate);
$transaction = $response->transaction;
transaction: models.Transaction = client.transactions.create(
  amount=1299,
  currency="MXN",
  country="MX",
  payment_method={
    "method": "oxxo",
    "country": "MX",
    "currency": "MXN",
    "redirect_url": "https://example.com/callback",
  }
)
const transaction = await client.transactions.create({
  amount: 1299,
  currency: "MXN",
  country: "MX",
  paymentMethod: {
    method: "oxxo",
    country: "MX",
    currency: "MXN",
    redirectUrl: "https://example.com/callback"
  }
})
After the transaction is created, the status is set to processing. The payment reference expires after 7 days.
{
  "type": "transaction",
  "id": "ea1efdd0-20f9-44d9-9b0b-0a3d71e9b625",
  "payment_method": {
    "type": "payment-method",
    "approval_url": "https://cdn.gr4vy.com/connectors/..."
  },
  "method": "oxxo"
}
Redirect the buyer to the approval_url where they receive the OXXO payment reference. Once the buyer pays at an OXXO store and the payment is confirmed through a webhook, the transaction progresses to a capture_succeeded state.

Custom voucher page

By default, OXXO delays the charge until the buyer accepts on the hosted page. To charge upfront and render your own barcode page, set a custom approval URL either at the connection level (in the connector credentials) or per transaction using connection options. When a custom approval URL is set, the OXXO reference is appended as a query parameter, for example: https://merchant.com/voucher?reference=123456.
var transaction = await client.Transactions.CreateAsync(
  transactionCreate: new TransactionCreate()
  {
    Amount = 1299,
    Currency = "MXN",
    ConnectionOptions = new TransactionCreateConnectionOptions()
    {
      OxxoOxxo = new ConnectionOptionsOxxoOxxo()
      {
        ApprovalUrl = "https://merchant.com/voucher",
      },
    },
    PaymentMethod =
      TransactionCreatePaymentMethod.CreateRedirectPaymentMethodCreate(
        new RedirectPaymentMethodCreate()
        {
          Method = "oxxo",
          Country = "MX",
          Currency = "MXN",
          RedirectUrl = "https://example.com/callback",
        }
      ),
  }
);
amount := int64(1299)
currency := "MXN"
country := "MX"
method := components.RedirectPaymentMethodCreateMethodOxxo
redirectUrl := "https://example.com/callback"

connectionOptions := components.TransactionCreateConnectionOptions{
  OxxoOxxo: &components.ConnectionOptionsOxxoOxxo{
    ApprovalUrl: gr4vy.String("https://merchant.com/voucher"),
  },
}

redirectPaymentMethodCreate := components.RedirectPaymentMethodCreate{
  Method: method,
  Country: country,
  Currency: currency,
  RedirectURL: redirectUrl,
}
paymentMethod := components.CreateTransactionCreatePaymentMethodRedirectPaymentMethodCreate(redirectPaymentMethodCreate)

transactionCreate := components.TransactionCreate{
  Amount:            amount,
  Currency:          currency,
  Country:           &country,
  ConnectionOptions: &connectionOptions,
  PaymentMethod:     &paymentMethod,
}

transaction, err := client.Transactions.Create(ctx, transactionCreate, nil, nil, nil)
CreateTransactionResponse transactionResponse = gr4vyClient.transactions().create()
  .transactionCreate(TransactionCreate.builder()
    .amount(1299L)
    .currency("MXN")
    .connectionOptions(TransactionCreateConnectionOptions.builder()
      .oxxoOxxo(ConnectionOptionsOxxoOxxo.builder()
        .approvalUrl("https://merchant.com/voucher")
        .build())
      .build())
    .paymentMethod(TransactionCreatePaymentMethod.of(RedirectPaymentMethodCreate.builder()
      .method(RedirectPaymentMethodCreateMethod.OXXO)
      .country("MX")
      .currency("MXN")
      .redirectUrl("https://example.com/callback")
      .build()))
    .build())
  .call();
$transactionCreate = new TransactionCreate(
  amount: 1299,
  currency: 'MXN',
  country: 'MX',
  connectionOptions: new TransactionCreateConnectionOptions(
    oxxoOxxo: new ConnectionOptionsOxxoOxxo(
      approvalUrl: 'https://merchant.com/voucher'
    )
  ),
  paymentMethod: new RedirectPaymentMethodCreate(
    method: 'oxxo',
    country: 'MX',
    currency: 'MXN',
    redirectUrl: 'https://example.com/callback'
  )
);
$response = $client->transactions->create($transactionCreate);
transaction: models.Transaction = client.transactions.create(
  amount=1299,
  currency="MXN",
  country="MX",
  connection_options={
    "oxxo-oxxo": {
      "approval_url": "https://merchant.com/voucher",
    },
  },
  payment_method={
    "method": "oxxo",
    "country": "MX",
    "currency": "MXN",
    "redirect_url": "https://example.com/callback",
  }
)
const transaction = await client.transactions.create({
  amount: 1299,
  currency: "MXN",
  country: "MX",
  connectionOptions: {
    "oxxo-oxxo": {
      approvalUrl: "https://merchant.com/voucher",
    },
  },
  paymentMethod: {
    method: "oxxo",
    country: "MX",
    currency: "MXN",
    redirectUrl: "https://example.com/callback"
  }
})

Required fields

OXXO requires the following buyer information with every transaction:
  • First name
  • Last name
  • Email address
  • Phone number

Custom expiration date

By default, OXXO payment references expire after 7 days. You can override this per transaction using the top-level approval_expires_at field on the transaction request. The value must be a future datetime in ISO 8601 format and must not exceed the connector’s maximum allowed expiration window.
var transaction = await client.Transactions.CreateAsync(
  transactionCreate: new TransactionCreate()
  {
    Amount = 1299,
    Currency = "MXN",
    ApprovalExpiresAt = DateTimeOffset.Parse("2026-04-10T23:59:59Z"),
    PaymentMethod =
      TransactionCreatePaymentMethod.CreateRedirectPaymentMethodCreate(
        new RedirectPaymentMethodCreate()
        {
          Method = "oxxo",
          Country = "MX",
          Currency = "MXN",
          RedirectUrl = "https://example.com/callback",
        }
      ),
  }
);
transactionCreate := components.TransactionCreate{
  Amount:            amount,
  Currency:          currency,
  Country:           &country,
  PaymentMethod:     &paymentMethod,
  ApprovalExpiresAt: gr4vy.Time(time.Date(2026, 4, 10, 23, 59, 59, 0, time.UTC)),
}

transaction, err := client.Transactions.Create(ctx, transactionCreate, nil, nil, nil)
CreateTransactionResponse transactionResponse = gr4vyClient.transactions().create()
  .transactionCreate(TransactionCreate.builder()
    .amount(1299L)
    .currency("MXN")
    .approvalExpiresAt(OffsetDateTime.parse("2026-04-10T23:59:59Z"))
    .paymentMethod(TransactionCreatePaymentMethod.of(RedirectPaymentMethodCreate.builder()
      .method(RedirectPaymentMethodCreateMethod.OXXO)
      .country("MX")
      .currency("MXN")
      .redirectUrl("https://example.com/callback")
      .build()))
    .build())
  .call();
$transactionCreate = new TransactionCreate(
  amount: 1299,
  currency: 'MXN',
  country: 'MX',
  approvalExpiresAt: new \DateTime('2026-04-10T23:59:59Z'),
  paymentMethod: new RedirectPaymentMethodCreate(
    method: 'oxxo',
    country: 'MX',
    currency: 'MXN',
    redirectUrl: 'https://example.com/callback'
  )
);
$response = $client->transactions->create($transactionCreate);
transaction: models.Transaction = client.transactions.create(
  amount=1299,
  currency="MXN",
  country="MX",
  approval_expires_at=datetime(2026, 4, 10, 23, 59, 59, tzinfo=timezone.utc),
  payment_method={
    "method": "oxxo",
    "country": "MX",
    "currency": "MXN",
    "redirect_url": "https://example.com/callback",
  }
)
const transaction = await client.transactions.create({
  amount: 1299,
  currency: "MXN",
  country: "MX",
  approvalExpiresAt: new Date("2026-04-10T23:59:59Z"),
  paymentMethod: {
    method: "oxxo",
    country: "MX",
    currency: "MXN",
    redirectUrl: "https://example.com/callback"
  }
})

Webhooks

OXXO requires webhook setup to receive payment confirmations. Configure the webhook public key in the connector credentials to verify incoming webhook signatures.