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

# Crear cobro

Crea un nuevo pago en tu cuenta.

### Headers

<ParamField header="x-idempotency" type="string" required placeholder="Token único para garantizar la idempotencia de la petición">
  Token único para garantizar la idempotencia de la petición
</ParamField>

### Body

<ParamField body="amount" type="number" required>
  Monto a cobrar, en **unidades mayores de la moneda** (no en centavos). Enviar `1400000` con
  `currency: "COP"` cobra \$1.400.000 COP.

  <Note>
    No lo confundas con los campos de `partial_payment_config`, que sí van en centavos: los
    reconoces porque lo llevan en el nombre (`min_amount_in_cents`).
  </Note>
</ParamField>

<ParamField body="title" type="string" required>
  Breve mensaje que se mostrará al usuario al realizar el pago
</ParamField>

<ParamField body="currency" type="string">
  Código de moneda ISO (COP, USD) por defecto COP
</ParamField>

<ParamField body="phone" type="string">
  Número de teléfono del cliente a enviar la solicitud de pago via whatsapp.
</ParamField>

<ParamField body="email" type="string">
  Campo opcional si quieres enviar una solicitud de pago via email
</ParamField>

<ParamField body="reference" type="string">
  Referencia de pago para que el usuario pueda interactuar con el portal de recaudo.
</ParamField>

<ParamField body="tax" type="number">
  Monto en la misma moneda con valor de impuestos, el valor predeterminado será del 19%
</ParamField>

<ParamField body="external_id" type="string">
  ID externo para relacionar el pago con un registro ya existente en tu sistema.
</ParamField>

<ParamField body="description" type="string">
  Descripción del pago
</ParamField>

<ParamField body="document_url" type="string">
  URL de un documento que se mostrará al usuario para que pueda realizar el pago.
</ParamField>

<ParamField body="due_date" type="date">
  Fecha de vencimiento del cobro, en formato `YYYY-MM-DD HH:MM:SS`.

  **No bloquea el pago**: pasada esta fecha el cobro se sigue pudiendo pagar. Su
  función es alimentar las reglas de cobranza ancladas al vencimiento (los
  recordatorios de "por vencer", "vence hoy" y de mora salen de acá). Es la misma
  fecha que el `due_date` de una factura, que se copia al cobro que la cobra.
</ParamField>

<ParamField body="timely_payment_date" type="date">
  Fecha de pago oportuno, en formato `YYYY-MM-DD` (también acepta fecha y hora):
  el último día para
  pagar sin recargo ni suspensión del servicio.

  **Es informativa**: no bloquea el pago ni expira el cobro. Es distinta de
  `due_date` — un recibo puede tener las dos. Las reglas de cobranza pueden anclar
  recordatorios a esta fecha (disparadores "antes", "el día" y "después" del pago
  oportuno, configurables en el portal). Es la misma fecha que el
  `timely_payment_date` de una factura, que se copia al cobro que la cobra.
</ParamField>

<ParamField body="expiration_date" type="date">
  Fecha de expiración del cobro, en formato `YYYY-MM-DD HH:MM:SS`.

  **Sí bloquea el pago**: al cumplirse, el cobro pasa a estado `expired` y deja de
  poder pagarse. Si no la envías se aplica la expiración por defecto configurada
  para tu empresa; si tu empresa no tiene una configurada, el cobro no expira.
</ParamField>

<Note>
  Son tres fechas distintas y complementarias: `due_date` es **cuándo vence el
  documento** (blanda, ancla los recordatorios de vencimiento y mora),
  `timely_payment_date` es **hasta cuándo se puede pagar sin recargo** (blanda,
  informativa, ancla los recordatorios de pago oportuno) y `expiration_date` es
  **hasta cuándo se puede pagar** (dura, cierra el cobro). Puedes enviar una,
  varias o las tres.
</Note>

<ParamField body="scheduled_date" type="date">
  Fecha en la que el cobro será enviado al usuario. `YYYY-MM-DD`.
</ParamField>

<ParamField body="metadata" type="object">
  Metadatos adicionales del pago en formato JSON

  <Warning>
    La llave `template_id` está reservada. Si la envías dentro de `metadata` recibirás un error 422: úsala como campo de primer nivel.
  </Warning>
</ParamField>

<ParamField body="template_id" type="integer">
  Plantilla de WhatsApp con la que se enviará el cobro. Si no la envías, OnePay elige la plantilla según la configuración de tu canal.

  Obtén los valores válidos con [`GET /templates`](/client/templates/list): solo sirven los `id` que traen `selectable: true`, es decir, plantillas aprobadas de categoría `PAYMENT` que pertenecen a tu empresa o son genéricas compartidas contigo.

  <Warning>
    Si la plantilla no existe, no está aprobada, no es de cobro o no está disponible para tu empresa, la petición falla con un error 422 y el cobro **no** se crea.
  </Warning>

  <Note>
    La plantilla queda fijada en el cobro: la verás en `metadata.template_id` de la respuesta y se usará también en los reenvíos. Si el cobro entra al motor de cobranzas, los recordatorios por etapa usan la plantilla configurada en la regla correspondiente.
  </Note>
</ParamField>

<ParamField body="redirect_url" type="string" placeholder="https://onepay.la">
  URL de redirección
</ParamField>

<ParamField body="splits" type="array">
  Los pagos divididos permiten distribuir automáticamente un único pago entre múltiples destinatarios según reglas preestablecidas, optimizando la gestión de fondos sin necesidad de cálculos manuales o costos adicionales.

  <Expandable title="Campos de splits[]">
    <ParamField body="splits[].customer_id" type="string" required>
      ID del cliente beneficiario del split. [Ver clientes](/client/customers/create).
    </ParamField>

    <ParamField body="splits[].split_type" type="string" required>
      Tipo de distribución:

      * `percentage` — Porcentaje entero del monto total (`10` = 10%)
      * `fixed` — Monto fijo en unidades mayores de la moneda (no en centavos)

      <Warning>
        Si el total de splits supera el 100% del monto o excede el monto total, la operación será rechazada.
      </Warning>
    </ParamField>

    <ParamField body="splits[].split_value" type="integer" required>
      Valor del split según el tipo:

      * Si `split_type` es `percentage`: porcentaje entero (`5` = 5%, `100` = 100%)
      * Si `split_type` es `fixed`: monto en la misma unidad que `amount` (unidades mayores, no centavos)

      <Warning>
        Versiones anteriores de esta página describían el porcentaje "en centésimas" (`10000` = 100%).
        Era un error: la suma de los splits de tipo `percentage` no puede pasar de `100`, así que
        esos valores se rechazan con un 422.
      </Warning>
    </ParamField>

    <ParamField body="splits[].description" type="string">
      Descripción interna del split.
    </ParamField>

    <ParamField body="splits[].account_id" type="string">
      ID de la cuenta donde se recibirá el split. Si no se especifica, se usa la cuenta principal del cliente.

      Para dividir hacia otra empresa que usa OnePay, registra su saldo como una cuenta y usa ese
      `account_id`. [Ver la guía](/client/accounts/onepay-balance).
    </ParamField>

    <ParamField body="splits[].to_company_wallet" type="boolean" deprecated>
      Forma anterior de dividir hacia el saldo de otra empresa: `true` y el identificador del saldo
      ajeno en `account_id`, en cada cobro.

      <Warning>
        Obsoleto. Registra ese saldo como una cuenta del cliente y usa `customer_id` + `account_id`
        como en cualquier otro split. [Cómo migrar](/client/accounts/onepay-balance#migrar-desde-to-company-wallet).
        Ambas formas funcionan durante la transición.
      </Warning>
    </ParamField>

    <ParamField body="splits[].scheduled_at" type="string">
      Fecha programada para realizar el split (`YYYY-MM-DD HH:mm:ss`). Si es `null`, se ejecuta de inmediato.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="partial_payment_config" type="object">
  Configuración para pagos parciales. Permite que un cobro sea pagado en múltiples transacciones.

  <Note>
    Requiere que el feature **Pagos Parciales** esté habilitado en tu cuenta. Contacta a soporte para activarlo.
  </Note>

  <Expandable title="Propiedades">
    <ParamField body="min_amount_in_cents" type="integer">
      Monto mínimo por pago parcial en centavos. Mínimo: 100 (equivale a \$1).
    </ParamField>

    <ParamField body="max_amount_in_cents" type="integer">
      Monto máximo por pago parcial en centavos. Si no se envía, el máximo es el saldo restante.
    </ParamField>

    <ParamField body="max_payment_methods" type="integer">
      Número máximo de pagos parciales permitidos. Mínimo: 2, Máximo: 10. Por defecto: 3.
    </ParamField>

    <ParamField body="timeout_hours" type="integer">
      Horas antes de que expire la ventana de pago parcial después del primer abono. Mínimo: 1, Máximo: 720. Por defecto: 24.
    </ParamField>
  </Expandable>
</ParamField>

<Note>
  **Métodos de pago permitidos**

  El método de pago disponible depende de la configuración de tu cuenta. Comunícate con el equipo de soporte para habilitar métodos adicionales.

  | Método                    | Campo requerido | Descripción                                     |
  | ------------------------- | --------------- | ----------------------------------------------- |
  | Cuenta bancaria (ACH)     | `account_id`    | Débito directo desde cuenta bancaria registrada |
  | Tarjeta de crédito/débito | `card_id`       | Cargo a tarjeta tokenizada                      |

  Solo uno de los dos (`account_id` o `card_id`) debe estar presente en la petición.
</Note>

### Ejemplos de uso

<Tabs>
  <Tab title="curl">
    ```bash theme={null}
    curl https://api.onepay.la/v1/payments \
      -X POST \
      -H "Authorization: Bearer sk_test_xxx" \
      -H "Content-Type: application/json" \
      -H "x-idempotency: payment-123" \
      -d '{
        "amount": 1400000,
        "currency": "COP",
        "title": "Suscripción Premium",
        "reference": "INV-2045",
        "phone": "+573201112233",
        "email": "customer@example.com",
        "redirect_url": "https://app.onepay.la/thanks",
        "allows": {
          "cards": true,
          "accounts": true,
          "pse": true
        },
        "metadata": {
          "salesforce_id": "OP-554"
        }
      }'
    ```
  </Tab>

  <Tab title="JavaScript">
    ```ts theme={null}
    import fetch from 'node-fetch';

    const body = {
      amount: 1400000,
      currency: 'COP',
      title: 'Suscripción Premium',
      reference: 'INV-2045',
      phone: '+573201112233',
      email: 'customer@example.com',
      redirect_url: 'https://app.onepay.la/thanks',
      allows: {
        cards: true,
        accounts: true,
        pse: true
      },
      metadata: {
        salesforce_id: 'OP-554'
      }
    };

    await fetch('https://api.onepay.la/v1/payments', {
      method: 'POST',
      headers: {
        Authorization: 'Bearer sk_test_xxx',
        'Content-Type': 'application/json',
        'x-idempotency': 'payment-123'
      },
      body: JSON.stringify(body)
    });
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import requests

    payload = {
        "amount": 1400000,
        "currency": "COP",
        "title": "Suscripción Premium",
        "reference": "INV-2045",
        "phone": "+573201112233",
        "email": "customer@example.com",
        "redirect_url": "https://app.onepay.la/thanks",
        "allows": {
            "cards": True,
            "accounts": True,
            "pse": True
        },
        "metadata": {
            "salesforce_id": "OP-554"
        }
    }

    response = requests.post(
        "https://api.onepay.la/v1/payments",
        headers={
            "Authorization": "Bearer sk_test_xxx",
            "x-idempotency": "payment-123"
        },
        json=payload,
        timeout=15
    )
    response.raise_for_status()
    print(response.json())
    ```
  </Tab>
</Tabs>

### Response

<ResponseField name="id" type="string">
  Identificador único del pago
</ResponseField>

<ResponseField name="amount" type="number">
  Monto del pago en pesos
</ResponseField>

<ResponseField name="currency" type="string">
  Código de moneda ISO
</ResponseField>

<ResponseField name="status" type="string">
  Estado del pago:

  * `pending` - Pendiente
  * `processing` - Procesando
  * `approved` - Aprobado
  * `declined` - Rechazado
  * `cancelled` - Cancelado
  * `expired` - Expirado
  * `partially_paid` - Parcialmente pagado
  * `partial_expired` - Pago parcial expirado
</ResponseField>

<ResponseField name="customer_id" type="string">
  ID del cliente que realizó el pago
</ResponseField>

<ResponseField name="payment_method" type="string">
  Método de pago utilizado
</ResponseField>

<ResponseField name="due_date" type="string | null">
  Fecha de vencimiento del cobro (ISO 8601). No bloquea el pago.
</ResponseField>

<ResponseField name="timely_payment_date" type="string | null">
  Fecha de pago oportuno (ISO 8601): último día para pagar sin recargo ni
  suspensión. Informativa: no bloquea el pago ni expira el cobro.
</ResponseField>

<ResponseField name="description" type="string">
  Descripción del pago
</ResponseField>

<ResponseField name="metadata" type="object">
  Metadatos adicionales del pago
</ResponseField>

<ResponseField name="partial_payment" type="object">
  Información de pago parcial. Solo presente cuando `partial_payment_config` está configurado.

  <Expandable title="Propiedades">
    <ResponseField name="partial_payment.total_paid_in_cents" type="integer">
      Total pagado hasta el momento en centavos
    </ResponseField>

    <ResponseField name="partial_payment.total_paid_label" type="string">
      Total pagado formateado (ej: "\$50.000")
    </ResponseField>

    <ResponseField name="partial_payment.remaining_amount_in_cents" type="integer">
      Saldo restante por pagar en centavos
    </ResponseField>

    <ResponseField name="partial_payment.remaining_label" type="string">
      Saldo restante formateado
    </ResponseField>

    <ResponseField name="partial_payment.progress_percentage" type="number">
      Porcentaje de progreso del pago (0 a 100)
    </ResponseField>

    <ResponseField name="partial_payment.is_fully_paid" type="boolean">
      Indica si el pago fue completado totalmente
    </ResponseField>

    <ResponseField name="partial_payment.min_amount_in_cents" type="integer">
      Monto mínimo por pago parcial en centavos
    </ResponseField>

    <ResponseField name="partial_payment.max_amount_in_cents" type="integer">
      Monto máximo por pago parcial en centavos
    </ResponseField>

    <ResponseField name="partial_payment.max_payment_methods" type="integer">
      Número máximo de pagos parciales permitidos
    </ResponseField>

    <ResponseField name="partial_payment.timeout_hours" type="integer">
      Horas de expiración configuradas
    </ResponseField>

    <ResponseField name="partial_payment.partial_expires_at" type="string">
      Fecha de expiración del pago parcial (ISO 8601). Se establece después del primer abono.
    </ResponseField>

    <ResponseField name="partial_payment.charges" type="array">
      Lista de cargos pagados

      <Expandable title="Propiedades del cargo">
        <ResponseField name="charges[].id" type="string">
          ID del cargo
        </ResponseField>

        <ResponseField name="charges[].amount_in_cents" type="integer">
          Monto del cargo en centavos
        </ResponseField>

        <ResponseField name="charges[].amount_label" type="string">
          Monto formateado
        </ResponseField>

        <ResponseField name="charges[].payment_method_type" type="string">
          Tipo de método de pago (ej: "card", "account", "pse")
        </ResponseField>

        <ResponseField name="charges[].payment_method" type="string">
          Descripción del método de pago
        </ResponseField>

        <ResponseField name="charges[].paid_at" type="string">
          Fecha de pago (ISO 8601)
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="created_at" type="string">
  Fecha y hora de creación en formato ISO 8601
</ResponseField>

### Ejemplo de respuesta

<ResponseExample>
  ```json Cobro estándar theme={null}
  {
    "id": "9e5ccd4a-d2f0-49dd-87fc-a0da752bd166",
    "source": "Suscripción Premium",
    "currency": "COP",
    "amount": 1400000,
    "amount_label": "$ 1.400.000",
    "title": "Suscripción Premium",
    "description": null,
    "phone": "+573201112233",
    "expiration_at": "2025-03-20T22:36:24.000000Z",
    "due_date": null,
    "timely_payment_date": null,
    "document_link": null,
    "external_id": null,
    "allows": {
      "cards": true,
      "accounts": true,
      "card_extra": false,
      "realtime": false,
      "pse": true,
      "transfiya": true
    },
    "status": "pending",
    "is_test": false,
    "created_at": "2025-03-05T22:36:24.000000Z",
    "paid_at": null,
    "payment_link": "https://pagos.onepay.la/payment/9e5ccd4a-d2f0-49dd-87fc-a0da752bd166",
    "redirect_url": "https://app.onepay.la/thanks",
    "provider_id": null,
    "metadata": { "salesforce_id": "OP-554" },
    "customer": null,
    "method": null,
    "splits": [],
    "company": null,
    "commission": null
  }
  ```

  ```json Con pagos parciales theme={null}
  {
    "id": "9e5ccd4a-d2f0-49dd-87fc-a0da752bd166",
    "source": "Suscripción Premium",
    "currency": "COP",
    "amount": 1400000,
    "amount_label": "$ 1.400.000",
    "title": "Suscripción Premium",
    "description": null,
    "phone": "+573201112233",
    "expiration_at": "2025-03-20T22:36:24.000000Z",
    "due_date": null,
    "timely_payment_date": null,
    "document_link": null,
    "external_id": null,
    "allows": {
      "cards": true,
      "accounts": true,
      "card_extra": false,
      "realtime": false,
      "pse": true,
      "transfiya": true
    },
    "status": "pending",
    "is_test": false,
    "created_at": "2025-03-05T22:36:24.000000Z",
    "paid_at": null,
    "payment_link": "https://pagos.onepay.la/payment/9e5ccd4a-d2f0-49dd-87fc-a0da752bd166",
    "redirect_url": "https://app.onepay.la/thanks",
    "provider_id": null,
    "metadata": { "salesforce_id": "OP-554" },
    "customer": null,
    "method": null,
    "splits": [],
    "company": null,
    "commission": null,
    "partial_payment": {
      "total_paid_in_cents": 0,
      "total_paid_label": "$ 0",
      "remaining_amount_in_cents": 140000000,
      "remaining_label": "$ 1.400.000",
      "progress_percentage": 0,
      "is_fully_paid": false,
      "min_amount_in_cents": 20000000,
      "max_amount_in_cents": null,
      "max_payment_methods": 3,
      "timeout_hours": 24,
      "partial_expires_at": null,
      "charges": []
    }
  }
  ```
</ResponseExample>
