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

# Crear orden de pago

> Registra una deuda y pide en el mismo request el cargo a la cuenta bancaria que el usuario registró en el enrolamiento. No requiere que el usuario esté adherido a un producto. El cargo es asíncrono: la orden nace en PROCESSING; consulta el resultado con GET /v2/debts/orders. La idempotencia es por externalRequestId en el body: un reintento con la misma llave, el mismo externalClientId, el mismo amount y el mismo externalPaymentMethodId retoma la deuda si sigue PENDING; si la llave ya se usó con otros datos (incluido otro externalPaymentMethodId, o enviarlo en un intento y no en el otro) o ya tiene una orden, 409.



## OpenAPI

````yaml /api-reference/openapi.yaml post /v2/debts/orders
openapi: 3.0.0
info:
  title: TapiPay API
  version: 1.0.0
  description: >
    API pública de la plataforma de cobranzas TapiPay.  Ofrece un contrato
    limpio y desacoplado del modelo interno de la plataforma, permitiendo a los
    clientes crear y gestionar cobros (deudas puntuales,  suscripciones
    recurrentes, links de pago, productos y contactos)  sin conocer detalles
    internos de Company, Modalities o GenerationData.
  contact:
    name: TapiPay Team
    url: https://www.tapipay.com
  license:
    name: Proprietary
servers:
  - url: https://tapipay-facade.homo.tapila.cloud
    description: Homologación
security:
  - apiKeyAuth: []
    tapiAuth: []
paths:
  /v2/debts/orders:
    post:
      tags:
        - Payment orders
      summary: Crear orden de pago
      description: >-
        Registra una deuda y pide en el mismo request el cargo a la cuenta
        bancaria que el usuario registró en el enrolamiento. No requiere que el
        usuario esté adherido a un producto. El cargo es asíncrono: la orden
        nace en PROCESSING; consulta el resultado con GET /v2/debts/orders. La
        idempotencia es por externalRequestId en el body: un reintento con la
        misma llave, el mismo externalClientId, el mismo amount y el mismo
        externalPaymentMethodId retoma la deuda si sigue PENDING; si la llave ya
        se usó con otros datos (incluido otro externalPaymentMethodId, o
        enviarlo en un intento y no en el otro) o ya tiene una orden, 409.
      operationId: createDebtOrder
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DebtOrderCreateRequest'
      responses:
        '201':
          description: Deuda registrada y cargo pedido
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    required:
                      - debt
                      - order
                    properties:
                      debt:
                        $ref: '#/components/schemas/DebtOrderDebt'
                      order:
                        $ref: '#/components/schemas/DebtOrder'
                  requestId:
                    type: string
        '400':
          description: >-
            INVALID_REQUEST: campo fuera del contrato, campo obligatorio
            faltante o inválido, paymentMethodType distinto de BANK_ACCOUNT, o
            los datos de la deuda no cumplen una regla de negocio (no se creó
            nada).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: >-
            RESOLUTION_ERROR (con envelope de error) si el companyCode no
            pertenece a tu cliente. En el resto de la API este caso es 422. Los
            403 del API Gateway (sin envelope) también pueden aparecer.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: >-
            CONTACT_NOT_FOUND si el externalClientId no corresponde a un
            contacto.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: >-
            RESOURCE_CONFLICT si el externalRequestId ya se usó con otros datos
            (incluido el externalPaymentMethodId) o ya tiene una orden. Consulta
            la orden con GET /v2/debts/orders.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: >-
            COMPANY_WITHOUT_DEBT_ID_MODALITY si tu compañía no tiene habilitadas
            las órdenes de pago. PAYMENT_METHODS_NOT_ENABLED si no tiene
            habilitado el débito automático. NO_ACTIVE_PAYMENT_METHOD si no se
            envió externalPaymentMethodId y el usuario no tiene una cuenta
            predeterminada vigente. PAYMENT_METHOD_NOT_AVAILABLE si el
            externalPaymentMethodId no existe, no es del usuario, no está
            vigente o no es del tipo de paymentMethodType (no se creó nada).
            ORDER_NOT_CREATED si no se pudo crear el cargo: la deuda se canceló
            y no se cobró nada.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: >-
            INTERNAL_ERROR: resultado incierto, no se sabe si el cargo se pidió.
            Reintenta con el mismo externalRequestId, nunca con uno nuevo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    DebtOrderCreateRequest:
      type: object
      additionalProperties: false
      required:
        - externalRequestId
        - externalClientId
        - amount
        - paymentMethodType
      description: >-
        Registra una deuda y pide en el mismo request el cargo a la cuenta
        bancaria que el usuario registró. Solo acepta estos campos: cualquier
        otro devuelve 400 INVALID_REQUEST. La deuda no admite pagos parciales.
      properties:
        externalRequestId:
          type: string
          minLength: 1
          maxLength: 250
          description: >-
            Llave de idempotencia de la orden. El debtId resultante es
            debt_<externalRequestId>. Ante un 500, reintenta con el mismo valor.
        externalClientId:
          type: string
          minLength: 1
          description: >-
            Identificador de un contacto existente. Si no existe, 404
            CONTACT_NOT_FOUND.
        amount:
          type: number
          minimum: 0.01
          description: Monto en pesos, hasta 2 decimales.
        paymentMethodType:
          type: string
          enum:
            - BANK_ACCOUNT
          description: >-
            Medio con el que se cobra. Por ahora solo la cuenta bancaria
            registrada.
        externalPaymentMethodId:
          type: string
          minLength: 1
          nullable: true
          example: b7e4a0c2-9f13-4e6d-8a25-71c3d9e0b4f8
          description: >-
            Cuenta con la que se cobra, tal como la devuelve GET
            /payment-methods. Tiene que ser una cuenta vigente del usuario y del
            tipo de paymentMethodType; si no, 422 PAYMENT_METHOD_NOT_AVAILABLE.
            Si no se envía, se cobra con la cuenta predeterminada del usuario.
        dueDate:
          type: string
          format: date
          description: >-
            Vencimiento de la deuda (YYYY-MM-DD). Si no se envía, la fecha de
            hoy en America/Mexico_City más 7 días.
        description:
          type: string
          minLength: 1
          maxLength: 255
        additionalData:
          $ref: '#/components/schemas/AdditionalData'
        companyCode:
          type: string
          description: Solo si tu cliente tiene varias companies.
    DebtOrderDebt:
      type: object
      description: >-
        La deuda registrada por la orden. Se lee como cualquier deuda con GET
        /debts/{id}.
      required:
        - debtId
        - externalRequestId
        - status
        - amount
        - amountPaid
        - currency
        - dueDate
        - createdAt
        - allowOverduePayment
        - contact
      properties:
        debtId:
          type: string
          example: debt_CARGO-2026-00042
        externalRequestId:
          type: string
        status:
          $ref: '#/components/schemas/DebtStatus'
        amount:
          type: number
        amountPaid:
          type: number
        currency:
          type: string
          example: MXN
        dueDate:
          type: string
          format: date
        createdAt:
          type: string
          format: date-time
        allowOverduePayment:
          type: boolean
        contact:
          type: object
          required:
            - contactId
            - externalClientId
            - createdInline
          properties:
            contactId:
              type: string
              example: con_cmruu1lx2000002l4ctm7b0et
            externalClientId:
              type: string
            createdInline:
              type: boolean
              description: Siempre false. Este endpoint no crea contactos.
    DebtOrder:
      type: object
      required:
        - orderId
        - status
        - amount
        - currency
        - paymentMethod
        - estimatedProcessingDate
      properties:
        orderId:
          type: string
          example: 6f1c2b9e-4d3a-4b8e-9a71-2c5d8e0f1a23
        status:
          type: string
          enum:
            - PROCESSING
            - PAID
            - FAILED
            - CHARGED_BACK
          description: >-
            PROCESSING: el cargo se pidió y no se confirmó todavía. PAID: se
            cobró. FAILED: no se pudo cobrar. CHARGED_BACK: se cobró y después
            se revirtió. El cargo es asíncrono: consulta el estado con GET
            /v2/debts/orders.
        amount:
          type: number
        currency:
          type: string
          example: MXN
        paymentMethod:
          type: object
          required:
            - externalPaymentMethodId
            - paymentMethodType
          properties:
            externalPaymentMethodId:
              type: string
              nullable: true
              description: Referencia opaca a la cuenta con la que se cobra.
            paymentMethodType:
              type: string
              nullable: true
              enum:
                - BANK_ACCOUNT
        estimatedProcessingDate:
          type: string
          format: date
          nullable: true
          description: >-
            Fecha estimada del cargo (YYYY-MM-DD). Por ahora siempre viene en
            null.
    Error:
      type: object
      required:
        - error
        - requestId
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              enum:
                - INVALID_REQUEST
                - BAD_REQUEST
                - RESOURCE_NOT_FOUND
                - RESOURCE_CONFLICT
                - RESOLUTION_ERROR
                - BUSINESS_RULE_VIOLATION
                - RATE_LIMITED
                - INTERNAL_ERROR
                - PARTIAL_UPDATE
                - NO_ACTIVE_PAYMENT_METHOD
                - COMPANY_WITHOUT_PRODUCT_MODALITY
                - CONTACT_NOT_FOUND
                - COMPANY_WITHOUT_DEBT_ID_MODALITY
                - PAYMENT_METHODS_NOT_ENABLED
                - ORDER_NOT_CREATED
                - PAYMENT_METHOD_NOT_AVAILABLE
              description: >-
                Código de error estándar. BAD_REQUEST se usa cuando tu cliente
                tiene varias companies y no se envía `companyCode`.
                NO_ACTIVE_PAYMENT_METHOD y COMPANY_WITHOUT_PRODUCT_MODALITY
                aparecen en POST /adhesions (el primero también en POST
                /v2/debts/orders). CONTACT_NOT_FOUND,
                COMPANY_WITHOUT_DEBT_ID_MODALITY, PAYMENT_METHODS_NOT_ENABLED,
                ORDER_NOT_CREATED y PAYMENT_METHOD_NOT_AVAILABLE solo aparecen
                en POST /v2/debts/orders. PARTIAL_UPDATE solo aparece en el 207
                de PATCH /subscriptions/{id}: la suscripción se actualizó, pero
                alguna de sus deudas no. Los 401 y 403 los emite el API Gateway
                y no usan este envelope (ver GatewayError). Excepción: en
                /v2/debts/orders, RESOLUTION_ERROR responde 403 con este
                envelope.
            message:
              type: string
              description: >-
                Mensaje legible del error. Es informativo: no lo parsees, usa
                `code` y `details[].field`.
            details:
              type: array
              description: >-
                Array de detalles adicionales (validaciones por campo, etc.). Un
                JSON malformado devuelve `[{ "field": "body", "issue": "Invalid
                JSON syntax" }]`.
              items:
                type: object
                properties:
                  field:
                    type: string
                    description: Campo que falló la validación
                  issue:
                    type: string
                    description: Descripción del problema
                  index:
                    type: integer
                    description: >-
                      Solo en el modo lote de POST /v2/debts. Posición del item
                      en `debts`.
                  externalRequestId:
                    type: string
                    description: >-
                      Solo en el modo lote de POST /v2/debts. externalRequestId
                      del item.
        requestId:
          type: string
          pattern: ^req_[a-zA-Z0-9]+$
          description: ID único del request para trazabilidad
    AdditionalData:
      type: object
      additionalProperties: true
      description: >-
        Datos adicionales propios del cliente. Debe ser un objeto plano; un
        escalar (string, número o booleano) devuelve 400 INVALID_REQUEST. No
        puede usar claves reservadas, que TapiPay escribe internamente:
        `description`, `paymentMethods`, `productName`, `externalProductId`,
        `debtExpirationDate`, `overduePayment`, `allowPartialPayments`,
        `recurringDebt`. Si aparece alguna, la API responde 400 INVALID_REQUEST
        con `details[].field = additionalData`. Se persiste en la deuda (en
        ligas de pago, en la deuda asociada al link; en suscripciones, en las
        deudas generadas).
      example:
        source: crm
        folio: F-2026-0042
    DebtStatus:
      type: string
      enum:
        - PENDING
        - PARTIALLY_PAID
        - PAID
        - OVERDUE
        - CANCELLED
    GatewayError:
      type: object
      description: >-
        Respuesta de error emitida por el API Gateway, antes de llegar al
        servicio. No lleva el envelope `error` ni `requestId`. Casos: token
        faltante o inválido en `x-authorization-token` devuelve `401 {"message":
        "Unauthorized"}`; `x-api-key` faltante o inválida devuelve `403
        {"message": "Forbidden"}`; token válido sin permiso sobre el recurso
        devuelve `403 {"Message": "User is not authorized to access this
        resource with an explicit deny"}`. Ojo al tipar: en este último caso el
        campo viene con mayúscula (`Message`), no `message`.
      properties:
        message:
          type: string
          example: Unauthorized
        Message:
          type: string
          description: Solo en el 403 de explicit deny (con mayúscula).
          example: User is not authorized to access this resource with an explicit deny
  responses:
    Unauthorized:
      description: >-
        No autenticado. Lo emite el API Gateway cuando falta o es inválido el
        token en `x-authorization-token`. Body `{"message": "Unauthorized"}`,
        sin envelope `error` ni `requestId`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/GatewayError'
          example:
            message: Unauthorized
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >
        API key del API Gateway de Tapi. Requerida en todas las operaciones.
        Distinta por ambiente (desarrollo, homologación, producción).
    tapiAuth:
      type: apiKey
      in: header
      name: x-authorization-token
      description: >
        Token TAPI JWT. Requerido en todas las operaciones. Se envía sin prefijo
        "Bearer". Ej: x-authorization-token: eyJhbGci...

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.