Ventas BETA
Endpoints para crear ventas y facturar desde un sistema externo.
Estos endpoints están disponibles para uso anticipado pero pueden cambiar de contrato, comportamiento o ser retirados antes de su release definitivo. No los comprometas en producción sin confirmar disponibilidad.
El comprobante se emite en la sucursal del punto de venta de tu integración, y esa sucursal
tiene que estar dentro de las habilitadas para el canal. Si el administrador del ERP configuró
una lista de sucursales habilitadas que no la incluye, la
operación responde 403.
A diferencia de las exportaciones, acá no hace falta tener sucursales cargadas: si no hay lista, se toma la sucursal de los depósitos o del punto de venta ya configurados en el canal. Una integración que hoy funciona sigue funcionando.
Venta directa
Permite crear una FACTURA_VENTA en forma directa, sin pasar antes por preventa.
/integraciones/terceros/ventaRequest
export interface VentaTerceros extends PedidoTerceros {
medioPago: MedioPagoTerceros;
}
export interface PedidoTerceros {
ordenId: number;
numero: number;
detalle?: string;
listaPrecioId?: number; // si no viene o es 0, usa la configurada en el canal
direccionEnvio?: DireccionTerceros;
direccionFacturacion?: DireccionTerceros;
usuario?: UsuarioTerceros; // requerido salvo que mandes entidadId
productos: ArticuloExterno[];
subtotal: number;
descuento: number;
recargo: number;
envio: number;
total: number;
empleadoId?: number; // vendedor del comprobante; pisa al configurado en el canal
entidadId?: number; // cliente explícito; si viene, ignora usuario y no crea cliente
}
export interface MedioPagoTerceros {
tipo: TipoMedio;
cuentaBancariaId?: number; // requerido si tipo = DEPOSITO_BANCO
tarjetaId?: number; // requerido si tipo = TARJETA
externalId?: string; // requerido si tipo = VIRTUAL
}
Tipos de medio de pago
export enum TipoMedio {
EFECTIVO = 1,
TARJETA = 5,
CUENTA_CORRIENTE = 6,
DEPOSITO_BANCO = 9,
VIRTUAL = 11,
}
ventaAunque el DTO admite varios tipos, hoy POST /venta aplica el medio con el helper interno
de integraciones, que solo soporta EFECTIVO, DEPOSITO_BANCO y VIRTUAL. Si se envía
otro tipo, la operación puede fallar con "El medio de pago no es compatible".
Respuesta
ajFacturaResult
Validaciones
| Regla | Error |
|---|---|
| Body inválido o sin productos | "Los datos de venta son invalidos" |
medioPago ausente | "El medio de pago es requerido" |
Request duplicada dentro de 30 segundos para el mismo ordenId | "La solicitud ya se esta procesando" |
| Medio de pago no soportado por el helper | "El medio de pago no es compatible" |
| Punto de venta en una sucursal no habilitada | 403 con "El punto de venta N pertenece a una sucursal no habilitada para esta integracion..." |
empleadoId que no es un empleado activo de una sucursal habilitada | 403 con "El empleadoId N no es un empleado valido..." |
entidadId que no es un cliente activo | 403 con "El entidadId N no es un cliente valido" |
Sin entidadId válido y sin usuario con dni/cuit/email | 400 con "Debe indicar entidadId o los datos del cliente..." |
Notas operativas
- el punto de venta lo toma siempre de la configuración de la integración
- si
listaPrecioIdno viene o es0, toma la configurada en la app/canal - usa una ventana anti-duplicados de 30 segundos por
ordenId - internamente asigna
numero = ordenId - el vendedor sale de
empleadoIdsi lo mandás; si no, del configurado en la integración - el cliente sale de
entidadIdsi lo mandás; si no, se resuelve/crea a partir deusuario
El vendedor del comprobante se resuelve en este orden: empleadoId del body, después el
vendedor por defecto de tu integración, y por último el vendedor asignado al cliente
(este último solo si tu integración está configurada para priorizarlo). Los ids válidos salen
de GET /empleados. Aplica igual a pedido, venta y
notacredito.
Si mandás entidadId, se usa ese cliente directo — no se busca por documento/CUIT/email ni se
crea uno nuevo. Sin entidadId, usuario sigue siendo obligatorio (con al menos dni, cuit
o email) para identificar o dar de alta al cliente. Un entidadId inválido responde 403;
la falta total de datos de cliente responde 400. Aplica igual a pedido, venta y
notacredito. Los ids válidos salen de GET /entidades.
Ejemplo
curl --request POST \
--url https://api.test-ninox.com.ar/integraciones/terceros/venta \
--header 'X-NX-TOKEN: {TU_TOKEN}' \
--header 'Content-Type: application/json' \
--data '{
"ordenId": 12345,
"numero": 12345,
"detalle": "Venta directa desde sistema externo",
"listaPrecioId": 3,
"usuario": {
"nombre": "Juan Perez",
"email": "juan@example.com",
"dni": "12345678",
"telefono": "1122334455",
"condicion": 1
},
"productos": [
{ "articuloId": 100, "precio": 1500.5, "cantidad": 2 }
],
"subtotal": 3001,
"descuento": 0,
"recargo": 0,
"envio": 500,
"total": 3501,
"medioPago": { "tipo": 1 }
}'
Nota de crédito
Crea una NOTACREDITO_VENTA directa. Espeja el flujo de venta: mismo payload de cliente,
productos, totales y medioPago (el medio con el que se reintegra), más un campo opcional
facturaRefId para vincular la nota de crédito a la venta original. El punto de venta lo
toma de la configuración de la integración.
/integraciones/terceros/notacreditoRequest
export interface NotaCreditoTerceros extends PedidoTerceros {
medioPago: MedioPagoTerceros;
facturaRefId?: number; // FacturaId de la venta original a acreditar (opcional)
}
Reutiliza las interfaces PedidoTerceros y MedioPagoTerceros definidas en
Venta directa.
Respuesta
ajFacturaResult
Validaciones
| Regla | Error |
|---|---|
| Body inválido o sin productos | "Los datos de la nota de credito son invalidos" |
medioPago ausente | "El medio de pago es requerido" |
Request duplicada dentro de 30 segundos para el mismo ordenId | "La solicitud ya se esta procesando" |
facturaRefId no corresponde a ninguna factura | "No se encontro la venta original {id} a acreditar" |
| Medio de pago no soportado por el helper | "El medio de pago no es compatible" |
entidadId que no es un cliente activo | 403 con "El entidadId N no es un cliente valido" |
Sin entidadId válido y sin usuario con dni/cuit/email | 400 con "Debe indicar entidadId o los datos del cliente..." |
Notas operativas
- el punto de venta lo toma siempre de la configuración de la integración
- si
listaPrecioIdno viene o es0, toma la configurada en la app/canal facturaRefIdes opcional pero recomendado: vincula la nota de crédito a la venta original, lo que habilita el saldado en cuenta corriente (en cascada) y la trazabilidad NC↔Venta- genera un ingreso de stock por los productos devueltos (no reserva stock)
- usa una ventana anti-duplicados de 30 segundos por
ordenId, independiente de la deventa - al igual que
venta, el medio se aplica con el helper interno que hoy soportaEFECTIVO,DEPOSITO_BANCOyVIRTUAL - acepta
empleadoIdcon la misma precedencia queventa(ver más arriba) - acepta
entidadIdcon la misma semántica queventa(ver más arriba)
Ejemplo
curl --request POST \
--url https://api.test-ninox.com.ar/integraciones/terceros/notacredito \
--header 'X-NX-TOKEN: {TU_TOKEN}' \
--header 'Content-Type: application/json' \
--data '{
"ordenId": 12345,
"numero": 12345,
"detalle": "Nota de credito por devolucion",
"listaPrecioId": 3,
"facturaRefId": 456,
"usuario": {
"nombre": "Juan Perez",
"email": "juan@example.com",
"dni": "12345678",
"telefono": "1122334455",
"condicion": 1
},
"productos": [
{ "articuloId": 100, "precio": 1500.5, "cantidad": 2 }
],
"subtotal": 3001,
"descuento": 0,
"recargo": 0,
"envio": 500,
"total": 3501,
"medioPago": { "tipo": 1 }
}'
Facturar preventa
Convierte una preventa existente en FACTURA_VENTA.
/integraciones/terceros/facturarRequest
export interface FacturarTerceros {
facturaId: number; // id de la preventa existente
puntoVentaId: number;
electronica: boolean;
medioPago: MedioPagoTerceros;
}
Respuesta
ajFacturaResult
Validaciones
| Regla | Error |
|---|---|
Body inválido o facturaId <= 0 | "El facturaId es requerido" |
medioPago ausente | "El medio de pago es requerido" |
puntoVentaId <= 0 | "El puntoVentaId es requerido" |
puntoVentaId inexistente | 403 con "El punto de venta N no existe" |
puntoVentaId en una sucursal no habilitada | 403 con "El punto de venta N pertenece a una sucursal no habilitada para esta integracion..." |
Request duplicada dentro de 30 segundos para la misma facturaId | "La solicitud ya se esta procesando" |
Notas operativas
- requiere que la preventa exista y esté en estado
PENDIENTE - si
electronica = true, intenta generar factura electrónica AFIP - usa una ventana anti-duplicados de 30 segundos por
facturaId - a diferencia de
venta, la facturación de preventa soporta el flujo completo de medios (EFECTIVO,TARJETA,CUENTA_CORRIENTE,DEPOSITO_BANCO,VIRTUAL) - no acepta
empleadoId: la preventa que estás facturando ya trae su vendedor - los
puntoVentaIdválidos los devuelveGET /puntos-venta
Ejemplo
curl --request POST \
--url https://api.test-ninox.com.ar/integraciones/terceros/facturar \
--header 'X-NX-TOKEN: {TU_TOKEN}' \
--header 'Content-Type: application/json' \
--data '{
"facturaId": 456,
"puntoVentaId": 1,
"electronica": false,
"medioPago": { "tipo": 9, "cuentaBancariaId": 12 }
}'
Medios de pago
Devuelve la configuración de medios habilitados y los catálogos necesarios para obtener ids
válidos antes de llamar a venta o facturar.
/integraciones/terceros/medios-pagoRespuesta
export interface MediosPagoConfigDTO {
medios: WMedios;
tarjetas: TarjetaDTO[];
tarjetasReglas: TarjetaReglaDTO[];
cuentasBancarias: CuentaBancariaDTO[];
bancos: BancoDTO[];
tarjetaCreditoReglas: boolean;
botonesRapidos: BotonRapidoConfig[];
recargoDigitalHabilitado: boolean;
facturaElectronicaAutomatica: boolean;
recargosTipoMedio: RecargoTipoMedioConfig[];
}
export interface WMedios {
efectivo: boolean;
cuentaCorriente: boolean;
tarjeta: boolean;
cheque: boolean;
tarjetaPropia: boolean;
chequePropio: boolean;
chequeCartera: boolean;
deposito: boolean;
extraccion: boolean;
transferencia: boolean;
virtual: boolean;
}
export interface CuentaBancariaDTO {
cuentaBancariaId: number;
descripcion: string;
bancoId?: number;
alias?: string;
cbu?: string;
}
Uso recomendado
- consultar este endpoint antes de operar con
DEPOSITO_BANCOoTARJETA - tomar
tarjetas[].tarjetaIdpara pagos con tarjeta - tomar
cuentasBancarias[].cuentaBancariaIdpara pagos por depósito o transferencia - usar
medioscomo capacidad disponible del tenant antes de construir el payload
Ejemplo
curl --request GET \
--url https://api.test-ninox.com.ar/integraciones/terceros/medios-pago \
--header 'X-NX-TOKEN: {TU_TOKEN}' \
--header 'Content-Type: application/json'
Flujos recomendados
Venta directa
- Consultar
/medios-pagopara validar el tipo disponible y obtener ids de tarjetas o cuentas bancarias si hacen falta. - Construir el payload de
ventacon cliente, productos, totales ymedioPago. - Enviar a
/venta. - Verificar
ajFacturaResulty registrarfacturaId,numero,pvNumeroy errores.
Facturación de preventa
- Tomar el
facturaIdde la preventa existente. - Consultar
/medios-pagosi el medio requiere ids auxiliares. - Enviar a
/facturar. - Verificar
ajFacturaResulty el estado final de la factura.
Nota de crédito
- Tomar el
facturaIdde la venta original a acreditar (parafacturaRefId). - Consultar
/medios-pagosi el medio de reintegro requiere ids auxiliares. - Construir el payload con cliente, productos a devolver, totales y
medioPago. - Enviar a
/notacredito. - Verificar
ajFacturaResulty registrarfacturaId,numero,pvNumeroy errores.