DTOs de catálogo
Schemas completos de los DTOs que usan los endpoints de catálogo: productos, clientes, catálogos de códigos y marcas.
ProductoApiRequestDto
Cuerpo de POST /api/v1/productos.
interface ProductoApiRequestDto {
/** OBLIGATORIO. SKU/código propio del integrador. Clave del upsert. */
codigo: string;
/** OBLIGATORIO. */
nombre: string;
descripcion?: string | null;
/** OBLIGATORIO. Código CABYS de Hacienda, mínimo 13 dígitos. Dato fiscal — va al XML. */
codigoCabys: string;
/** OBLIGATORIO. Código de unidad de medida del catálogo de Hacienda
(GET /catalogos/unidades-medida). Dato fiscal — va al XML. */
unidadMedida: string;
/** OBLIGATORIO. > 0. */
precioVenta: number;
/** OBLIGATORIO. > 0. */
precioCosto: number;
/** Default 0. Informativo — no se recalcula contra precioVenta/precioCosto. */
porcentajeGanancia?: number;
idCategoria?: number | null;
idSubcategoria?: number | null;
/** Opcional. Si se omite en un ALTA, el producto queda SIN marca (se ve como 0 en
la respuesta). En una ACTUALIZACIÓN, si se omite, conserva la marca que el
producto ya tenía — es una de las dos excepciones a que el update no sea parcial. */
idMarca?: number | null;
/** Opcional. Misma regla que idMarca, aplicada a proveedor. */
idProveedor?: number | null;
/** Código de tipo de código de Hacienda ("01" del vendedor, "02" del comprador, …).
Default "01" si se omite. */
tipoCodigo?: string | null;
/** Solo aplica al dar de alta (default true). En una actualización el producto
conserva su estado, y mandar un valor distinto del actual devuelve 400. */
estado?: boolean;
/** OBLIGATORIO. Al menos 1 línea. En una actualización reemplaza la lista completa
de impuestos del producto — no se mezcla con la que ya tenía. */
impuestos: ProductoApiImpuestoDto[];
}Validaciones por campo
| Campo | Regla | Error si falla |
|---|---|---|
codigo | No vacío tras recortar espacios. | 400 — Debe indicar 'codigo'. |
nombre | No vacío tras recortar espacios. | 400 — Debe indicar 'nombre'. |
codigoCabys | Mínimo 13 dígitos. | 400 — El código CABYS debe tener 13 dígitos. |
unidadMedida | No vacío. | 400 — Debe indicar 'unidadMedida'. |
precioVenta | > 0. | 400 — Debe indicar 'precioVenta'. |
precioCosto | > 0. | 400 — Debe indicar 'precioCosto'. |
impuestos | Array no vacío, cada línea con codigo. | 400 — Debe indicar al menos un impuesto en 'impuestos'. / 400 — Cada línea de 'impuestos' debe indicar 'codigo'. |
ProductoApiImpuestoDto
Línea de impuesto de un producto.
interface ProductoApiImpuestoDto {
/** OBLIGATORIO. Código de impuesto del catálogo de Hacienda (p. ej. "01" = IVA). */
codigo: string;
porcentaje: number;
/** Código de tarifa dentro del impuesto (p. ej. "08" = tarifa general 13%). */
codigoTarifa?: string | null;
}ProductoApiResponseDto
Devuelto por POST /api/v1/productos y GET /api/v1/productos/{codigo}.
interface ProductoApiResponseDto {
idProducto: number;
codigo: string;
nombre: string;
descripcion?: string | null;
codigoCabys: string;
unidadMedida: string;
precioVenta: number;
precioCosto: number;
idCategoria?: number | null;
idSubcategoria?: number | null;
/** 0 = sin marca asignada. No es "marca número 0". */
idMarca: number;
/** 0 = sin proveedor asignado. No es "proveedor número 0". */
idProveedor: number;
estado: boolean;
impuestos: ProductoApiImpuestoDto[];
/** No bloqueante. Solo se llena cuando el guardado autocorrigió la unidad de medida
(CABYS de servicio con unidad no compatible). Viaja únicamente en la respuesta del
POST que la generó — GET /productos/{codigo} siempre la devuelve en null. */
advertencia?: string | null;
}ClienteApiRequestDto
Cuerpo de POST /api/v1/clientes. Upsert por identificacion: alta si no existe, actualización parcial si existe.
interface ClienteApiRequestDto {
/** OBLIGATORIO. Clave del upsert. No se puede cambiar una vez creado el cliente. */
identificacion?: string | null;
/** Código de tipo de identificación de Hacienda (01 física, 02 jurídica, …).
OBLIGATORIO al dar de alta. En una actualización, "" se ignora. */
tipoIdentificacion?: string | null;
/** OBLIGATORIO al dar de alta. En una actualización, "" se ignora. */
nombre?: string | null;
/** En una actualización, "" SÍ se aplica (queda vacío). */
apellidos?: string | null;
/** Nombre interno/comercial. Solo aplica a cédula jurídica ("02"). */
nombreInterno?: string | null;
/** OBLIGATORIO al dar de alta — una cadena vacía no pasa la validación. En una
actualización, si se envía, debe ser un correo válido: no se puede vaciar. */
correo?: string | null;
/** OBLIGATORIO al dar de alta. Se normaliza. En una actualización, si se envía,
debe ser un teléfono válido: no se puede vaciar. */
telefono?: string | null;
/** En una actualización, "" SÍ se aplica (queda en null). */
direccion?: string | null;
/** En una actualización, "" SÍ se aplica (queda en null). */
comentario?: string | null;
/** Default false al dar de alta. En una actualización se pisa solo si el campo
viene presente en el JSON — incluido un false explícito. */
pagaTimbre?: boolean | null;
/** Marcador; las exoneraciones en sí no se administran por este endpoint. */
exonerado?: boolean | null;
limiteCredito?: number | null;
}La semántica campo por campo de la actualización parcial está en Crear o actualizar cliente.
ClienteApiResponseDto
Devuelto por POST /api/v1/clientes y GET /api/v1/clientes/{identificacion}.
interface ClienteApiResponseDto {
idCliente: number;
identificacion: string;
tipoIdentificacion: string;
nombre: string;
apellidos: string;
nombreInterno?: string | null;
correo: string;
telefono: string;
direccion?: string | null;
comentario?: string | null;
estado: boolean;
exonerado: boolean;
pagaTimbre: boolean;
limiteCredito?: number | null;
}DTOs de solo lectura
DTOs devueltos por los catálogos de códigos.
interface MedioPagoApiDto {
/** Usar como medioPago al emitir. */
codigo: string;
nombre: string;
permiteDescuento: boolean;
}
interface CondicionVentaApiDto {
/** Usar como condicionVenta al emitir. */
codigo: string;
nombre: string;
}
interface UnidadMedidaApiDto {
/** Código de unidad de medida del catálogo de Hacienda. */
codigo: string;
nombre: string;
reduceInventario: boolean;
}
interface ActividadEconomicaApiDto {
codigo: string;
descripcion: string;
/** true = actividad por defecto del tenant cuando no se indica codigoActividad al emitir. */
principal: boolean;
}
interface PuntoVentaApiDto {
/** Usar como idPuntoVenta al emitir. */
id: number;
nombre: string;
activo: boolean;
}
interface TipoCodigoApiDto {
/** Usar como tipoCodigo al crear un producto. */
codigo: string;
descripcion: string;
}
interface MarcaApiDto {
/** Usar como idMarca al crear un producto. */
id: number;
nombre: string;
/* Sin campo 'activo': el listado ya devuelve solo marcas activas. */
}