Referencia · Ventas
Crear una venta
/ventaCrearEmite un Comprobante Fiscal Electrónico (CFE).
La respuesta incluye tres opciones para imprimir o mostrar el comprobante:
-
urlA4: comprobante A4 en PDF. -
urlTicket: ticket térmico en PDF (formato estrecho). -
htmlTicket: ticket en HTML (útil para preview o impresión web).
Identificación del cliente
Sección titulada «Identificación del cliente»Cómo identifica Fixed a un cliente ya existente (para actualizarlo) en vez de crear uno nuevo, dentro de la misma empresa y mismo tipoDocumento:
-
Si documento no viene vacío: busca por documento. Si encuentra, actualiza ese cliente. Si no encuentra ningún cliente con ese documento, busca por mailEnvioFactura (ver punto 2); si tampoco encuentra por mail, crea un cliente nuevo con ese documento.
-
Si documento viene vacío pero mailEnvioFactura no: busca por mailEnvioFactura (sin distinguir mayúsculas/minúsculas ni espacios). Si encuentra, actualiza ese cliente. Si no encuentra, crea uno nuevo.
-
Si tanto documento como mailEnvioFactura vienen vacíos: siempre crea un cliente nuevo.
Esto permite, por ejemplo, facturar a nombre de clientes de e-commerce que la primera vez no informan documento (solo mail), y que si en una venta posterior sí lo informan, Fixed complete el documento en la misma ficha de cliente en vez de duplicarla.
Límites de caracteres
Sección titulada «Límites de caracteres»Estos campos tienen un largo máximo; si se supera, la request se rechaza con un error (no se trunca en silencio):
-
cliente.razonSocial: 150 caracteres (E18). -
cliente.nombreComercial: 150 caracteres (E18). -
lineasVenta[].descripcion: 80 caracteres (E24). -
lineasVenta[].descripcionLarga: 500 caracteres (E24).
Reintentos seguros (idempotencia)
Sección titulada «Reintentos seguros (idempotencia)»Si no recibiste la respuesta de un llamado anterior (por ejemplo por un corte de red) y no
sabés si la venta se llegó a emitir, no reintentes a ciegas: mandá el campo
idempotencyKey la primera vez que intentás emitir esa venta, y reusá exactamente el mismo
valor, con exactamente los mismos datos, para reintentar esa misma venta. Fixed te devuelve
la misma respuesta de la primera vez (sea éxito o error) en vez de reprocesar.
Una idempotencyKey queda asociada para siempre a los datos de esa venta puntual: no se
puede reusar para una venta distinta, ni para reintentar la misma venta con datos
corregidos. Si mandás la misma idempotencyKey con datos diferentes a los originales,
Fixed devuelve el error E23. Para emitir una venta distinta, o la misma venta con datos
corregidos, generá una idempotencyKey nueva.
Cómo generar la idempotencyKey: tiene que identificar el intento de emisión en sí,
nunca derivarse del contenido de la venta. Si la generás a partir de los datos de la venta
(por ejemplo un hash de sus campos), dos ventas distintas que coincidan en todos sus datos
(mismo cliente, mismo importe, etc.) van a chocar contra la misma key, y la segunda no se va
a emitir: va a recibir de vuelta el resultado de la primera.
-
Recomendado: un UUID v4 generado justo antes de intentar emitir esa venta puntual.
-
También válido: el identificador único de esa venta en tu sistema, si ya tenés uno. Puede ser el de la orden, el trabajo o el servicio.
idempotencyKey es opcional: si no lo mandás, el comportamiento es el de siempre, sin
protección contra reintentos duplicados.
La guía correspondiente está en Emitir un CFE.
Solicitud
Sección titulada «Solicitud»La ruta POST /ventaCrear se agrega a la URL base del ambiente.
Enviá los headers x-api-key y x-api-secret. Cómo obtenerlos está en Credenciales.
El cuerpo es JSON (Content-Type: application/json).
Si falta un campo obligatorio, la API rechaza la solicitud.
| Campo | Tipo | Obligatorio | Descripción | Ejemplo |
|---|---|---|---|---|
cliente |
objeto | null | Sí | Ver cliente. | — |
fecha |
string | Sí | Fecha del comprobante en formato dd/mm/aaaa. | 23/06/2026 |
moneda |
string | Sí | Código ISO de la moneda del comprobante (UYU, USD, EUR, etc.). | UYU |
montoBruto |
number | Sí | 0=precios sin IVA (neto), 1=precios con IVA incluido. | 1 |
lineasVenta |
array de objetos | Sí | Ver lineasVenta. | — |
observaciones |
string | Sí | Observaciones del comprobante. | "" |
totalAPagar |
number | Sí | Total a pagar calculado por el integrador; debe coincidir con el calculado por Fixed. | 120 |
redondear |
boolean | Sí | Si se aplica redondeo al total. | false |
local |
string | No | Id de local (opcional). Consultar /localesListado. | — |
formaDePago |
string | No | Forma de pago (opcional, default “contado”). Valores: contado, credito. |
contado |
cotizacion |
number | No | Cotización a usar cuando moneda es distinta de “UYU” (opcional): cuántos pesos uruguayos vale una unidad de la moneda del comprobante (por ejemplo, 43.5 si 1 EUR = $ 43,50). Si no se envía, se usa la cotización del día cargada en la empresa en Fixed o, si no hay, la del BCU. Se ignora si moneda es “UYU”. |
— |
ordenCompra |
string | No | Número de orden de compra (opcional). | "" |
idempotencyKey |
string | No | Clave de idempotencia (opcional). Si reintentás un llamado a /ventaCrear (por ejemplo porque no recibiste la respuesta anterior por un corte de red) usando la misma idempotencyKey y exactamente los mismos datos, Fixed devuelve el mismo resultado de la primera vez (éxito o error) en vez de reprocesar. Reusarla con datos distintos devuelve el error E23. Ver sección “Reintentos seguros (idempotencia)” en la descripción de POST /ventaCrear, especialmente cómo generar este valor correctamente. |
a1b2c3d4-e5f6-4a1b-9c2d-1234567890ab |
Solicitud cliente
Sección titulada «Solicitud cliente»| Campo | Tipo | Obligatorio | Descripción | Ejemplo |
|---|---|---|---|---|
tipoDocumento |
number | Sí | Tipo de documento: 2=RUT, 3=CI, 4=Otros, 5=Pasaporte, 6=DNI, 7=NIFE. | 2 |
documento |
string | Sí | Número de documento (RUT, CI, etc.). Obligatorio para tipoDocumento 2 (RUT); opcional para el resto. Ver sección “Identificación del cliente” en la descripción de POST /ventaCrear. | 219314970014 |
pais |
string | No | Código ISO de país (2 letras). Obligatorio para tipoDocumento 4 (Otros), 5 (Pasaporte), 6 (DNI) y 7 (NIFE). Para tipoDocumento 6 (DNI) solo se admite AR, BR, CL o PY. | AR |
razonSocial |
string | Sí | Razón social del cliente. | Panadería El Buen Pan S.A. |
nombreComercial |
string | Sí | Nombre comercial. | El Buen Pan |
domicilio |
string | Sí | Domicilio fiscal. | Av. Italia 1234 |
localidad |
string | Sí | Localidad. | Montevideo |
departamento |
string | Sí | Departamento. | Montevideo |
domicilioEntrega |
string | Sí | Domicilio de entrega. | Av. Italia 1234 |
mailEnvioFactura |
string | Sí | Email para envío de factura. Si no se envía documento, se usa para identificar al cliente (ver sección “Identificación del cliente” en la descripción de POST /ventaCrear). | facturacion@ejemplo.com |
telefono |
string | Sí | Teléfono de contacto. | 099123456 |
observaciones |
string | Sí | Observaciones del cliente. | "" |
Solicitud lineasVenta
Sección titulada «Solicitud lineasVenta»Líneas del comprobante (al menos una).
| Campo | Tipo | Obligatorio | Descripción | Ejemplo |
|---|---|---|---|---|
cantidad |
number | Sí | Cantidad de unidades vendidas. | 1 |
descripcion |
string | Sí | Nombre corto del ítem en el comprobante. | Pan francés |
descripcionLarga |
string | Sí | Detalle adicional de la línea. | Pan francés artesanal |
rubro |
string | Sí | Nombre o id del rubro de servicios; se crea si no existe. | Panadería |
tasaIva |
string | Sí | Valor cfeDgi de la tasa de IVA configurada en Fixed. Debe ser exactamente uno de los valores del enum CfeDgiTasaIva. Valores: Basic, Exp, Min, Exe, Otro, NoFac, Suspenso, Percibido, literalE. |
Basic |
descuentoMonto |
number | Sí | Monto de descuento en la línea (no porcentaje). | 0 |
precioUnitario |
number | Sí | Precio unitario según montoBruto. | 120 |
codigo |
string | No | Código del ítem (opcional), por ejemplo código de barras o código interno. Se guarda bajo el primer tipo de código que la empresa tenga configurado para impresión en Fixed (o “Código” si no tiene ninguno configurado), y así viaja en el comprobante fiscal igual que si se hubiera cargado a mano. | 7791234567890 |
Respuesta 200
Sección titulada «Respuesta 200»CFE emitido. Respuesta incluye urlA4, urlTicket y htmlTicket
Si la operación sale bien, codigoError viene vacío.
Si el CFE ya se emitió y después falla el armado de las URLs, la respuesta sigue siendo HTTP 200, con codigoError vacío y las URLs vacías. La descripcion indica el idCFE para consultar o imprimir. No reintentes la emisión: crearías otro comprobante.
| Campo | Tipo | Obligatorio | Descripción | Ejemplo |
|---|---|---|---|---|
descripcion |
string | Sí | Texto libre. Vacío cuando la operación sale bien. | — |
codigoError |
string | Sí | Vacío cuando la operación sale bien. Con valor, es un código de error de esta operación. | — |
idCFE |
string | Sí | Identificador del CFE en Fixed. Guardalo: lo piden la consulta, la impresión y la devolución. | — |
numero |
number | Sí | Número del comprobante dentro de la serie. | — |
serie |
string | Sí | Serie del comprobante. | — |
tipoCFE |
number | string | Sí | Código numérico del comprobante según DGI. Una venta sin RUT es 101 (e-Ticket) y con RUT es 111 (e-Factura). La nota de crédito correspondiente es 102 o 112. En un error puede venir como texto vacío. | — |
comprobante |
string | Sí | Texto legible armado como «tipo serie número». Por ejemplo, e-Ticket A 1523. |
— |
urlA4 |
string | Sí | URL del PDF del comprobante en formato A4. | — |
urlVerificarCFE |
string | Sí | Página para verificar el comprobante. En testing empieza con https://testing.fixed.uy/verificarCFE/ y en producción con https://acceso.fixed.uy/verificarCFE/. |
— |
idVenta |
string | No | Identificador de la venta en Fixed. | — |
urlTicket |
string | No | URL del ticket térmico en PDF. Formato estrecho para impresoras de ticket. | — |
htmlTicket |
string | No | Ticket en HTML. Útil para preview en pantalla o impresión desde el navegador. | — |
pdfBase64 |
string | No | PDF del comprobante en formato A4, en base64. | — |
xml |
string | No | XML del CFE firmado. | — |
observaciones |
string | No | Adenda de la venta. Es el mismo valor enviado en observaciones. |
— |
Errores
Sección titulada «Errores»Una respuesta de error trae codigoError y descripcion. El mismo código puede significar cosas distintas según el endpoint. El índice completo está en Códigos de error.
Si fallan las credenciales o el formato del body, aplican los códigos comunes: A01 a A06, V01 y V02.
| Código | Significado |
|---|---|
| E02 | Moneda incorrecta |
| E03 | Empresa no encontrada |
| E04 | Sin firma electrónica vigente |
| E05 | Sin CAE disponible |
| E08 | Formato de fecha inválido, debe ser dd/mm/aaaa |
| E15 | totalAPagar no coincide con el total calculado (ver “Cómo calcula Fixed el total” en POST /ventaCrear) |
| E18 | Datos de cliente inválidos para el tipo de documento indicado |
| E19 | Venta > 5000 UI sin documento, domicilio, localidad o departamento del cliente (DGI los exige) |
| E20 | formaDePago inválida |
| E21 | cotizacion inválida (debe ser mayor a 0) |
| E22 | Ya hay una emisión en curso con esa idempotencyKey |
| E23 | Esa idempotencyKey ya fue usada con datos distintos |
| E24 | descripcion supera 80 caracteres o descripcionLarga supera 500 |
| E25 | observaciones supera los 500 caracteres |
| E26 | cantidad (mayor a 0, hasta 3 decimales), precioUnitario (mayor a 0, hasta 2 decimales) o descuentoMonto (0 o más, hasta 2 decimales) inválido en una línea |
| X01 | Local inválido |
| X02 | Tasa de IVA no habilitada en la empresa, o descuento mayor al importe de la línea |
| X03 | Error inesperado generando la factura |
| X04 | Error inesperado |
| X05 | Error inesperado generando la venta |
HTTP 500
Sección titulada «HTTP 500»Error de validación o negocio (ver codigoError)
{ "descripcion": "Moneda incorrecta", "codigoError": "E02", "idCFE": "", "numero": 0, "serie": "", "tipoCFE": "", "comprobante": "", "urlA4": "", "urlVerificarCFE": ""}Ejemplos
Sección titulada «Ejemplos»Venta a consumidor final
Sección titulada «Venta a consumidor final»Sin cliente identificado. Una línea en UYU con IVA incluido en precio.
{ "cliente": null, "fecha": "23/06/2026", "moneda": "UYU", "montoBruto": 1, "lineasVenta": [ { "cantidad": 1, "descripcion": "Pan francés", "descripcionLarga": "Pan francés artesanal", "rubro": "Panadería", "tasaIva": "Basic", "descuentoMonto": 0, "precioUnitario": 120 } ], "observaciones": "", "totalAPagar": 120, "redondear": false}Venta con múltiples líneas
Sección titulada «Venta con múltiples líneas»Caso típico en POS/e-commerce: varias líneas con distintos rubros y tasas de IVA. Ajustá tasaIva según lo configurado en Fixed (Basic=22%, Min=10%, Exe=0%).
{ "cliente": null, "fecha": "23/06/2026", "moneda": "UYU", "montoBruto": 1, "lineasVenta": [ { "cantidad": 2, "descripcion": "Pan francés", "descripcionLarga": "Pan francés artesanal", "rubro": "Panadería", "tasaIva": "Basic", "descuentoMonto": 0, "precioUnitario": 120 }, { "cantidad": 1, "descripcion": "Leche entera", "descripcionLarga": "Leche entera 1 litro", "rubro": "Lácteos", "tasaIva": "Min", "descuentoMonto": 0, "precioUnitario": 55 }, { "cantidad": 3, "descripcion": "Bolsa reciclable", "descripcionLarga": "Bolsa biodegradable", "rubro": "Accesorios", "tasaIva": "Exe", "descuentoMonto": 0, "precioUnitario": 10 } ], "observaciones": "", "totalAPagar": 325, "redondear": false}Venta con cliente identificado
Sección titulada «Venta con cliente identificado»Cliente con RUT. Si ya existe, se actualizan sus datos.
{ "cliente": { "tipoDocumento": 2, "documento": "219314970014", "razonSocial": "Panadería El Buen Pan S.A.", "nombreComercial": "El Buen Pan", "domicilio": "Av. Italia 1234", "localidad": "Montevideo", "departamento": "Montevideo", "domicilioEntrega": "Av. Italia 1234", "mailEnvioFactura": "facturacion@ejemplo.com", "telefono": "099123456", "observaciones": "" }, "fecha": "23/06/2026", "moneda": "UYU", "montoBruto": 1, "lineasVenta": [ { "cantidad": 2, "descripcion": "Docena de medialunas", "descripcionLarga": "Medialunas de manteca", "rubro": "Panadería", "tasaIva": "Basic", "descuentoMonto": 0, "precioUnitario": 450 } ], "observaciones": "Mostrador", "totalAPagar": 900, "redondear": false, "local": ""}Venta en dólares
Sección titulada «Venta en dólares»Comprobante en USD. Verificar cotización vigente de la empresa.
{ "cliente": null, "fecha": "23/06/2026", "moneda": "USD", "montoBruto": 1, "lineasVenta": [ { "cantidad": 1, "descripcion": "Servicio exportación", "descripcionLarga": "", "rubro": "Servicios", "tasaIva": "Exp", "descuentoMonto": 0, "precioUnitario": 50 } ], "observaciones": "", "totalAPagar": 50, "redondear": false}Venta a crédito
Sección titulada «Venta a crédito»Igual a una venta simple, pero con formaDePago: “credito” en vez del default “contado”.
{ "cliente": null, "fecha": "23/06/2026", "moneda": "UYU", "montoBruto": 1, "lineasVenta": [ { "cantidad": 1, "descripcion": "Pan francés", "descripcionLarga": "Pan francés artesanal", "rubro": "Panadería", "tasaIva": "Basic", "descuentoMonto": 0, "precioUnitario": 120 } ], "observaciones": "", "totalAPagar": 120, "redondear": false, "formaDePago": "credito"}Venta con descuento en una línea
Sección titulada «Venta con descuento en una línea»descuentoMonto es un importe (no un porcentaje): se resta del precioUnitario x cantidad de esa línea antes de calcular el IVA.
{ "cliente": null, "fecha": "23/06/2026", "moneda": "UYU", "montoBruto": 1, "lineasVenta": [ { "cantidad": 2, "descripcion": "Docena de medialunas", "descripcionLarga": "Medialunas de manteca", "rubro": "Panadería", "tasaIva": "Basic", "descuentoMonto": 100, "precioUnitario": 450 } ], "observaciones": "Descuento por pronto pago", "totalAPagar": 800, "redondear": false}Respuesta de una venta a consumidor final
Sección titulada «Respuesta de una venta a consumidor final»Esta forma sale del armado de la respuesta en el código. Los identificadores, el número y el tramo final de cada URL los genera Fixed al emitir. En testing el dominio es testing.fixed.uy; en producción, acceso.fixed.uy.
{ "descripcion": "", "codigoError": "", "idCFE": "id-generado-por-fixed", "idVenta": "id-de-la-venta", "numero": 1523, "serie": "A", "tipoCFE": 101, "comprobante": "e-Ticket A 1523", "urlA4": "https://testing.fixed.uy/verificarCFEverPDF/...", "urlTicket": "https://testing.fixed.uy/verificarCFEverTicket/...", "urlVerificarCFE": "https://testing.fixed.uy/verificarCFE/...", "htmlTicket": "<html>...</html>", "pdfBase64": "...", "xml": "<?xml version=\"1.0\" ...>", "observaciones": ""}