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

# Payments Guide

> Learn how to create and manage payments with the LuxCore API

# Payments Guide

This guide covers everything you need to know about creating and managing payments through the LuxCore API.

## Payment Types

LuxCore supports four payment types:

| Type            | Direction | Description                               |
| --------------- | --------- | ----------------------------------------- |
| `deposit`       | Inbound   | Customer pays to merchant (checkout)      |
| `withdrawal`    | Outbound  | Merchant pays to customer/vendor (payout) |
| `deposit_pp`    | Inbound   | Deposit with hosted payment page          |
| `withdrawal_pp` | Outbound  | Withdrawal with hosted payment page       |

## Payment Methods

| Method        | Code            | Deposit | Withdrawal | Processing Time    |
| ------------- | --------------- | ------- | ---------- | ------------------ |
| SPEI          | `spei`          | ✅       | ✅          | Up to 30 min       |
| OXXO          | `oxxo`          | ✅       | ❌          | Up to 30 min       |
| Card          | `card`          | ✅       | ❌          | Up to 30 min       |
| Bank Transfer | `bank_transfer` | ✅       | ✅          | Up to 30 min       |
| Cash          | `cash`          | ✅       | ❌          | Up to 30 min       |
| Crypto        | `crypto`        | ✅       | ✅          | Up to 30 min       |
| PayID         | `payid`         | ✅       | ✅          | Up to 10 min       |
| iPay          | `ipay`          | ✅       | ❌          | Instant (redirect) |

## Supported Payment Currencies

| Currency          | Code  | Country   | Common Payment Method    |
| ----------------- | ----- | --------- | ------------------------ |
| Argentine Peso    | `ARS` | Argentina | `bank_transfer`          |
| Australian Dollar | `AUD` | Australia | `bank_transfer`, `payid` |
| Mexican Peso      | `MXN` | Mexico    | `spei`                   |
| Sri Lankan Rupee  | `LKR` | Sri Lanka | `ipay`                   |
| Turkish Lira      | `TRY` | Turkey    | `bank_transfer`          |
| Uruguayan Peso    | `UYU` | Uruguay   | `bank_transfer`          |

<Warning>
  **All amounts are in minor units** (centavos, cents). For example, to charge 1,000.00 ARS, pass `amount: 100000`. Passing `1000` would create a payment for only 10.00 ARS.
</Warning>

## Creating a Deposit (Customer Payment)

When a customer needs to pay you:

<Tabs>
  <Tab title="ARS (Argentina)">
    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST "https://api.lux-core.io/api/v1/payments" \
        -H "X-API-Key: qp_test_sk_your_key" \
        -H "Content-Type: application/json" \
        -d '{
          "amount": 150000,
          "currency": "ARS",
          "method": "bank_transfer",
          "type": "deposit",
          "merchant_reference": "order_abc123",
          "description": "Order #ABC123",
          "customer": {
            "name": "Maria Garcia",
            "email": "maria@example.com",
            "phone": "+5491112345678"
          },
          "metadata": {
            "order_id": "abc123",
            "source": "web"
          }
        }'
      ```

      ```python Python theme={null}
      import requests

      payment = requests.post(
          "https://api.lux-core.io/api/v1/payments",
          headers={"X-API-Key": "qp_test_sk_your_key"},
          json={
              "amount": 150000,  # 1500.00 ARS (amount in centavos)
              "currency": "ARS",
              "method": "bank_transfer",
              "type": "deposit",
              "merchant_reference": "order_abc123",
              "description": "Order #ABC123",
              "customer": {
                  "name": "Maria Garcia",
                  "email": "maria@example.com",
                  "phone": "+5491112345678"
              },
              "metadata": {
                  "order_id": "abc123",
                  "source": "web"
              }
          }
      )
      ```
    </CodeGroup>

    ### Response (ARS)

    ```json theme={null}
    {
      "transaction_id": "pay_1234567890_abcdefgh",
      "status": "processing",
      "amount": 150000,
      "currency": "ARS",
      "method": "bank_transfer",
      "type": "deposit",
      "bank_details": {
        "amount": "150000",
        "purpose": "Payment pay_1234567890_abcdefgh",
        "currency": "ARS",
        "bank_name": "Banco Nacion",
        "swift_code": null,
        "account_holder": "LuxCore Platform S.A.",
        "account_number": "0110012345678901234567"
      },
      "created_at": "2025-01-21T10:30:00Z"
    }
    ```
  </Tab>

  <Tab title="MXN (Mexico)">
    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST "https://api.lux-core.io/api/v1/payments" \
        -H "X-API-Key: qp_test_sk_your_key" \
        -H "Content-Type: application/json" \
        -d '{
          "amount": 150000,
          "currency": "MXN",
          "method": "spei",
          "type": "deposit",
          "merchant_reference": "order_abc123",
          "description": "Order #ABC123",
          "customer": {
            "name": "Maria Garcia",
            "email": "maria@example.com",
            "phone": "+525551234567"
          },
          "metadata": {
            "order_id": "abc123",
            "source": "web"
          }
        }'
      ```

      ```python Python theme={null}
      import requests

      payment = requests.post(
          "https://api.lux-core.io/api/v1/payments",
          headers={"X-API-Key": "qp_test_sk_your_key"},
          json={
              "amount": 150000,  # $1,500.00 MXN
              "currency": "MXN",
              "method": "spei",
              "type": "deposit",
              "merchant_reference": "order_abc123",
              "description": "Order #ABC123",
              "customer": {
                  "name": "Maria Garcia",
                  "email": "maria@example.com",
                  "phone": "+525551234567"
              },
              "metadata": {
                  "order_id": "abc123",
                  "source": "web"
              }
          }
      )
      ```
    </CodeGroup>

    ### Response (MXN)

    ```json theme={null}
    {
      "transaction_id": "pay_1234567890_abcdefgh",
      "status": "processing",
      "amount": 150000,
      "currency": "MXN",
      "method": "spei",
      "type": "deposit",
      "bank_details": {
        "amount": "150000",
        "purpose": "Payment pay_1234567890_abcdefgh",
        "currency": "MXN",
        "bank_name": "STP",
        "swift_code": null,
        "account_holder": "LuxCore Platform S.A. de C.V.",
        "account_number": "646180157000000001"
      },
      "created_at": "2025-01-21T10:30:00Z"
    }
    ```
  </Tab>

  <Tab title="UYU (Uruguay)">
    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST "https://api.lux-core.io/api/v1/payments" \
        -H "X-API-Key: qp_test_sk_your_key" \
        -H "Content-Type: application/json" \
        -d '{
          "amount": 150000,
          "currency": "UYU",
          "method": "bank_transfer",
          "type": "deposit",
          "merchant_reference": "order_abc123",
          "description": "Order #ABC123",
          "customer": {
            "name": "Maria Garcia",
            "email": "maria@example.com",
            "phone": "+59891234567"
          },
          "metadata": {
            "order_id": "abc123",
            "source": "web"
          }
        }'
      ```

      ```python Python theme={null}
      import requests

      payment = requests.post(
          "https://api.lux-core.io/api/v1/payments",
          headers={"X-API-Key": "qp_test_sk_your_key"},
          json={
              "amount": 150000,  # $1,500.00 UYU
              "currency": "UYU",
              "method": "bank_transfer",
              "type": "deposit",
              "merchant_reference": "order_abc123",
              "description": "Order #ABC123",
              "customer": {
                  "name": "Maria Garcia",
                  "email": "maria@example.com",
                  "phone": "+59891234567"
              },
              "metadata": {
                  "order_id": "abc123",
                  "source": "web"
              }
          }
      )
      ```
    </CodeGroup>

    ### Response (UYU)

    ```json theme={null}
    {
      "transaction_id": "pay_1234567890_abcdefgh",
      "status": "processing",
      "amount": 150000,
      "currency": "UYU",
      "method": "bank_transfer",
      "type": "deposit",
      "bank_details": {
        "amount": "150000",
        "purpose": "Payment pay_1234567890_abcdefgh",
        "currency": "UYU",
        "bank_name": "BROU",
        "swift_code": null,
        "account_holder": "LuxCore Platform S.A.",
        "account_number": "001234567890"
      },
      "created_at": "2025-01-21T10:30:00Z"
    }
    ```
  </Tab>

  <Tab title="AUD (Australia)">
    <CodeGroup>
      ```bash cURL (Bank Transfer) theme={null}
      curl -X POST "https://api.lux-core.io/api/v1/payments" \
        -H "X-API-Key: qp_test_sk_your_key" \
        -H "Content-Type: application/json" \
        -d '{
          "amount": 150000,
          "currency": "AUD",
          "method": "bank_transfer",
          "type": "deposit",
          "merchant_reference": "order_abc123",
          "description": "Order #ABC123",
          "customer": {
            "name": "James Smith",
            "email": "james@example.com",
            "phone": "+61412345678"
          },
          "metadata": {
            "order_id": "abc123",
            "source": "web"
          }
        }'
      ```

      ```python Python (Bank Transfer) theme={null}
      import requests

      payment = requests.post(
          "https://api.lux-core.io/api/v1/payments",
          headers={"X-API-Key": "qp_test_sk_your_key"},
          json={
              "amount": 150000,  # $1,500.00 AUD (amount in cents)
              "currency": "AUD",
              "method": "bank_transfer",
              "type": "deposit",
              "merchant_reference": "order_abc123",
              "description": "Order #ABC123",
              "customer": {
                  "name": "James Smith",
                  "email": "james@example.com",
                  "phone": "+61412345678"
              },
              "metadata": {
                  "order_id": "abc123",
                  "source": "web"
              }
          }
      )
      ```
    </CodeGroup>

    ### Response (AUD - Bank Transfer)

    ```json theme={null}
    {
      "transaction_id": "pay_1234567890_abcdefgh",
      "status": "processing",
      "amount": 150000,
      "currency": "AUD",
      "method": "bank_transfer",
      "type": "deposit",
      "bank_details": {
        "amount": "150000",
        "purpose": "Payment pay_1234567890_abcdefgh",
        "currency": "AUD",
        "bank_name": "Commonwealth Bank",
        "swift_code": "CTBAAU2S",
        "account_holder": "LuxCore Platform Pty Ltd",
        "bsb": "062-000",
        "account_number": "12345678"
      },
      "created_at": "2026-02-18T10:30:00Z"
    }
    ```

    ***

    Alternatively, use **PayID** for a faster deposit experience:

    <CodeGroup>
      ```bash cURL (PayID) theme={null}
      curl -X POST "https://api.lux-core.io/api/v1/payments" \
        -H "X-API-Key: qp_test_sk_your_key" \
        -H "Content-Type: application/json" \
        -d '{
          "amount": 150000,
          "currency": "AUD",
          "method": "payid",
          "type": "deposit",
          "merchant_reference": "order_abc123",
          "description": "Order #ABC123",
          "customer": {
            "name": "James Smith",
            "email": "james@example.com",
            "phone": "+61412345678"
          },
          "metadata": {
            "order_id": "abc123",
            "source": "web"
          }
        }'
      ```

      ```python Python (PayID) theme={null}
      import requests

      payment = requests.post(
          "https://api.lux-core.io/api/v1/payments",
          headers={"X-API-Key": "qp_test_sk_your_key"},
          json={
              "amount": 150000,  # $1,500.00 AUD (amount in cents)
              "currency": "AUD",
              "method": "payid",
              "type": "deposit",
              "merchant_reference": "order_abc123",
              "description": "Order #ABC123",
              "customer": {
                  "name": "James Smith",
                  "email": "james@example.com",
                  "phone": "+61412345678"
              },
              "metadata": {
                  "order_id": "abc123",
                  "source": "web"
              }
          }
      )
      ```
    </CodeGroup>

    ### Response (AUD - PayID)

    ```json theme={null}
    {
      "transaction_id": "pay_1234567890_abcdefgh",
      "status": "processing",
      "amount": 150000,
      "currency": "AUD",
      "method": "payid",
      "type": "deposit",
      "payid_details": {
        "amount": "150000",
        "purpose": "Payment pay_1234567890_abcdefgh",
        "currency": "AUD",
        "payid": "pay-1234567890@lux-core.io",
        "payid_type": "email",
        "payid_name": "LuxCore Platform Pty Ltd",
        "reference": "LXC-ABC123"
      },
      "created_at": "2026-02-18T10:30:00Z"
    }
    ```

    <Info>
      **PayID** uses Australia's New Payments Platform (NPP) for near-instant settlement. The customer sends funds to the provided PayID identifier (email, phone, or ABN) through their banking app. PayID deposits typically settle within minutes.
    </Info>
  </Tab>

  <Tab title="TRY (Turkey)">
    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST "https://api.lux-core.io/api/v1/payments" \
        -H "X-API-Key: qp_test_sk_your_key" \
        -H "Content-Type: application/json" \
        -d '{
          "amount": 150000,
          "currency": "TRY",
          "method": "bank_transfer",
          "type": "deposit",
          "merchant_reference": "order_abc123",
          "description": "Order #ABC123",
          "customer": {
            "name": "Mehmet Yilmaz",
            "email": "mehmet@example.com",
            "phone": "+905551234567"
          },
          "metadata": {
            "order_id": "abc123",
            "source": "web"
          }
        }'
      ```

      ```python Python theme={null}
      import requests

      payment = requests.post(
          "https://api.lux-core.io/api/v1/payments",
          headers={"X-API-Key": "qp_test_sk_your_key"},
          json={
              "amount": 150000,  # ₺1,500.00 TRY (amount in kurus)
              "currency": "TRY",
              "method": "bank_transfer",
              "type": "deposit",
              "merchant_reference": "order_abc123",
              "description": "Order #ABC123",
              "customer": {
                  "name": "Mehmet Yilmaz",
                  "email": "mehmet@example.com",
                  "phone": "+905551234567"
              },
              "metadata": {
                  "order_id": "abc123",
                  "source": "web"
              }
          }
      )
      ```
    </CodeGroup>

    ### Response (TRY)

    ```json theme={null}
    {
      "transaction_id": "pay_1234567890_abcdefgh",
      "status": "processing",
      "amount": 150000,
      "currency": "TRY",
      "method": "bank_transfer",
      "type": "deposit",
      "bank_details": {
        "amount": "150000",
        "purpose": "Payment pay_1234567890_abcdefgh",
        "currency": "TRY",
        "bank_name": "Turkish Bank",
        "swift_code": null,
        "account_holder": "LuxCore Platform",
        "account_number": "TR000000000000000000000000"
      },
      "created_at": "2026-05-06T10:30:00Z"
    }
    ```

    <Info>
      TRY uses standard minor units: `100` equals ₺1.00. Available payment methods can depend on your merchant configuration; use `bank_transfer` unless your account manager enables another TRY rail.
    </Info>
  </Tab>

  <Tab title="LKR (Sri Lanka)">
    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST "https://api.lux-core.io/api/v1/payments" \
        -H "X-API-Key: qp_test_sk_your_key" \
        -H "Content-Type: application/json" \
        -d '{
          "amount": 150000,
          "currency": "LKR",
          "method": "ipay",
          "type": "deposit",
          "merchant_reference": "order_abc123",
          "description": "Order #ABC123",
          "customer": {
            "name": "Kamal Perera",
            "email": "kamal@example.com",
            "phone": "+94771234567"
          },
          "metadata": {
            "order_id": "abc123",
            "source": "web"
          }
        }'
      ```

      ```python Python theme={null}
      import requests

      payment = requests.post(
          "https://api.lux-core.io/api/v1/payments",
          headers={"X-API-Key": "qp_test_sk_your_key"},
          json={
              "amount": 150000,  # Rs. 1,500.00 LKR (amount in cents)
              "currency": "LKR",
              "method": "ipay",
              "type": "deposit",
              "merchant_reference": "order_abc123",
              "description": "Order #ABC123",
              "customer": {
                  "name": "Kamal Perera",
                  "email": "kamal@example.com",
                  "phone": "+94771234567"
              },
              "metadata": {
                  "order_id": "abc123",
                  "source": "web"
              }
          }
      )
      ```
    </CodeGroup>

    ### Response (LKR)

    ```json theme={null}
    {
      "transaction_id": "pay_1234567890_abcdefgh",
      "status": "processing",
      "amount": 150000,
      "currency": "LKR",
      "method": "ipay",
      "type": "deposit",
      "merchant_reference": "order_abc123",
      "created_at": "2025-11-22T10:30:00Z",
      "ipay_checkout": {
        "checkout_url": "https://checkout.ipay.lk/pay/abc123",
        "form_action": "https://sandbox.ipay.lk/listener",
        "form_method": "POST",
        "checkout_params": {
          "merchantId": "LUXCORE",
          "amount": "1500.00",
          "currency": "LKR",
          "referenceNo": "pay_1234567890_abcdefgh",
          "responseUrl": "https://api.lux-core.io/api/v1/providers/ipay/callback",
          "checkValue": "a1b2c3..."
        },
        "payment_schemes": ["VISA", "MC", "IPAY", "LQR"],
        "redirect_required": true
      }
    }
    ```

    ***

    Optionally, restrict the checkout to a specific payment scheme:

    ```bash theme={null}
    curl -X POST "https://api.lux-core.io/api/v1/payments" \
      -H "X-API-Key: qp_test_sk_your_key" \
      -H "Content-Type: application/json" \
      -d '{
        "amount": 150000,
        "currency": "LKR",
        "method": "ipay",
        "type": "deposit",
        "merchant_reference": "order_visa_only",
        "customer": {
          "name": "Kamal Perera",
          "email": "kamal@example.com"
        },
        "ipay": {
          "payment_method": "VISA"
        }
      }'
    ```

    <Info>
      **Available payment schemes for iPay:**

      * `VISA` — Visa cards
      * `MC` — Mastercard
      * `IPAY` — iPay App
      * `LQR` — LankaQR (scan-to-pay)

      Pass `ipay.payment_method` to restrict the checkout to a single scheme. If omitted, all available schemes are shown to the customer.
    </Info>

    <Warning>
      iPay deposits use a **redirect or form-based flow**. After creating the payment, submit a form to `ipay_checkout.form_action` with `ipay_checkout.checkout_params`, or redirect the customer to `ipay_checkout.checkout_url`. The customer completes payment on the hosted checkout page, and status updates are delivered via webhooks.
    </Warning>

    ### iPay Integration Details

    #### Checkout Flow

    1. Create a payment via `POST /payments` with `method: "ipay"` and `currency: "LKR"`
    2. The response includes an `ipay_checkout` object — submit a form to `ipay_checkout.form_action` with `ipay_checkout.checkout_params`, or redirect to `ipay_checkout.checkout_url`
    3. The customer completes payment on the iPay hosted checkout page (Visa, Mastercard, LankaQR, or iPay App)
    4. iPay sends a server-to-server callback to confirm payment status
    5. You receive a webhook (`payment.completed` or `payment.failed`) with the final status

    #### Response Fields

    | Field                             | Type      | Description                                                   |
    | --------------------------------- | --------- | ------------------------------------------------------------- |
    | `ipay_checkout`                   | object    | iPay checkout details for completing payment                  |
    | `ipay_checkout.checkout_url`      | string    | URL to redirect the customer for payment                      |
    | `ipay_checkout.form_action`       | string    | Form action URL for POST-based checkout                       |
    | `ipay_checkout.form_method`       | string    | HTTP method for form submission (`POST`)                      |
    | `ipay_checkout.checkout_params`   | object    | Parameters to include in the form submission                  |
    | `ipay_checkout.payment_schemes`   | string\[] | Available payment schemes (e.g., `VISA`, `MC`, `IPAY`, `LQR`) |
    | `ipay_checkout.redirect_required` | boolean   | Whether a redirect/form submission is required                |
    | `status`                          | string    | Initial status is `processing`                                |

    #### Limits

    | Parameter      | Value              |
    | -------------- | ------------------ |
    | Minimum amount | 100 (Rs. 1.00 LKR) |
    | Currency       | LKR only           |
    | Withdrawals    | Not supported      |

    #### iPay Callback Statuses

    iPay reports three transaction statuses via server-to-server callback:

    | iPay Status | Code | LuxCore Status | Description                                              |
    | ----------- | ---- | -------------- | -------------------------------------------------------- |
    | Accepted    | `A`  | `completed`    | Payment successful, funds transferred                    |
    | Pending     | `P`  | `processing`   | Funds deducted, transfer pending (end-of-day settlement) |
    | Declined    | `D`  | `failed`       | Payment declined by iPay or card issuer                  |

    <Info>
      **Pending (P) status:** In rare cases, iPay may report a "Pending" status, meaning the customer's funds have been deducted but the transfer to the merchant is scheduled for end-of-day batch settlement. The system monitors these payments and auto-cancels them if unresolved after 24 hours.
    </Info>
  </Tab>
</Tabs>

## Creating a Withdrawal (Payout)

To send money to a beneficiary:

<Info>
  **`customer` vs `payout`:** For withdrawals, both objects refer to the same person — the recipient of the funds.

  * **`customer`** — personal contact information (name, email, phone). Used for customer identification, matching, and communication.
  * **`payout`** — bank account details for executing the transfer (account number, bank code, reference).
</Info>

### Payout Fields

| Field                | Required | Description                                                                                                                               | Example                    |
| -------------------- | :------: | ----------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- |
| `recipient_name`     |  **Yes** | Full name of the beneficiary (must match bank account holder)                                                                             | `"Juan Perez Martinez"`    |
| `bank_account`       |  **Yes** | Bank account number. CBU/CVU (22 digits) for ARS, CLABE (18 digits) for MXN, account number for UYU, account number (6-10 digits) for AUD | `"0110012345678901234567"` |
| `bank_code`          |    No    | Bank code. Required for MXN/SPEI. For AUD, use BSB (6 digits, format `XXX-XXX`)                                                           | `"002"`                    |
| `account_type`       |    No    | Account type                                                                                                                              | `"checking"`               |
| `beneficiary_tax_id` |    No    | Beneficiary tax ID (RFC, RUC, CUIT, ABN)                                                                                                  | `"20-12345678-9"`          |
| `description`        |    No    | Purpose of the payout                                                                                                                     | `"Salary January 2025"`    |
| `reference`          |    No    | Merchant-provided tracking reference. If not provided, system generates one automatically                                                 | `"PAYOUT-JAN-001"`         |
| `payid`              |    No    | PayID identifier (email, phone, or ABN). Required when `method` is `payid` for AUD withdrawals                                            | `"james@example.com"`      |
| `payid_type`         |    No    | Type of PayID: `email`, `phone`, or `abn`. Required when `payid` is provided                                                              | `"email"`                  |

<Tabs>
  <Tab title="ARS (Argentina)">
    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST "https://api.lux-core.io/api/v1/payments" \
        -H "X-API-Key: qp_test_sk_your_key" \
        -H "Content-Type: application/json" \
        -d '{
          "amount": 250000,
          "currency": "ARS",
          "method": "bank_transfer",
          "type": "withdrawal",
          "merchant_reference": "payout_vendor_001",
          "description": "Payout January 2025",
          "customer": {
            "name": "Juan Perez Martinez",
            "email": "juan.perez@example.com",
            "phone": "+5491112345678"
          },
          "payout": {
            "recipient_name": "Juan Perez Martinez",
            "bank_account": "0110012345678901234567"
          }
        }'
      ```

      ```python Python theme={null}
      payout = requests.post(
          "https://api.lux-core.io/api/v1/payments",
          headers={"X-API-Key": "qp_test_sk_your_key"},
          json={
              "amount": 250000,
              "currency": "ARS",
              "method": "bank_transfer",
              "type": "withdrawal",
              "merchant_reference": "payout_vendor_001",
              "description": "Payout January 2025",
              "customer": {
                  "name": "Juan Perez Martinez",
                  "email": "juan.perez@example.com",
                  "phone": "+5491112345678"
              },
              "payout": {
                  "recipient_name": "Juan Perez Martinez",
                  "bank_account": "0110012345678901234567"
              }
          }
      )
      ```
    </CodeGroup>

    ### Response (ARS Withdrawal)

    ```json theme={null}
    {
      "transaction_id": "pay_1234567890_abcdefgh",
      "status": "pending",
      "amount": 250000,
      "currency": "ARS",
      "method": "bank_transfer",
      "type": "withdrawal",
      "merchant_reference": "payout_vendor_001",
      "payout": {
        "recipient_name": "Juan Perez Martinez",
        "bank_account": "0110012345678901234567",
        "status": "pending"
      },
      "created_at": "2025-01-21T10:30:00Z"
    }
    ```
  </Tab>

  <Tab title="MXN (Mexico)">
    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST "https://api.lux-core.io/api/v1/payments" \
        -H "X-API-Key: qp_test_sk_your_key" \
        -H "Content-Type: application/json" \
        -d '{
          "amount": 250000,
          "currency": "MXN",
          "method": "spei",
          "type": "withdrawal",
          "merchant_reference": "payout_vendor_001",
          "description": "Payout January 2025",
          "customer": {
            "name": "Juan Perez Martinez",
            "email": "juan.perez@example.com",
            "phone": "+525551234567"
          },
          "payout": {
            "recipient_name": "Juan Perez Martinez",
            "bank_account": "012345678901234567",
            "bank_code": "002",
            "reference": "PAYOUT-JAN-001"
          }
        }'
      ```

      ```python Python theme={null}
      payout = requests.post(
          "https://api.lux-core.io/api/v1/payments",
          headers={"X-API-Key": "qp_test_sk_your_key"},
          json={
              "amount": 250000,
              "currency": "MXN",
              "method": "spei",
              "type": "withdrawal",
              "merchant_reference": "payout_vendor_001",
              "description": "Payout January 2025",
              "customer": {
                  "name": "Juan Perez Martinez",
                  "email": "juan.perez@example.com",
                  "phone": "+525551234567"
              },
              "payout": {
                  "recipient_name": "Juan Perez Martinez",
                  "bank_account": "012345678901234567",
                  "bank_code": "002",
                  "reference": "PAYOUT-JAN-001"
              }
          }
      )
      ```
    </CodeGroup>

    ### Response (MXN Withdrawal)

    ```json theme={null}
    {
      "transaction_id": "pay_1234567890_abcdefgh",
      "status": "pending",
      "amount": 250000,
      "currency": "MXN",
      "method": "spei",
      "type": "withdrawal",
      "merchant_reference": "payout_vendor_001",
      "payout": {
        "recipient_name": "Juan Perez Martinez",
        "clabe": "012345678901234567",
        "bank_code": "002",
        "status": "pending"
      },
      "created_at": "2025-01-21T10:30:00Z"
    }
    ```

    <Note>
      For MXN/SPEI withdrawals, the response returns `clabe` instead of `bank_account` in the payout object. This matches the Mexican banking convention where the 18-digit account identifier is called CLABE.
    </Note>
  </Tab>

  <Tab title="UYU (Uruguay)">
    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST "https://api.lux-core.io/api/v1/payments" \
        -H "X-API-Key: qp_test_sk_your_key" \
        -H "Content-Type: application/json" \
        -d '{
          "amount": 250000,
          "currency": "UYU",
          "method": "bank_transfer",
          "type": "withdrawal",
          "merchant_reference": "payout_vendor_001",
          "description": "Payout January 2025",
          "customer": {
            "name": "Juan Perez Martinez",
            "email": "juan.perez@example.com",
            "phone": "+59891234567"
          },
          "payout": {
            "recipient_name": "Juan Perez Martinez",
            "bank_account": "001234567890"
          }
        }'
      ```

      ```python Python theme={null}
      payout = requests.post(
          "https://api.lux-core.io/api/v1/payments",
          headers={"X-API-Key": "qp_test_sk_your_key"},
          json={
              "amount": 250000,
              "currency": "UYU",
              "method": "bank_transfer",
              "type": "withdrawal",
              "merchant_reference": "payout_vendor_001",
              "description": "Payout January 2025",
              "customer": {
                  "name": "Juan Perez Martinez",
                  "email": "juan.perez@example.com",
                  "phone": "+59891234567"
              },
              "payout": {
                  "recipient_name": "Juan Perez Martinez",
                  "bank_account": "001234567890"
              }
          }
      )
      ```
    </CodeGroup>

    ### Response (UYU Withdrawal)

    ```json theme={null}
    {
      "transaction_id": "pay_1234567890_abcdefgh",
      "status": "pending",
      "amount": 250000,
      "currency": "UYU",
      "method": "bank_transfer",
      "type": "withdrawal",
      "merchant_reference": "payout_vendor_001",
      "payout": {
        "recipient_name": "Juan Perez Martinez",
        "bank_account": "001234567890",
        "status": "pending"
      },
      "created_at": "2025-01-21T10:30:00Z"
    }
    ```
  </Tab>

  <Tab title="AUD (Australia)">
    <CodeGroup>
      ```bash cURL (Bank Transfer) theme={null}
      curl -X POST "https://api.lux-core.io/api/v1/payments" \
        -H "X-API-Key: qp_test_sk_your_key" \
        -H "Content-Type: application/json" \
        -d '{
          "amount": 250000,
          "currency": "AUD",
          "method": "bank_transfer",
          "type": "withdrawal",
          "merchant_reference": "payout_vendor_001",
          "description": "Payout February 2026",
          "customer": {
            "name": "James Smith",
            "email": "james@example.com",
            "phone": "+61412345678"
          },
          "payout": {
            "recipient_name": "James Smith",
            "bank_account": "12345678",
            "bank_code": "062-000"
          }
        }'
      ```

      ```python Python (Bank Transfer) theme={null}
      payout = requests.post(
          "https://api.lux-core.io/api/v1/payments",
          headers={"X-API-Key": "qp_test_sk_your_key"},
          json={
              "amount": 250000,  # $2,500.00 AUD
              "currency": "AUD",
              "method": "bank_transfer",
              "type": "withdrawal",
              "merchant_reference": "payout_vendor_001",
              "description": "Payout February 2026",
              "customer": {
                  "name": "James Smith",
                  "email": "james@example.com",
                  "phone": "+61412345678"
              },
              "payout": {
                  "recipient_name": "James Smith",
                  "bank_account": "12345678",
                  "bank_code": "062-000"
              }
          }
      )
      ```
    </CodeGroup>

    ### Response (AUD Bank Transfer Withdrawal)

    ```json theme={null}
    {
      "transaction_id": "pay_1234567890_abcdefgh",
      "status": "pending",
      "amount": 250000,
      "currency": "AUD",
      "method": "bank_transfer",
      "type": "withdrawal",
      "merchant_reference": "payout_vendor_001",
      "payout": {
        "recipient_name": "James Smith",
        "bank_account": "12345678",
        "bsb": "062-000",
        "status": "pending"
      },
      "created_at": "2026-02-18T10:30:00Z"
    }
    ```

    ***

    Alternatively, use **PayID** for faster payouts:

    <CodeGroup>
      ```bash cURL (PayID) theme={null}
      curl -X POST "https://api.lux-core.io/api/v1/payments" \
        -H "X-API-Key: qp_test_sk_your_key" \
        -H "Content-Type: application/json" \
        -d '{
          "amount": 250000,
          "currency": "AUD",
          "method": "payid",
          "type": "withdrawal",
          "merchant_reference": "payout_vendor_001",
          "description": "Payout February 2026",
          "customer": {
            "name": "James Smith",
            "email": "james@example.com",
            "phone": "+61412345678"
          },
          "payout": {
            "recipient_name": "James Smith",
            "payid": "james@example.com",
            "payid_type": "email"
          }
        }'
      ```

      ```python Python (PayID) theme={null}
      payout = requests.post(
          "https://api.lux-core.io/api/v1/payments",
          headers={"X-API-Key": "qp_test_sk_your_key"},
          json={
              "amount": 250000,  # $2,500.00 AUD
              "currency": "AUD",
              "method": "payid",
              "type": "withdrawal",
              "merchant_reference": "payout_vendor_001",
              "description": "Payout February 2026",
              "customer": {
                  "name": "James Smith",
                  "email": "james@example.com",
                  "phone": "+61412345678"
              },
              "payout": {
                  "recipient_name": "James Smith",
                  "payid": "james@example.com",
                  "payid_type": "email"
              }
          }
      )
      ```
    </CodeGroup>

    ### Response (AUD PayID Withdrawal)

    ```json theme={null}
    {
      "transaction_id": "pay_1234567890_abcdefgh",
      "status": "pending",
      "amount": 250000,
      "currency": "AUD",
      "method": "payid",
      "type": "withdrawal",
      "merchant_reference": "payout_vendor_001",
      "payout": {
        "recipient_name": "James Smith",
        "payid": "james@example.com",
        "payid_type": "email",
        "status": "pending"
      },
      "created_at": "2026-02-18T10:30:00Z"
    }
    ```

    <Info>
      **PayID Withdrawal Types:**

      * `email` — recipient's email registered as PayID (e.g., `james@example.com`)
      * `phone` — recipient's phone number in E.164 format (e.g., `+61412345678`)
      * `abn` — Australian Business Number (e.g., `51824753556`)
    </Info>
  </Tab>
</Tabs>

<Warning>
  Withdrawals require sufficient balance in your merchant account. Use the Balance API to check available funds before initiating payouts.
</Warning>

## Per-Payment Webhook URL

You can optionally specify a `webhook_url` to receive events for a specific payment without pre-configuring a webhook endpoint:

```bash theme={null}
curl -X POST "https://api.lux-core.io/api/v1/payments" \
  -H "X-API-Key: qp_test_sk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 150000,
    "currency": "ARS",
    "method": "bank_transfer",
    "type": "deposit",
    "merchant_reference": "order_abc123",
    "customer": {
      "name": "Maria Garcia",
      "email": "maria@example.com"
    },
    "webhook_url": "https://your-server.com/webhooks/payments",
    "webhook_events": ["payment.completed", "payment.failed"]
  }'
```

| Field            | Type      | Required | Description                                                                                                          |
| ---------------- | --------- | :------: | -------------------------------------------------------------------------------------------------------------------- |
| `webhook_url`    | string    |    No    | HTTPS URL to receive webhook events for this payment (max 2048 characters)                                           |
| `webhook_events` | string\[] |    No    | Events to subscribe to. Defaults to `["payment.created", "payment.completed", "payment.failed", "payment.refunded"]` |

<Info>
  In-request webhooks are signed using your merchant's **default webhook secret**. See the [Webhooks Guide](/guides/webhooks#in-request-webhooks) for details on signature verification and secret management.
</Info>

## Traffic Type

Optionally tag payments with a traffic type for analytics and routing:

```bash theme={null}
curl -X POST "https://api.lux-core.io/api/v1/payments" \
  -H "X-API-Key: qp_test_sk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 100000,
    "currency": "ARS",
    "method": "bank_transfer",
    "type": "deposit",
    "merchant_reference": "order_123",
    "traffic_type": "primary",
    "customer": {
      "name": "Customer Name",
      "email": "customer@example.com"
    }
  }'
```

| Value       | Description                       |
| ----------- | --------------------------------- |
| `primary`   | Primary traffic (default routing) |
| `secondary` | Secondary/backup traffic          |
| `vip`       | VIP/priority traffic              |

<Note>
  `traffic_type` is optional. If not provided, the payment uses default routing. Traffic type is included in payment responses and CSV exports.
</Note>

## Hosted Payment Pages

For a simpler integration, use hosted payment pages (`deposit_pp` or `withdrawal_pp`):

```bash theme={null}
curl -X POST "https://api.lux-core.io/api/v1/payments" \
  -H "X-API-Key: qp_test_sk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 100000,
    "currency": "ARS",
    "method": "bank_transfer",
    "type": "deposit_pp",
    "merchant_reference": "checkout_123",
    "customer": {
      "name": "Customer Name",
      "email": "customer@example.com"
    }
  }'
```

Response includes a payment page URL:

```json theme={null}
{
  "transaction_id": "pay_xyz789",
  "status": "processing",
  "payment_page": {
    "url": "https://{payment-page-host}/pay/{token}?sig={signature}&exp={expires}"
  }
}
```

<Info>
  The payment page URL is dynamically generated and may vary based on the selected currency, payment method, and region. Always use the exact URL returned in the API response.
</Info>

Redirect your customer to this URL to complete the payment.

## Payment Statuses

Understanding payment statuses is crucial for proper integration. Each status represents a specific state in the payment lifecycle.

### Status Reference

| Status             | Description                                          | Terminal |    Webhooks Sent    |
| ------------------ | ---------------------------------------------------- | :------: | :-----------------: |
| `created`          | Payment created, not yet assigned to a provider      |     ❌    |          -          |
| `pending_approval` | Payment awaiting manual approval                     |     ❌    |          -          |
| `pending`          | Payment created, awaiting processing or approval     |     ❌    |          -          |
| `processing`       | Payment is being processed, awaiting customer action |     ❌    |          -          |
| `completed`        | Payment was successful, funds transferred            |     ✅    | `payment.completed` |
| `failed`           | Payment failed due to error or rejection             |     ✅    |   `payment.failed`  |
| `cancelled`        | Payment was cancelled by merchant or system          |     ✅    | `payment.cancelled` |
| `expired`          | Payment expired before completion                    |     ✅    |   `payment.failed`  |
| `refunded`         | Payment was fully refunded                           |     ✅    |  `payment.refunded` |
| `partial_refund`   | Payment was partially refunded                       |     ✅    |  `payment.refunded` |

<Info>
  **Terminal statuses** (`completed`, `failed`, `cancelled`, `expired`, `refunded`, `partial_refund`) are final states - the payment cannot transition to non-terminal status.
</Info>

### Initial Status by Payment Type

| Payment Type    | Initial Status | Description                             |
| --------------- | -------------- | --------------------------------------- |
| `deposit`       | `processing`   | Customer needs to complete the transfer |
| `withdrawal`    | `pending`      | Awaiting approval and processing        |
| `deposit_pp`    | `processing`   | Customer redirected to payment page     |
| `withdrawal_pp` | `pending`      | Awaiting approval                       |

### Status Descriptions

<AccordionGroup>
  <Accordion title="created">
    The payment has been created in the system but has not yet been assigned to a payment provider or requisite. This is a transient status that typically transitions quickly to `pending` or `processing`.

    **Next possible statuses:** `pending`, `processing`, `failed`
  </Accordion>

  <Accordion title="pending_approval">
    The payment requires manual approval before it can be processed. This may apply to high-value transactions or flagged payments that need review.

    **Next possible statuses:** `processing`, `cancelled`
  </Accordion>

  <Accordion title="pending">
    The payment has been created and is waiting to be processed. For withdrawals, this means the payout is queued and awaiting approval or processing by the payment provider.

    **Next possible statuses:** `processing`, `cancelled`, `expired`
  </Accordion>

  <Accordion title="processing">
    The payment is actively being processed. For deposits, this means the customer has been given payment instructions (bank details, payment page URL) and we are waiting for them to complete the transfer.

    **Next possible statuses:** `completed`, `failed`, `cancelled`, `expired`
  </Accordion>

  <Accordion title="completed">
    The payment was successful. For deposits, the funds have been received and credited to your merchant balance. For withdrawals, the funds have been sent to the beneficiary.

    **This is a terminal status.** You will receive a `payment.completed` webhook.
  </Accordion>

  <Accordion title="failed">
    The payment could not be completed. This can happen due to various reasons: bank rejection, invalid account details, insufficient funds (for withdrawals), or technical issues.

    **This is a terminal status.** You will receive a `payment.failed` webhook with an `error_code` and `error_message`.
  </Accordion>

  <Accordion title="cancelled">
    The payment was cancelled before completion. This can be initiated by the merchant via API, by an admin, or automatically by the system.

    **This is a terminal status.** You will receive a `payment.cancelled` webhook.
  </Accordion>

  <Accordion title="expired">
    The payment was not completed within the allowed time window. Deposits typically expire after 1-60 minutes (configurable per merchant).

    **This is a terminal status.** You will receive a `payment.failed` webhook with `error_code: TTL_EXPIRED`.
  </Accordion>

  <Accordion title="refunded">
    The payment was fully refunded after completion. The refunded amount has been deducted from your merchant balance.

    **This is a terminal status.** You will receive a `payment.refunded` webhook.
  </Accordion>

  <Accordion title="partial_refund">
    The payment was partially refunded. Part of the original amount has been returned to the customer.

    **This is a terminal status.** You will receive a `payment.refunded` webhook with the refunded amount.
  </Accordion>
</AccordionGroup>

### Initiating Refunds

<Info>
  Refunds are currently initiated through the support team. A programmatic Refunds API is planned for Q2 2026.
</Info>

To request a refund:

1. Create a support ticket with category `refund_request` via the [Tickets API](/guides/tickets) or the merchant dashboard
2. Include the `payment_id` of the payment to be refunded
3. The support team will process the refund and update the payment status
4. You will receive a `payment.refunded` webhook when the refund is complete

Refund amounts are deducted from your merchant balance (`available_amount` decreases).

### Handling Status Changes

<Warning>
  **Always use webhooks** to track payment status changes. Polling the API is not recommended as it adds latency and may hit rate limits.
</Warning>

```javascript theme={null}
// Example: Handling status in your webhook handler
switch (payment.status) {
  case 'completed':
    // Update order to paid, deliver goods/services
    await markOrderAsPaid(payment.merchant_reference);
    break;
  case 'failed':
  case 'expired':
    // Notify customer, allow retry
    await notifyPaymentFailed(payment.merchant_reference, payment.error_message);
    break;
  case 'cancelled':
    // Clean up pending order
    await cancelOrder(payment.merchant_reference);
    break;
  case 'refunded':
  case 'partial_refund':
    // Process refund in your system
    await processRefund(payment.merchant_reference, payment.refunded_amount);
    break;
}
```

## Retrieving Payment Status

```bash theme={null}
curl -X GET "https://api.lux-core.io/api/v1/payments/pay_1234567890_abcdefgh" \
  -H "X-API-Key: qp_test_sk_your_key"
```

## Listing Payments

```bash theme={null}
curl -X GET "https://api.lux-core.io/api/v1/payments?status=completed&limit=20" \
  -H "X-API-Key: qp_test_sk_your_key"
```

### Query Parameters

| Parameter         | Type     | Description                |
| ----------------- | -------- | -------------------------- |
| `status`          | string   | Filter by status           |
| `method`          | string   | Filter by payment method   |
| `created_at_from` | ISO 8601 | Start date filter          |
| `created_at_to`   | ISO 8601 | End date filter            |
| `limit`           | integer  | Results per page (max 100) |
| `offset`          | integer  | Pagination offset          |

## Customer Management

Payments are automatically linked to customers in your account. You can optionally pass an existing customer ID to link a payment to a specific customer.

### Customer Fields

| Field         | Type   | Required | Description                                                                                               |
| ------------- | ------ | :------: | --------------------------------------------------------------------------------------------------------- |
| `name`        | string |    No    | Customer full name (max 255 characters)                                                                   |
| `email`       | string |    No    | Customer email address (max 255 characters)                                                               |
| `phone`       | string |    No    | Customer phone number (max 50 characters)                                                                 |
| `external_id` | string |    No    | Your unique customer identifier from your system. Used to link payments to your internal customer records |

<Note>
  All `customer` fields are optional. However, providing at least `email` or `phone` is recommended for automatic customer matching and communication.
</Note>

<Info>
  **`external_id`** is your own customer reference (e.g., user ID from your database). It is stored on the customer record and is unique per merchant. Use it for reconciliation and analytics without relying on LuxCore internal IDs.
</Info>

### Automatic Customer Matching

When creating a payment, if you don't provide a `customer_id`, the system will:

1. Search for an existing customer by **email** (exact match, case-insensitive)
2. If not found by email, search by **phone** (normalized)
3. If no match found, create a new customer with the provided data

If `external_id` is provided and a customer is found by email or phone, the `external_id` will be assigned to the existing customer (if not already set).

### Using External ID

Pass `external_id` inside the `customer` object to link payments to your internal customer records:

```bash theme={null}
curl -X POST "https://api.lux-core.io/api/v1/payments" \
  -H "X-API-Key: qp_test_sk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 150000,
    "currency": "ARS",
    "method": "bank_transfer",
    "type": "deposit",
    "merchant_reference": "order_abc123",
    "customer": {
      "name": "Maria Garcia",
      "email": "maria@example.com",
      "external_id": "usr_98765"
    }
  }'
```

<Warning>
  `external_id` must be unique per merchant. If you attempt to create a new customer with an `external_id` that is already assigned to another customer within the same merchant account, the request will fail.
</Warning>

### Using Customer ID

If you have an existing customer, you can pass their ID directly:

```bash theme={null}
curl -X POST "https://api.lux-core.io/api/v1/payments" \
  -H "X-API-Key: qp_test_sk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 150000,
    "currency": "ARS",
    "method": "bank_transfer",
    "type": "deposit",
    "merchant_reference": "order_abc123",
    "customer_id": 12345,
    "customer": {
      "name": "Maria Garcia",
      "email": "maria@example.com"
    }
  }'
```

<Info>
  When `customer_id` is provided, the system validates that the customer exists and belongs to your merchant account. The `customer` object fields (name, email, phone, external\_id) are **not updated** in this case — only the link to the existing customer is used.
</Info>

### Customer in Response

Payment responses now include customer information:

```json theme={null}
{
  "transaction_id": "pay_1234567890_abcdefgh",
  "status": "processing",
  "customer_id": 12345,
  "customer": {
    "id": 12345,
    "name": "Maria Garcia",
    "email": "maria@example.com",
    "phone": "+5491112345678",
    "external_id": "usr_98765"
  }
}
```

## Cancelling a Payment

Cancel a pending payment:

```bash theme={null}
curl -X POST "https://api.lux-core.io/api/v1/payments/pay_1234567890_abcdefgh/cancel" \
  -H "X-API-Key: qp_test_sk_your_key"
```

<Note>
  Only payments in `pending` status can be cancelled.
</Note>

## Idempotency

Use unique `merchant_reference` values for idempotency. If you submit a payment with a reference that was already used, the API will return the existing payment instead of creating a duplicate.

## Best Practices

<CardGroup cols={2}>
  <Card title="Validate Amounts" icon="calculator">
    Always validate amounts before submission. Amounts are in minor units (centavos).
  </Card>

  <Card title="Handle Webhooks" icon="webhook">
    Don't rely on polling. Set up webhooks for real-time status updates.
  </Card>

  <Card title="Store References" icon="database">
    Save `transaction_id` and `merchant_reference` for reconciliation.
  </Card>

  <Card title="Check Balance" icon="wallet">
    For withdrawals, verify sufficient balance before initiating.
  </Card>
</CardGroup>
