> ## Documentation Index
> Fetch the complete documentation index at: https://docs.v2.topup.com.co/llms.txt
> Use this file to discover all available pages before exploring further.

# PayIn

> Country-specific information for PayIn transactions in Mexico.

## Overview

The PayIn API for Mexico enables customer deposit transactions through multiple payment methods including card payments, OXXO cash vouchers, and SPEI bank transfers. Transactions are processed in real-time with webhook notifications for status updates.

### Key Features

* **Multiple Payment Methods**: `CARD`, `CASH_BANK`, `CASH_STORE`, `CASH_ALL`, `SPEI`, `OXXO`
* **Currency**: Mexican Peso (`MXN`)
* **Real-time Processing**: Immediate transaction validation and processing
* **Webhook Notifications**: Asynchronous status updates via IPN
* **Secure Redirect Flow**: Customer completes payment on a secure hosted page

### Quick Reference

| Parameter         | Value                | Description                |
| ----------------- | -------------------- | -------------------------- |
| **Endpoint**      | `POST /api/v1/payin` | Initiate PayIn transaction |
| **Currency**      | `MXN`                | Mexican Peso               |
| **Country Code**  | `MX`                 | Mexico                     |
| **Auth Required** | Yes                  | Token-Top + Basic Auth     |

***

## Request Parameters

### Required Fields

| Field            | Type   | Description                                    | Example                                                                                    |
| ---------------- | ------ | ---------------------------------------------- | ------------------------------------------------------------------------------------------ |
| `reference`      | string | Unique transaction identifier from your system | `"TXN-MX-001"`                                                                             |
| `amount`         | float  | Transaction amount in MXN                      | `150.00` (= MX\$ 150.00)                                                                   |
| `currency`       | string | Three-letter currency code (ISO 4217)          | `"MXN"`                                                                                    |
| `country`        | string | Two-letter country code (ISO 3166-1 alpha-2)   | `"MX"`                                                                                     |
| `payment_method` | string | Payment method identifier                      | `"ALL_METHODS"`, `"CARD"`, `"SPEI"`, `"OXXO"`, `"CASH_BANK"`, `"CASH_STORE"`, `"CASH_ALL"` |
| `ipn_url`        | string | Webhook URL for transaction status updates     | `"https://your-domain.com/webhook"`                                                        |
| `redirect_url`   | string | URL to redirect customer after payment         | `"https://your-domain.com/payment/success"`                                                |
| `customer_data`  | object | Customer information object (see below)        | —                                                                                          |

### Customer Data Object

| Field              | Type   | Required                                                        | Description                                | Example                            |
| ------------------ | ------ | --------------------------------------------------------------- | ------------------------------------------ | ---------------------------------- |
| `legal_doc`        | string | ✅                                                               | Customer's legal document number           | `"CURP12345678901234"`             |
| `legal_doc_type`   | string | ✅                                                               | Document type: `CURP`, `RFC`, `INE`, `PPN` | `"INE"`                            |
| `phone_code`       | string | ✅                                                               | Country calling code                       | `"52"`                             |
| `phone_number`     | string | ✅                                                               | 10-digit phone number without country code | `"5512345678"`                     |
| `email`            | string | ✅                                                               | Customer email address                     | `"johndoe@email.com"`              |
| `full_name`        | string | ✅                                                               | Customer full name                         | `"John Doe"`                       |
| `customer_address` | string | ✅ Required when `payment_method` is `CASH_BANK` or `CASH_STORE` | Customer's full address for cash delivery  | `"Av. Insurgentes Sur 1602, CDMX"` |

### Optional Fields

| Field             | Type    | Description                        | Default          |
| ----------------- | ------- | ---------------------------------- | ---------------- |
| `description`     | string  | Transaction description            | —                |
| `expiration_time` | integer | Payment link expiration in minutes | `720` (12 hours) |

<Note>
  The `customer_address` field is **required** when using `CASH_BANK` or `CASH_STORE`.
</Note>

<Note>
  **`CASH_ALL`** displays a hosted form showing only the available cash options (`CASH_BANK`, `CASH_STORE`). The customer selects their preferred channel on that page.
</Note>

## Direct Integrations (Back to Back)

### SPEI Direct Activation

When the **Direct SPEI activation** is enabled for your merchant account in the TumiPay backoffice, you can create a PayIn transaction with `payment_method: "SPEI"` and return transfer instructions directly in the API response.

This direct mode is intended for merchants that implement their own user experience and need to display the beneficiary CLABE and expiration date without redirecting the customer to a hosted checkout page.

<Note>
  Direct SPEI mode must be enabled by TumiPay before using this flow in production.
</Note>

### Request Example (SPEI Direct)

```json theme={null}
{
    "reference": "TXN-MX-SPEI-001",
    "amount": 40.00,
    "currency": "MXN",
    "country": "MX",
    "payment_method": "SPEI",
    "description": "SPEI direct activation test",
    "redirect_url": "https://tumipay.co/",
    "ipn_url": "https://your-domain.com/webhook",
    "customer_data": {
        "legal_doc": "CURP12345678901234",
        "legal_doc_type": "INE",
        "phone_code": "52",
        "phone_number": "2223634886",
        "email": "customer@example.com",
        "full_name": "John Doe",
        "address": "Av. Insurgentes Sur 1602, CDMX"
    }
}
```

### Response Example (SPEI Direct)

```json theme={null}
{
    "code": "01",
    "status": "SUCCESS",
    "message": "Operacion exitosa",
    "data": {
        "ticket": "Ciolt3HaJdQFLHS",
        "date": "2026-06-01 13:09:49",
        "transaction": {
            "reference": "3pFBNpRHdXdqNcq2S1QxyQbhQZXVaq",
            "amount": 40.00,
            "currency": "MXN",
            "payment_method": "SPEI",
            "ipn_url": "https://your-domain.com/webhook",
            "description": "SPEI direct activation test",
            "clabe_number": "734180000090924227",
            "expiration_date": "2026-06-02T06:09:50"
        }
    }
}
```

***

## Response Structure

### Success Response

| Field     | Type   | Description                      |
| --------- | ------ | -------------------------------- |
| `code`    | string | Response code (`"01"` = success) |
| `status`  | string | Transaction status (`"SUCCESS"`) |
| `message` | string | Description of the response      |
| `data`    | object | Transaction data object          |

### Data Object

| Field         | Type   | Description                                 |
| ------------- | ------ | ------------------------------------------- |
| `ticket`      | string | Unique transaction identifier (TumiPay ID)  |
| `date`        | string | Transaction timestamp (YYYY-MM-DD HH:MM:SS) |
| `payment_url` | string | Secure payment URL for customer redirect    |
| `transaction` | object | Transaction details echo                    |

### SPEI Direct Response Fields

When Direct SPEI activation is enabled, the `transaction` object also includes:

| Field             | Type   | Description                                        |
| ----------------- | ------ | -------------------------------------------------- |
| `clabe_number`    | string | CLABE to receive the customer bank transfer        |
| `expiration_date` | string | Expiration timestamp for the transfer instructions |

<Note>
  For direct SPEI transactions, `payment_url` may be omitted and the integration should use `clabe_number` and `expiration_date` from `data.transaction`.
</Note>

***

## Examples

### Request Example

<CodeGroup dropdown>
  ```bash cURL theme={null}
  curl --request POST 'https://api-empresas.staging.topup.com.co/production/api/v1/payin' \
  --header 'Token-Top: your_auth_token' \
  --header 'Authorization: Basic your_auth_key' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "reference": "TXN-MX-001",
      "amount": 150.00,
      "currency": "MXN",
      "country": "MX",
      "payment_method": "ALL_METHODS",
      "description": "Test PayIn Mexico",
      "customer_data": {
          "legal_doc": "CURP12345678901234",
          "legal_doc_type": "INE",
          "phone_code": "52",
          "phone_number": "5512345678",
          "email": "johndoe@email.com",
          "full_name": "John Doe"
      },
      "expiration_time": 720,
      "ipn_url": "https://your-domain.com/webhook",
      "redirect_url": "https://your-domain.com/payment/success"
  }'
  ```

  ```bash cURL (CASH) theme={null}
  curl --request POST 'https://api-empresas.staging.topup.com.co/production/api/v1/payin' \
  --header 'Token-Top: your_auth_token' \
  --header 'Authorization: Basic your_auth_key' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "reference": "TXN-MX-002",
      "amount": 200.00,
      "currency": "MXN",
      "country": "MX",
      "payment_method": "CASH_BANK",
      "description": "Test Cash PayIn Mexico",
      "customer_data": {
          "legal_doc": "CURP12345678901234",
          "legal_doc_type": "INE",
          "phone_code": "52",
          "phone_number": "5512345678",
          "email": "johndoe@email.com",
          "full_name": "John Doe",
          "customer_address": "Av. Insurgentes Sur 1602, Col. Crédito Constructor, CDMX"
      },
      "expiration_time": 720,
      "ipn_url": "https://your-domain.com/webhook",
      "redirect_url": "https://your-domain.com/payment/success"
  }'
  ```

  ```typescript TypeScript theme={null}
  import axios from 'axios';

  const makePayinRequest = async () => {
    try {
      const response = await axios.post('https://api-empresas.staging.topup.com.co/production/api/v1/payin', {
        reference: 'TXN-MX-001',
        amount: 150.00,
        currency: 'MXN',
        country: 'MX',
        payment_method: 'ALL_METHODS',
        description: 'Test PayIn Mexico',
        customer_data: {
          legal_doc: 'CURP12345678901234',
          legal_doc_type: 'INE',
          phone_code: '52',
          phone_number: '5512345678',
          email: 'johndoe@email.com',
          full_name: 'John Doe'
        },
        expiration_time: 720,
        ipn_url: 'https://your-domain.com/webhook',
        redirect_url: 'https://your-domain.com/payment/success'
      }, {
        headers: {
          'Token-Top': 'your_auth_token',
          'Authorization': 'Basic your_auth_key',
          'Content-Type': 'application/json'
        }
      });
      console.log(response.data);
    } catch (error) {
      console.error(error);
    }
  };

  makePayinRequest();
  ```

  ```php PHP theme={null}
  <?php
  $curl = curl_init();

  curl_setopt_array($curl, array(
    CURLOPT_URL => 'https://api-empresas.staging.topup.com.co/production/api/v1/payin',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => '',
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 0,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_POSTFIELDS =>'{
      "reference": "TXN-MX-001",
      "amount": 150.00,
      "currency": "MXN",
      "country": "MX",
      "payment_method": "ALL_METHODS",
      "description": "Test PayIn Mexico",
      "customer_data": {
          "legal_doc": "CURP12345678901234",
          "legal_doc_type": "INE",
          "phone_code": "52",
          "phone_number": "5512345678",
          "email": "johndoe@email.com",
          "full_name": "John Doe"
      },
      "expiration_time": 720,
      "ipn_url": "https://your-domain.com/webhook",
      "redirect_url": "https://your-domain.com/payment/success"
  }',
    CURLOPT_HTTPHEADER => array(
      'Token-Top: your_auth_token',
      'Authorization: Basic your_auth_key',
      'Content-Type: application/json'
    ),
  ));

  $response = curl_exec($curl);

  curl_close($curl);
  echo $response;
  ```

  ```java Java theme={null}
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;
  import java.net.URI;
  import java.io.IOException;

  public class PayinRequest {
      public static void main(String[] args) throws IOException, InterruptedException {
          HttpClient client = HttpClient.newHttpClient();
          String json = "{ \"reference\": \"TXN-MX-001\", \"amount\": 150.00, \"currency\": \"MXN\", \"country\": \"MX\", \"payment_method\": \"ALL_METHODS\", \"description\": \"Test PayIn Mexico\", \"customer_data\": { \"legal_doc\": \"CURP12345678901234\", \"legal_doc_type\": \"INE\", \"phone_code\": \"52\", \"phone_number\": \"5512345678\", \"email\": \"johndoe@email.com\", \"full_name\": \"John Doe\" }, \"expiration_time\": 720, \"ipn_url\": \"https://your-domain.com/webhook\", \"redirect_url\": \"https://your-domain.com/payment/success\" }";

          HttpRequest request = HttpRequest.newBuilder()
                  .uri(URI.create("https://api-empresas.staging.topup.com.co/production/api/v1/payin"))
                  .header("Token-Top", "your_auth_token")
                  .header("Authorization", "Basic your_auth_key")
                  .header("Content-Type", "application/json")
                  .POST(HttpRequest.BodyPublishers.ofString(json))
                  .build();

          HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

          System.out.println(response.body());
      }
  }
  ```

  ```go Go theme={null}
  package main

  import (
      "fmt"
      "net/http"
      "io/ioutil"
      "strings"
  )

  func main() {
      url := "https://api-empresas.staging.topup.com.co/production/api/v1/payin"
      method := "POST"

      payload := strings.NewReader(`{
          "reference": "TXN-MX-001",
          "amount": 150.00,
          "currency": "MXN",
          "country": "MX",
          "payment_method": "ALL_METHODS",
          "description": "Test PayIn Mexico",
          "customer_data": {
              "legal_doc": "CURP12345678901234",
              "legal_doc_type": "INE",
              "phone_code": "52",
              "phone_number": "5512345678",
              "email": "johndoe@email.com",
              "full_name": "John Doe"
          },
          "expiration_time": 720,
          "ipn_url": "https://your-domain.com/webhook",
          "redirect_url": "https://your-domain.com/payment/success"
      }`)

      client := &http.Client{}
      req, err := http.NewRequest(method, url, payload)

      if err != nil {
          fmt.Println(err)
          return
      }
      req.Header.Add("Token-Top", "your_auth_token")
      req.Header.Add("Authorization", "Basic your_auth_key")
      req.Header.Add("Content-Type", "application/json")

      res, err := client.Do(req)
      if err != nil {
          fmt.Println(err)
          return
      }
      defer res.Body.Close()

      body, err := ioutil.ReadAll(res.Body)
      if err != nil {
          fmt.Println(err)
          return
      }
      fmt.Println(string(body))
  }
  ```

  ```rust Rust theme={null}
  use reqwest::Client;
  use serde_json::json;

  async fn make_payin_request() -> Result<(), reqwest::Error> {
      let client = Client::new();
      let response = client.post("https://api-empresas.staging.topup.com.co/production/api/v1/payin")
          .header("Token-Top", "your_auth_token")
          .header("Authorization", "Basic your_auth_key")
          .header("Content-Type", "application/json")
          .json(&json!({
              "reference": "TXN-MX-001",
              "amount": 150.00,
              "currency": "MXN",
              "country": "MX",
              "payment_method": "ALL_METHODS",
              "description": "Test PayIn Mexico",
              "customer_data": {
                  "legal_doc": "CURP12345678901234",
                  "legal_doc_type": "INE",
                  "phone_code": "52",
                  "phone_number": "5512345678",
                  "email": "johndoe@email.com",
                  "full_name": "John Doe"
              },
              "expiration_time": 720,
              "ipn_url": "https://your-domain.com/webhook",
              "redirect_url": "https://your-domain.com/payment/success"
          }))
          .send()
          .await?;

      let response_json: serde_json::Value = response.json().await?;
      println!("{:#?}", response_json);

      Ok(())
  }
  ```
</CodeGroup>

### Response Example

```json theme={null}
{
    "code": "01",
    "status": "SUCCESS",
    "message": "Operacion exitosa",
    "data": {
        "ticket": "9CQtDGwb2OLRrz3",
        "date": "2025-10-15 17:58:36",
        "payment_url": "https://link.staging.topup.com.co/payments/main?s=9CQtDGwb2OLRrz3",
        "transaction": {
            "reference": "TXN-MX-001",
            "amount": 150.00,
            "currency": "MXN",
            "payment_method": "ALL_METHODS",
            "redirect_url": "https://your-domain.com/payment/success",
            "ipn_url": "https://your-domain.com/webhook",
            "description": "Test PayIn Mexico"
        }
    }
}
```
