This guide shows you how to accept cash payments using SafetyPay, an alternative cash payment network that operates across Latin America. SafetyPay is ideal for regions without OXXO coverage or when you want to offer additional cash payment options to your customers.

When to Use SafetyPay

SafetyPay is ideal for:
  • Customers in regions without OXXO coverage.
  • Expanding cash payment options beyond convenience stores.
  • Markets where SafetyPay has established payment networks.
  • Customers who prefer alternative payment locations.

Step 1: Create a SafetyPay Payment Request

SafetyPay payments are straightforward - just specify the payment type and the API will generate payment instructions:
{
  "operation_type": "payment",
  "amount": 180.00,
  "currency": "MXN",
  "customer": {
    "name": "Patricia Morales Vega",
    "email": "patricia.morales@email.com"
  },
  "payment_method": {
    "type": "SAFETYPAY"
  },
  "client_reference": "order-789"
}

Step 2: Send the Payment Request

Create and send a POST request to the Process Transaction endpoint to initiate a SafetyPay payment. This request creates a payment voucher that your customer can use at authorized SafetyPay locations:
curl -X POST https://stage.tonder.io/api/v1/process/ \
  -H "Authorization: Token YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "operation_type": "payment",
    "amount": 180.00,
    "currency": "MXN",
    "customer": {
      "name": "Patricia Morales Vega",
      "email": "patricia.morales@email.com"
    },
    "payment_method": {
      "type": "SAFETYPAY"
    },
    "client_reference": "order-789"
  }'

Step 3: Handle the Response

After sending the payment request, you’ll receive a response containing the payment voucher details and instructions. SafetyPay payments start with a pending status and include comprehensive payment information for your customer:
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "operation_type": "payment",
  "status": "pending",
  "amount": 180.00,
  "currency": "MXN",
  "payment_instructions": {
    "reference_code": "SP180456789",
    "payment_locations": [
      "Tiendas de conveniencia autorizadas",
      "Farmacias participantes", 
      "Supermercados afiliados"
    ],
    "expiration_date": "2024-07-29T23:59:59Z",
    "instructions": [
      "Acude a un punto de pago SafetyPay autorizado",
      "Presenta el código de referencia",
      "Paga exactamente $180.00 MXN en efectivo"
    ]
  },
  "voucher_url": "https://api.safetypay.com/vouchers/abc123",
  "store_locator": "https://safetypay.com/locator?ref=SP180456789",
  "created_at": "2024-07-26T10:30:00Z"
}

Step 4: Provide Payment Instructions to Your Customer

Present the payment voucher clearly to help customers complete their SafetyPay payment successfully. Create a user-friendly page that displays all necessary information for the customer to pay at any SafetyPay location:
1

Show the reference code prominently

Display the reference_code that customers need to present at payment locations.
2

List payment locations

Show the types of locations where customers can pay using payment_locations.
3

Provide store locator

Include a link to the store_locator to help customers find nearby payment locations.
4

Set clear expectations

Explain the payment process and timeline using the instructions array.
5

Include expiration date

Clearly show when the payment voucher expires.

Customer Instructions Template

Create a comprehensive payment page that includes all the information customers need to complete their SafetyPay payment. This HTML template demonstrates how to structure and present the payment voucher information effectively:
<div class="safetypay-voucher">
  <h2>Completa tu pago con SafetyPay</h2>
  
  <div class="reference-code">
    <h3>Código de referencia: SP180456789</h3>
    <p>Presenta este código en el punto de pago</p>
  </div>
  
  <div class="amount">
    <h3>Monto a pagar: $180.00 MXN</h3>
  </div>
  
  <div class="locations">
    <h4>Dónde puedes pagar:</h4>
    <ul>
      <li>Tiendas de conveniencia autorizadas</li>
      <li>Farmacias participantes</li>
      <li>Supermercados afiliados</li>
    </ul>
    <a href="{STORE_LOCATOR_URL}" target="_blank">
      Encontrar puntos de pago cercanos
    </a>
  </div>
  
  <div class="instructions">
    <h4>Instrucciones:</h4>
    <ol>
      <li>Acude a un punto de pago SafetyPay autorizado</li>
      <li>Presenta el código de referencia</li>
      <li>Paga exactamente $180.00 MXN en efectivo</li>
    </ol>
  </div>
  
  <div class="expiration">
    <p><strong>Válido hasta:</strong> 29 de julio, 2024</p>
  </div>
  
  <a href="{VOUCHER_URL}" class="voucher-link">
    Ver comprobante completo
  </a>
</div>
This HTML template creates a complete payment voucher interface that:
  • Displays the reference code prominently for easy customer reference
  • Shows the exact amount to prevent payment errors
  • Lists all payment locations where customers can complete their payment
  • Provides a store locator link to help customers find nearby locations
  • Includes step-by-step instructions for the payment process
  • Shows the expiration date to create urgency and prevent expired payments
  • Offers a voucher link for customers who want to see the complete payment details

Step 5: Track Payment Status

SafetyPay payments follow this status flow:
  1. pending - Waiting for customer to pay at authorized location
  2. success - Cash payment received and confirmed by SafetyPay network
Webhooks provide real-time notifications when payment status changes. Set up webhooks to receive payment confirmations:
{
  "event": "payment.status_changed",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "success", 
    "amount": 180.00,
    "completed_at": "2024-07-27T15:45:00Z",
    "payment_location": "Farmacia San Pablo - Sucursal Centro"
  }
}
If you prefer not to use webhooks, you can check payment status periodically by polling the API:
curl -X GET https://stage.tonder.io/api/v1/transactions/550e8400-e29b-41d4-a716-446655440000/ \
  -H "Authorization: Token YOUR_API_KEY"

Step 6: Handle SafetyPay-Specific Scenarios

There are some specificities to consider when using SafetyPay payments:
SafetyPay partners with various types of businesses to provide convenient payment options for customers:
  • Regional chains and independent stores.
  • Major pharmacy chains.
  • Selected supermarket locations.
  • Some bank branches (varies by region).
The processing time for SafetyPay payments follows these rules:
  • Payment window is usually 3-7 days from voucher generation.
  • Confirmation time is 24-48 hours after customer pays at location.
  • Business hours vary by payment location (many 24/7 options available).
Regarding the amount limits, SafetyPay has the following restrictions:
  • Minimum amount is typically $10 MXN (varies by location).
  • Maximum amount is usually $5,000-10,000 MXN per transaction.
  • Daily limits may apply depending on payment location.

Common Scenarios and Solutions

Here you can find some common scenarios and solutions:
This is an example of how to provide store locator assistance:
// Provide store locator assistance
function helpFindPaymentLocation(referenceCode) {
  const locatorUrl = `https://safetypay.com/locator?ref=${referenceCode}`;
  const customerSupport = "1-800-SAFETYPAY";
  
  return {
    message: "Use our store locator to find nearby payment locations",
    locatorUrl: locatorUrl,
    supportPhone: customerSupport,
    alternatives: [
      "Try searching for 'SafetyPay' at nearby convenience stores",
      "Ask at pharmacy counters if they accept SafetyPay",
      "Contact customer support for location assistance"
    ]
  };
}
This is an example of how to handle expired vouchers:
// Handle expired vouchers
function handleExpiredVoucher(originalTransactionId) {
  return {
    message: "This payment voucher has expired",
    actions: [
      "Create a new payment request",
      "Contact customer support if payment was already made",
      "Consider alternative payment methods"
    ],
    newPaymentUrl: "/create-new-payment",
    supportContact: "support@yourstore.com"
  };
}

Best Practices for SafetyPay Integration

Follow these best practices to integrate SafetyPay payments:
  • Explain that SafetyPay is different from OXXO.
  • Always provide links to find payment locations.
  • Send instructions via email and SMS.
  • Keep customers informed about payment status.
  • Offer alternative payment methods.
  • Prioritize SafetyPay in regions where it’s strong.
  • Handle network timeouts and API errors.
  • Ensure vouchers display well on mobile devices.
  • Check SafetyPay availability in your target markets.
  • Some customers may be unfamiliar with SafetyPay.
  • Factor in 24-48 hour processing time for order fulfillment.
  • Train support team on SafetyPay-specific questions.

Integration Example

This complete JavaScript implementation demonstrates how to integrate SafetyPay payments into your application. The example includes payment creation, voucher display, and status checking functionality:
class SafetyPayHandler {
  async createPayment(orderData) {
    const paymentRequest = {
      operation_type: "payment",
      amount: orderData.total,
      currency: "MXN",
      customer: orderData.customer,
      payment_method: { type: "SAFETYPAY" },
      client_reference: orderData.orderId
    };
    
    try {
      const response = await this.apiClient.post('/process/', paymentRequest);
      return this.displayVoucher(response);
    } catch (error) {
      console.error('SafetyPay payment creation failed:', error);
      throw error;
    }
  }
  
  displayVoucher(response) {
    const instructions = response.payment_instructions;
    
    return {
      referenceCode: instructions.reference_code,
      amount: response.amount,
      locations: instructions.payment_locations,
      storeLocator: response.store_locator,
      voucherUrl: response.voucher_url,
      expirationDate: instructions.expiration_date,
      instructions: instructions.instructions
    };
  }
  
  async checkPaymentStatus(transactionId) {
    const response = await this.apiClient.get(`/transactions/${transactionId}/`);
    return response.status;
  }
}

Next Steps