POST
/api/mod/facturacion/{espacio}/ordersCrea una orden
Convierte un carrito en una orden con su total a pagar. Mandas variantes y cantidades: Productos pone los precios y aparta el stock, y la orden los congela. Responde con el total, hasta cuándo puede pagarse y las cuentas donde pagar.
- PERMISOescribe
- CRÉDITOSno gasta
- AUTENTICACIÓNBearer bth_…
PARÁMETROS
| CAMPO | TIPO | REQUERIDO | QUÉ ES |
|---|---|---|---|
| espacio | string | SÍ | El id del espacio (sale en GET /api/companies). Tiene que tener el módulo Facturación. |
CUERPO · JSON
| CAMPO | TIPO | REQUERIDO | QUÉ ES |
|---|---|---|---|
| lineas | [{ variant_id, cantidad }] | SÍ | Lo que compra: el id de la variante en Productos y cuántas (por defecto 1). Al menos una. |
| session_ref | string | no | Tu referencia de la conversación o del carrito. Luego puedes filtrar las órdenes por ella. |
| lead_ref | string | no | Tu referencia del cliente. |
| moneda | string | no | Por defecto "COP". |
| canal | string | no | El canal de la venta, por defecto "chat". Se le pasa a Productos al cotizar. |
| envio | string | no | El envío, por defecto 0. Se suma al total. Si lo cotizaste en Comercial, es su total_envio. |
| tarifa_version | string | no | La tarifa_version de esa cotización de Comercial, para saber con qué tabla se calculó el envío. |
| descuento | string | no | Un descuento tuyo o de los beneficios de Comercial, por defecto 0. Se resta del total de productos, sin pasar de él. |
| ttl_min | integer | no | Minutos para pagar antes de que venza. Por defecto, ttl_reserva_min de la configuración (45). |
| despacho | { campo: valor } | no | Datos de despacho que ya tengas. Solo se guardan los campos activos en la configuración; el resto se descarta sin error. Datos personales. |
RESPUESTA 201
La orden, en pending_payment. Guarda su id.
| CAMPO | TIPO | QUÉ ES |
|---|---|---|
| id · estado | string | El id de la orden y su estado: ver estados. |
| session_ref · lead_ref | string | null | Tus referencias de la conversación y del cliente, las que mandaste al crearla. |
| lineas[] | { variant_id, sku, nombre, cantidad, precio_unitario, total_linea, adjustments } | Cada línea con el precio que dio Productos al crearla. No cambia aunque el precio cambie después. |
| lineas[].adjustments | [{ promotion_id, regla, target, monto }] | Las promociones de Productos que rebajaron la línea. monto va en negativo. Vacío si ninguna. |
| subtotal · descuento_total | string | La suma de las líneas antes de promociones, y todos los descuentos: los de Productos más el descuento que mandaste. |
| envio | string | El envío que mandaste al crearla. 0 si no mandaste. |
| total | string | Lo que el cliente paga: el total de productos de Productos, menos tu descuento, más el envío. |
| moneda | string | Por defecto COP. |
| catalog_version · tarifa_version | string | null | La versión de precios de Productos con la que se cotizó, y la de la tarifa de Comercial que mandaste. |
| reservation_refs | string[] | Las reservas de stock en Productos. Vacío si reservar_stock está apagado. |
| despacho | object | null | Los datos de despacho guardados (campo → valor). Datos personales. |
| creado_at · actualizado_at | number | Segundos desde 1970, con decimales. |
| expira_at | number | null | Hasta cuándo puede pagarse, en segundos desde 1970. |
| cuentas[] | { metodo, etiqueta, numero, titular } | Las cuentas activas del espacio, para decirle al cliente dónde pagar. Salen de la configuración. |
| despacho_status | { activo, completo, faltantes, campos } | Qué datos de despacho faltan. Con el despacho apagado: activo: false y completo: true. |
ERRORES DE ESTA RUTA · SIEMPRE {"detail": …}
| STATUS | CUÁNDO | DETAIL LITERAL |
|---|---|---|
| 403 | El espacio no tiene el módulo Facturación | módulo no habilitado para este espacio. |
| 403 | La clave es de solo lectura | Tu cuenta es de solo lectura en este espacio. |
| 409 | Una variante no tiene stock suficiente. No se crea nada | Sin stock suficiente: sin disponibilidad para <variant_id> |
| 422 | lineas viene vacía | el carrito no tiene líneas. |
| 422 | Alguna variante no existe o no tiene precio en Productos | hay líneas sin precio; no se puede cotizar la orden. |
| 422 | Productos no devolvió ninguna línea con precio | la cotización no produjo líneas facturables. |
| 502 | Productos no responde. No se crea nada: reintenta | El servicio de productos no está disponible; intenta más tarde. |
| 422 | Falta un campo obligatorio o uno no es de su tipo (detail es una lista) | — |
Y los de cualquier ruta —clave inválida, cuenta no al día, IP, límites—, en Errores, límites y créditos.
CONVIENE SABER
- El precio lo pone Productos, nunca tú: la orden congela el de ese momento (
catalog_version) y no cambia aunque edites el catálogo después. - Con
reservar_stockencendido (por defecto), aparta las unidades en Productos hasta que la orden se pague, se cancele o venza. Si una línea no tiene stock, no se aparta nada y no se crea la orden. - La orden nace en
pending_paymentcon suexpira_at. Pasado ese momento no cambia sola: la vence vencer órdenes. - Los importes van como texto decimal (
"81300"), para no perder precisión.