CredonixDocs
Referencia de la APIÓrdenes de cobro

Crear

Crea una orden de cobro y, opcionalmente, timbra su CFDI en la misma solicitud.

Descripción general

Este endpoint crea una orden de cobro con sus conceptos. Si envías el objeto cfdi, la API también timbra el CFDI en la misma solicitud, igual que en la aplicación. Una solicitud exitosa devuelve 201 con la orden de cobro creada y la llave cfdi, que trae el CFDI timbrado o null si no se timbró.

Al crearla:

  • status se calcula con las fechas: overdue si la fecha de vencimiento ya pasó, issued si la fecha de emisión ya llegó y created si todavía no llega.
  • remaining_amount (saldo pendiente) es igual a total_amount.
  • Los datos fiscales del cliente (nombre, razón social, RFC, régimen fiscal y código postal) se copian a la orden de cobro.
  • sat_status queda en emitted si se timbró un CFDI real y en not_required en cualquier otro caso, incluido el modo de prueba.

Con cfdi, el timbrado ocurre antes de guardar la orden de cobro. Si el SAT o el PAC rechazan el CFDI, la orden de cobro no se crea. Para timbrar después de crearla, usa Emitir CFDI.

Acepta el header Idempotency-Key (ver Idempotencia). Requiere el permiso Crear en Órdenes de cobro.

Endpoint

POSThttps://app.credonix.mx/api/v1/invoices

Orden de cobro sin CFDI


Sin cfdi, la API solo crea la orden de cobro y la respuesta trae "cfdi": null. La tasa del impuesto es una fracción ("0.16" = 16 %). Si omites base, se usa el subtotal neto del concepto.

{
  "customer_id": "cmu2193s9004kv1dqthqupd39",
  "legal_entity_id": "cmpydghmk0004v1oyioviuwjs",
  "concept": "Consultoría septiembre 2026",
  "issue_date": "2026-09-14",
  "due_date": null,
  "currency": "MXN",
  "items": [
    {
      "product_name": "Consultoría administrativa",
      "description": "Servicio mensual de consultoría",
      "quantity": 1,
      "unit_price": "1000",
      "product_code": "84111506",
      "unit_code": "E48",
      "taxes": [
        { "type": "iva", "category": "transferred", "rate": "0.16" }
      ]
    }
  ]
}

Varios impuestos por concepto


Cada concepto puede llevar varios impuestos. total_tax es la suma de los trasladados menos la de los retenidos, por eso puede ser negativo: aquí se retienen ISR al 10 % y IEPS al 8 % sobre 100, y el total queda en 82.00.

"taxes": [
  { "type": "iva", "category": "exempt", "rate": "0" },
  { "type": "isr", "category": "withheld", "rate": "0.10" },
  { "type": "ieps", "category": "withheld", "rate": "0.08" }
]

Orden de cobro timbrada en la misma solicitud


Agrega cfdi para timbrar el CFDI al crear la orden de cobro. La respuesta trae el CFDI en cfdi, con la misma forma que en Listar CFDI.

El ejemplo usa "test": true, así que el CFDI es de prueba, sin validez fiscal, y sat_status sigue en not_required. Sin test (o con false), el CFDI es real y la orden de cobro queda con sat_status: "emitted".

Antes de timbrar, la API verifica que la razón social esté configurada para timbrar, que el cliente tenga razón social, RFC, régimen fiscal y código postal, y que cada concepto tenga nombre o descripción, product_code y unit_code.

"cfdi": {
  "payment_form": "99",
  "payment_method": "PPD",
  "cfdi_use": "G03",
  "issue_date": "2026-09-14",
  "test": true
}

Reglas de los campos

CampoTipoRequeridoNotas
customer_idstringCliente de tu organización.
legal_entity_idstringRazón social emisora de tu organización. Obligatorio aunque no envíes cfdi.
conceptstringNo vacío.
descriptionstring | nullNoSi se omite, se guarda como "". Se envía al CFDI como condiciones de pago.
issue_datestringFecha de emisión, YYYY-MM-DD.
due_datestring | nullNoFecha de vencimiento, YYYY-MM-DD. No puede ser anterior a issue_date.
currencyMXN | USD
notesstring | nullNoNotas internas.
itemsarrayAl menos un concepto. Ver items[].
cfdiobject | nullNoSi se envía, se timbra el CFDI en la misma solicitud. Ver cfdi.

items[]

CampoTipoRequeridoNotas
product_idstring | nullNoProducto de tu organización.
product_namestring | nullNoSe requiere product_name o description.
descriptionstring | nullNo
quantityintegerNúmero JSON entero mayor que 0.
unit_pricestring | numberDecimal ≥ 0, por ejemplo "1234.50".
discountstring | number | nullNoDecimal ≥ 0. Con percentage es un porcentaje (10 = 10 %); con fixed, un monto.
discount_typepercentage | fixed | nullCon descuentoObligatorio si discount es distinto de 0.
product_codestring | nullPara timbrarClave de producto o servicio del SAT.
unit_codestring | nullPara timbrarClave de unidad del SAT.
taxesarrayNoPor defecto []. Ver items[].taxes[].

El total de cada concepto (subtotal − descuento + trasladados − retenidos) debe ser mayor o igual a 0.

items[].taxes[]

CampoTipoRequeridoNotas
typestringiva, isr o ieps, en minúsculas. Cualquier otro valor es un impuesto local de hasta 10 caracteres.
categorytransferred | withheld | exemptiva: trasladado, retenido o exento. isr: solo retenido. ieps: trasladado o retenido. Impuestos locales: trasladado o retenido.
ratestring | numberFracción ≥ 0: "0.16" es 16 %.
basestring | number | nullNoSi se omite o es 0, se usa el subtotal neto del concepto (subtotal − descuento).

cfdi

CampoTipoRequeridoNotas
payment_methodPUE | PPDMétodo de pago.
payment_formstringClave de forma de pago (ver catálogos). Con PPD debe ser 99; con PUE no puede ser 99.
cfdi_usestringNoUso del CFDI. Por defecto G03.
issue_datestringFecha de timbrado, YYYY-MM-DD. No puede ser futura ni de más de 2 días en el pasado.
exchange_ratestring | number | nullSi currency es USDTipo de cambio, mayor que 0. En órdenes de cobro en MXN se ignora.
testbooleanNoPor defecto false. true timbra un CFDI de prueba.

Catálogos del SAT

CampoValores
payment_form01 Efectivo, 02 Cheque, 03 Transferencia electrónica, 04 Tarjeta de crédito, 05 Monedero electrónico, 06 Dinero electrónico, 08 Vales de despensa, 12 Dación en pago, 13 Pago por subrogación, 14 Pago por consignación, 15 Condonación, 17 Compensación, 23 Novación, 24 Confusión, 25 Remisión de deuda, 26 Prescripción o caducidad, 27 A satisfacción del acreedor, 28 Tarjeta de débito, 29 Tarjeta de servicios, 30 Aplicación de anticipos, 31 Intermediario pagos, 99 Por definir, CX01 Depósito en ventanilla, CX02 Moneypool.
cfdi_useG01, G02, G03, I01I08, D01D10, CP01, CN01, S01.
payment_methodPUE, PPD.

Errores

StatusCódigoCausa
400VALIDATION_ERRORFalla de validación del cuerpo. errors[] trae un elemento por campo, con field en notación de puntos (items.0.taxes.0.category). Si faltan datos para timbrar, trae field: "cfdi" con código not_ready.
400CUSTOMER_NOT_FOUNDcustomer_id no existe en tu organización.
400LEGAL_ENTITY_NOT_FOUNDlegal_entity_id no existe en tu organización.
400PRODUCT_NOT_FOUNDUn product_id de los conceptos no existe en tu organización.
400EXCHANGE_RATE_REQUIREDOrden de cobro en USD con cfdi.exchange_rate igual a 0.
400CFDI_STAMP_FAILEDNo fue posible timbrar: faltan datos de la razón social, del cliente o de los conceptos, o el SAT o el PAC rechazaron el CFDI. message explica la causa.
400LEGAL_ENTITY_NOT_CONFIGUREDCon "test": true, la razón social no está configurada para timbrar CFDI de prueba.
401MISSING_API_KEY | INVALID_API_KEY | API_KEY_REVOKEDAPI key ausente, inválida o revocada.
403INSUFFICIENT_PERMISSIONSLa API key no tiene el permiso Crear en Órdenes de cobro.
500INTERNAL_ERRORError interno. Si ocurre después de timbrar, el CFDI se cancela y la orden de cobro no se crea.

400 — validación fallida

Orden de cobro en USD con cfdi pero sin cfdi.exchange_rate:

{
  "code": "VALIDATION_ERROR",
  "message": "Ocurrió un error con los datos de la orden de cobro. Verifica la información e intenta nuevamente.",
  "errors": [
    {
      "field": "cfdi.exchange_rate",
      "code": "custom",
      "message": "El tipo de cambio es requerido por el SAT."
    }
  ],
  "request_id": "4252bb14-7e68-48f8-8690-d2f0e9aaff39"
}

Impuesto con una categoría no permitida (ISR trasladado):

{
  "code": "VALIDATION_ERROR",
  "message": "La petición contiene datos inválidos. Revisa errors para ver el detalle de cada campo.",
  "errors": [
    {
      "field": "items.0.taxes.0.category",
      "code": "custom",
      "message": "ISR solo puede ser retenido"
    }
  ],
  "request_id": "bcb0be71-5561-417f-bbde-f336beffe3f5"
}

message depende de la etapa de validación; usa errors[] para identificar cada campo.

Abrir Credonix