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:
statusse calcula con las fechas:overduesi la fecha de vencimiento ya pasó,issuedsi la fecha de emisión ya llegó ycreatedsi todavía no llega.remaining_amount(saldo pendiente) es igual atotal_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_statusqueda enemittedsi se timbró un CFDI real y ennot_requireden 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
https://app.credonix.mx/api/v1/invoicesOrden 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
| Campo | Tipo | Requerido | Notas |
|---|---|---|---|
customer_id | string | Sí | Cliente de tu organización. |
legal_entity_id | string | Sí | Razón social emisora de tu organización. Obligatorio aunque no envíes cfdi. |
concept | string | Sí | No vacío. |
description | string | null | No | Si se omite, se guarda como "". Se envía al CFDI como condiciones de pago. |
issue_date | string | Sí | Fecha de emisión, YYYY-MM-DD. |
due_date | string | null | No | Fecha de vencimiento, YYYY-MM-DD. No puede ser anterior a issue_date. |
currency | MXN | USD | Sí | |
notes | string | null | No | Notas internas. |
items | array | Sí | Al menos un concepto. Ver items[]. |
cfdi | object | null | No | Si se envía, se timbra el CFDI en la misma solicitud. Ver cfdi. |
items[]
| Campo | Tipo | Requerido | Notas |
|---|---|---|---|
product_id | string | null | No | Producto de tu organización. |
product_name | string | null | No | Se requiere product_name o description. |
description | string | null | No | |
quantity | integer | Sí | Número JSON entero mayor que 0. |
unit_price | string | number | Sí | Decimal ≥ 0, por ejemplo "1234.50". |
discount | string | number | null | No | Decimal ≥ 0. Con percentage es un porcentaje (10 = 10 %); con fixed, un monto. |
discount_type | percentage | fixed | null | Con descuento | Obligatorio si discount es distinto de 0. |
product_code | string | null | Para timbrar | Clave de producto o servicio del SAT. |
unit_code | string | null | Para timbrar | Clave de unidad del SAT. |
taxes | array | No | Por defecto []. Ver items[].taxes[]. |
El total de cada concepto (subtotal − descuento + trasladados − retenidos) debe ser mayor o igual a 0.
items[].taxes[]
| Campo | Tipo | Requerido | Notas |
|---|---|---|---|
type | string | Sí | iva, isr o ieps, en minúsculas. Cualquier otro valor es un impuesto local de hasta 10 caracteres. |
category | transferred | withheld | exempt | Sí | iva: trasladado, retenido o exento. isr: solo retenido. ieps: trasladado o retenido. Impuestos locales: trasladado o retenido. |
rate | string | number | Sí | Fracción ≥ 0: "0.16" es 16 %. |
base | string | number | null | No | Si se omite o es 0, se usa el subtotal neto del concepto (subtotal − descuento). |
cfdi
| Campo | Tipo | Requerido | Notas |
|---|---|---|---|
payment_method | PUE | PPD | Sí | Método de pago. |
payment_form | string | Sí | Clave de forma de pago (ver catálogos). Con PPD debe ser 99; con PUE no puede ser 99. |
cfdi_use | string | No | Uso del CFDI. Por defecto G03. |
issue_date | string | Sí | Fecha de timbrado, YYYY-MM-DD. No puede ser futura ni de más de 2 días en el pasado. |
exchange_rate | string | number | null | Si currency es USD | Tipo de cambio, mayor que 0. En órdenes de cobro en MXN se ignora. |
test | boolean | No | Por defecto false. true timbra un CFDI de prueba. |
Catálogos del SAT
| Campo | Valores |
|---|---|
payment_form | 01 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_use | G01, G02, G03, I01–I08, D01–D10, CP01, CN01, S01. |
payment_method | PUE, PPD. |
Errores
| Status | Código | Causa |
|---|---|---|
400 | VALIDATION_ERROR | Falla 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. |
400 | CUSTOMER_NOT_FOUND | customer_id no existe en tu organización. |
400 | LEGAL_ENTITY_NOT_FOUND | legal_entity_id no existe en tu organización. |
400 | PRODUCT_NOT_FOUND | Un product_id de los conceptos no existe en tu organización. |
400 | EXCHANGE_RATE_REQUIRED | Orden de cobro en USD con cfdi.exchange_rate igual a 0. |
400 | CFDI_STAMP_FAILED | No 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. |
400 | LEGAL_ENTITY_NOT_CONFIGURED | Con "test": true, la razón social no está configurada para timbrar CFDI de prueba. |
401 | MISSING_API_KEY | INVALID_API_KEY | API_KEY_REVOKED | API key ausente, inválida o revocada. |
403 | INSUFFICIENT_PERMISSIONS | La API key no tiene el permiso Crear en Órdenes de cobro. |
500 | INTERNAL_ERROR | Error 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.