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

# Payment Orders

> Track payment status and prevent duplicate charges

## Understanding Payment Orders

Every payment you process creates a payment order. Track the status, retrieve transaction details, and prevent duplicate charges automatically.

## Create a Payment Order

Create a payment order to process card payments, SPEI transfers, PayCash cash payments, CIE Cash Net deposits, or batch payments. Each payment type uses the same endpoint with different payment method configurations.

<Warning>
  **PCI Compliance Required for Direct Card Integration**

  If you handle raw card data (card number, CVV, expiry) through this API, your business must be PCI DSS compliant. This involves security audits, vulnerability scans, and strict compliance requirements.

  **Not PCI compliant?** Use our hosted payment page or JavaScript SDK instead. These solutions handle card data for you and keep your business out of PCI scope.

  Contact [support@cheqpay.mx](mailto:support@cheqpay.mx) for hosted payment options.
</Warning>

```http theme={null}
POST /v2/payment-orders
x-api-key: YOUR_API_KEY
x-merchant-id: YOUR_MERCHANT_ID
Content-Type: application/json
```

### Card Payment Example

```json theme={null}
{
  "externalId": "order-123",
  "customer": {
    "externalId": "customer-abc",
    "firstName": "María",
    "lastName": "González",
    "email": "maria@example.com",
    "phoneNumber": "+521555123456"
  },
  "billingAddress": {
    "address": "Av. Reforma 123",
    "city": "Mexico City",
    "state": "CDMX",
    "postalCode": "01000",
    "country": "MX"
  },
  "amount": 10000,
  "currency": "MXN",
  "description": "Order #12345",
  "paymentMethod": {
    "type": "card",
    "cardDetails": {
      "number": "4000000000002503",
      "expiryMonth": "12",
      "expiryYear": "25",
      "cvc": "123"
    }
  }
}
```

<Warning>
  `amount` unit is the smallest currency unit (e.g., cents). So for MXN, 100 MXN = 10000 cents
</Warning>

### Response

```json theme={null}
{
  "paymentOrder": {
    "id": "ord_abc123",
    "externalId": "order-123",
    "amount": 10000,
    "currency": "MXN",
    "status": "COMPLETED",
    "description": "Order #12345"
  },
  "customer": {
    "id": "cus_xyz789",
    "firstName": "María",
    "lastName": "González",
    "email": "maria@example.com"
  },
  "paymentMethod": {
    "id": "pm_def456",
    "type": "card",
    "card": {
      "brand": "visa",
      "last4": "1111",
      "expiryMonth": "12",
      "expiryYear": "25"
    }
  }
}
```

### Required Fields

| Field                | Type    | Required | Description                                              |
| -------------------- | ------- | -------- | -------------------------------------------------------- |
| `externalId`         | string  | Yes      | Your unique order ID                                     |
| `amount`             | integer | Yes      | Amount in cents (10000 = \$100.00)                       |
| `currency`           | string  | Yes      | ISO currency code (MXN, USD)                             |
| `customer.firstName` | string  | Yes      | Customer's first name                                    |
| `customer.lastName`  | string  | Yes      | Customer's last name                                     |
| `customer.email`     | string  | Yes      | Customer's email address                                 |
| `paymentMethod.type` | string  | Yes      | Payment type (`card`, `spei`, `paycash`, `cie_cash_net`) |

<CardGroup cols={2}>
  <Card title="Card Payments" icon="credit-card" href="/features/card-payments">
    Accept credit and debit cards
  </Card>

  <Card title="SPEI Transfers" icon="building-columns" href="/features/spei-transfers">
    Immediate bank-to-bank transfers in Mexico
  </Card>

  <Card title="PayCash Payments" icon="money-bill" href="/features/paycash-payments">
    Offline cash payments with reference
  </Card>

  <Card title="CIE Cash Net" icon="building-columns" href="/features/cie-cash-net-payments">
    BBVA cash and bank deposits
  </Card>

  <Card title="Batch Payments" icon="layer-group" href="/features/batch-payments">
    Process multiple payments
  </Card>
</CardGroup>

## Order Status

Payment orders move through different states as they process:

| Status                                      | Description                                                                                      | Action                                                      |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------ | ----------------------------------------------------------- |
| `PENDING`                                   | Payment is being processed                                                                       | Wait for completion                                         |
| `PROCESSING`                                | Payment in progress                                                                              | Wait for completion                                         |
| `REFERENCE_GENERATED`                       | Payment reference issued (SPEI CLABE, CIE or PayCash reference), awaiting the customer's deposit | Share the reference and wait for the deposit                |
| `AUTHORIZED`                                | Payment authorized; capture completes automatically                                              | Wait for completion, or refund to reverse the authorization |
| `PARTIALLY_AUTHORIZED`                      | Partial amount authorized                                                                        | Review and process partial amount                           |
| `ACTION_REQUIRED`                           | Additional action needed                                                                         | Check order details for next steps                          |
| `COMPLETED`                                 | Payment successful ✓                                                                             | Fulfill the order                                           |
| `PARTIALLY_PAID`                            | Partial payment received                                                                         | Track remaining balance                                     |
| `FAILED`                                    | Payment declined                                                                                 | Show error to customer                                      |
| `PAYER_AUTHENTICATION_DEVICE_DATA_REQUIRED` | 3DS device data collection needed                                                                | Show invisible data collection iframe                       |
| `PAYER_AUTHENTICATION_CHALLENGE_REQUIRED`   | 3DS challenge verification needed                                                                | Show authentication challenge iframe                        |
| `CANCELLATION_REQUESTED`                    | Cancellation in progress                                                                         | Wait for cancellation to complete                           |
| `CANCELLED`                                 | Payment cancelled                                                                                | Order cancelled                                             |
| `REFUND_PROCESSING`                         | Refund is being processed                                                                        | Wait for refund completion                                  |
| `PARTIALLY_REFUNDED`                        | Partial refund issued                                                                            | Update order total                                          |
| `REFUNDED`                                  | Fully refunded                                                                                   | Order fully refunded                                        |
| `EXPIRED`                                   | Payment reference expired before the customer paid (offline methods)                             | Create a new order if still needed                          |
| `LATE_RECONCILED`                           | Deposit received and reconciled after the order expired                                          | Review and fulfill or refund                                |

<Note>
  **Common Statuses:** Most card payments will only see `PENDING` → `PROCESSING` → `COMPLETED`. Offline methods (SPEI, CIE, PayCash) sit in `REFERENCE_GENERATED` while the customer completes the deposit. The other statuses handle specific scenarios like 3DS authentication, authorizations, cancellations, and refunds.
</Note>

### Status Flow

```mermaid theme={null}
graph LR
    A[PENDING] --> B[PROCESSING]
    A --> K[REFERENCE_GENERATED]
    K --> C
    B --> C[COMPLETED]
    B --> D[FAILED]
    B --> H[PAYER_AUTHENTICATION_DEVICE_DATA_REQUIRED]
    H --> I[Enrollment Check]
    I --> C
    I --> D
    I --> E[PAYER_AUTHENTICATION_CHALLENGE_REQUIRED]
    E --> J[Validate]
    J --> C
    J --> D
    C --> F[PARTIALLY_REFUNDED]
    F --> G[REFUNDED]
    C --> G
```

<Tip>
  Most successful payments go directly from `PENDING` → `PROCESSING` → `COMPLETED` in 2-5 seconds.
</Tip>

### 3D Secure Flow (Summary)

When 3DS is required, the flow adds three steps:

1. Collect device data (invisible iframe) when status is `PAYER_AUTHENTICATION_DEVICE_DATA_REQUIRED`.
2. Check enrollment: `POST /v2/payment-orders/:id/payer-authentication` → result may be `COMPLETED`, `FAILED`, or `PAYER_AUTHENTICATION_CHALLENGE_REQUIRED`.
3. If a challenge is required, display the challenge iframe using `stepUpUrl` and `jwt`, then validate with `POST /v2/payment-orders/:id/payer-authentication/validate`.

<Note>
  The authentication method (SMS, biometrics, app, etc.) is decided by the issuing bank, not by Cheqpay or the merchant, and can vary per transaction.
</Note>

<Card title="Full 3D Secure Guide" icon="shield" href="/features/3d-secure">
  See detailed implementation steps and examples
</Card>

## Track Your Orders

Every payment order has two IDs:

* **Cheqpay ID** - Our internal reference (e.g., `ord_abc123`)
* **External ID** - Your order or transaction ID (e.g., `order-12345`)

### Retrieve an Order

Use either ID to retrieve order details:

```http theme={null}
GET /v2/payment-orders/:id
x-api-key: YOUR_API_KEY
x-merchant-id: YOUR_MERCHANT_ID
```

#### Example Request

```bash theme={null}
curl -X GET https://api.sandbox.cheqpay.mx/pos/v2/payment-orders/ord_abc123 \
  -H "x-api-key: YOUR_API_KEY" \
  -H "x-merchant-id: YOUR_MERCHANT_ID"
```

#### Example Response

```json theme={null}
{
  "id": "ord_abc123",
  "externalId": "order-12345",
  "status": "COMPLETED",
  "amount": 10000,
  "currency": "MXN",
  "description": "Product purchase",
  "customer": {
    "id": "cus_xyz789",
    "firstName": "María",
    "lastName": "González",
    "email": "maria@example.com"
  },
  "paymentMethod": {
    "type": "card",
    "card": {
      "brand": "visa",
      "last4": "1111"
    }
  },
  "createdAt": "2025-10-30T10:00:00.000Z",
  "completedAt": "2025-10-30T10:00:05.000Z"
}
```

### What's Included

<AccordionGroup>
  <Accordion title="Payment Status" icon="circle-check">
    Current status and timestamps for all state changes
  </Accordion>

  <Accordion title="Customer Information" icon="user">
    Complete customer details including contact information
  </Accordion>

  <Accordion title="Payment Method Details" icon="credit-card">
    Masked card information or payment method used
  </Accordion>

  <Accordion title="Transaction Amounts" icon="dollar-sign">
    Original amount, refunded amounts, and net total
  </Accordion>

  <Accordion title="Complete Timeline" icon="clock">
    Created, processed, completed, and updated timestamps
  </Accordion>
</AccordionGroup>

## Prevent Duplicate Charges

Cheqpay automatically prevents duplicate payments using the `externalId` field. If you send the same request twice, we'll handle it intelligently:

```json theme={null}
{
  "externalId": "order-12345"
}
```

### Smart Duplicate Detection

<CardGroup cols={3}>
  <Card title="Payment Successful" icon="check">
    Returns existing payment (no duplicate charge)
  </Card>

  <Card title="Payment Pending" icon="clock">
    Returns pending payment (no new request)
  </Card>

  <Card title="Payment Failed" icon="xmark">
    Creates new payment (allows retry)
  </Card>
</CardGroup>

### How It Works

<Steps>
  <Step title="First Request">
    You create a payment with `externalId: "order-12345"` and it succeeds.
  </Step>

  <Step title="Duplicate Request">
    Network issue causes the request to be sent again with the same `externalId`.
  </Step>

  <Step title="Protected">
    Cheqpay recognizes the duplicate and returns the existing successful payment. No duplicate charge.
  </Step>
</Steps>

<Warning>
  Always use your order ID or transaction ID as the `externalId`. This protects your customers from being charged twice due to network issues or user errors.
</Warning>

### Best Practice

```javascript theme={null}
// ✅ Good - Use your order ID
const payment = await createPayment({
  externalId: `order-${orderId}`,
  amount: 10000,
  // ...
});

// ❌ Bad - Random or missing ID
const payment = await createPayment({
  externalId: Math.random().toString(),
  amount: 10000,
  // ...
});
```

## List Payment Orders

Retrieve a list of payment orders for reporting and reconciliation:

```http theme={null}
GET /v2/payment-orders?limit=20&offset=0
x-api-key: YOUR_API_KEY
x-merchant-id: YOUR_MERCHANT_ID
```

### Query Parameters

| Parameter    | Type    | Description                               |
| ------------ | ------- | ----------------------------------------- |
| `limit`      | integer | Number of results (default: 20, max: 100) |
| `offset`     | integer | Pagination offset (default: 0)            |
| `status`     | string  | Filter by status                          |
| `customerId` | string  | Filter by customer ID                     |
| `startDate`  | date    | Filter from date (ISO 8601)               |
| `endDate`    | date    | Filter to date (ISO 8601)                 |

## Monitoring Payment Status

You can check payment order status at any time using the GET endpoint to retrieve the latest information.

## Next Steps

<CardGroup cols={2}>
  <Card title="Process Payments" icon="credit-card" href="/features/card-payments">
    Learn how to create payment orders
  </Card>

  <Card title="Handle Refunds" icon="rotate-left" href="/features/refunds">
    Issue full or partial refunds
  </Card>

  <Card title="Manage Customers" icon="users" href="/features/customers">
    Track customer payment history
  </Card>

  <Card title="Error Handling" icon="triangle-exclamation" href="/guides/error-handling">
    Handle failed payments gracefully
  </Card>
</CardGroup>
