Tutorial: Generar nota de remisión (desde carrito existente)
¡Hola! Te voy a explicar paso a paso cómo generar una nota de remisión electrónica usando nuestra API, a partir de un carrito ya existente. No es el flujo simplificado libre: en este tutorial se asume que ya tenés un carrito creado y querés emitir la nota de remisión sobre sus ítems. No te preocupes si no eres experto en programación, te lo explico de manera sencilla.
Entorno
Sección titulada «Entorno»URL Base: https://api.guarani.app
¿Qué vamos a hacer?
Sección titulada «¿Qué vamos a hacer?»Este flujo es para emitir una nota de remisión basada en un carrito existente. Necesitás tener ya creado un carrito (por ejemplo, desde el flujo de factura simplificada u otro proceso). Luego:
- Consultar el timbrado (autorización de la SET)
- Consultar los ítems disponibles del carrito (qué ítems pueden incluirse en la remisión)
- Construir los datos de la remisión (emisión, chofer, transporte, vehículo, salida, destino, ítems)
- Enviar todo junto al endpoint de notas de remisión
Requisito previo: Tenés que tener ya un carrito creado en el sistema (y conocer su carrito_id). Este tutorial no cubre la creación del carrito; solo la emisión de la nota de remisión sobre ese carrito.
Paso 1: Consultar el timbrado
Sección titulada «Paso 1: Consultar el timbrado»¿Por qué necesitás consultar el timbrado?
Sección titulada «¿Por qué necesitás consultar el timbrado?»El timbrado es la autorización que te da la SET (Secretaría de Estado de Tributación) para emitir documentos electrónicos. Contiene información importante que necesitás incluir en cada nota de remisión:
- numero_timbrado: El número de autorización de la SET
- numero_establecimiento: El código de tu local o sucursal
- punto_expedicion: El punto desde donde emitís los documentos
¿Cómo consultar el timbrado?
Sección titulada «¿Cómo consultar el timbrado?»Hacé una consulta al endpoint de timbrados:
curl -X GET "https://api.guarani.app/timbrados?page=1&limit=100" \ -H "x-api-key: Bearer <access_token>" \ -H "Accept: application/json" | jqNota: Reemplazá
<access_token>con un token JWT válido proporcionado por el equipo Guarani.
Para más información sobre timbrados, consultá la documentación completa en Obtener lista de timbrados.
Paso 2: Consultar los ítems disponibles
Sección titulada «Paso 2: Consultar los ítems disponibles»Antes de armar el cuerpo de la nota de remisión, tenés que saber qué ítems del carrito están pendientes de remitir. Cada ítem del carrito tiene un id que usarás como carrito_item_id en el array items al emitir la remisión. Solo podés incluir ítems con cantidad_disponible mayor a cero.
Endpoint: GET /notas/remision/carrito/{carrito_id}/items-pendientes
Reemplazá {carrito_id} por el ID del carrito sobre el que querés emitir la nota de remisión.
curl --location 'https://api.guarani.app/notas/remision/carrito/{carrito_id}/items-pendientes' \ --header 'Content-Type: application/json' \ --header 'x-api-key: Bearer <access_token>' | jqNota: Reemplazá
<access_token>y{carrito_id}por tu token JWT válido y el ID del carrito respectivamente.
Ejemplo de respuesta (ítems pendientes)
Sección titulada «Ejemplo de respuesta (ítems pendientes)»La respuesta trae en data todos los ítems del carrito. Cada ítem tiene mercaderia o servicio (uno de los dos será null), datos del producto/servicio, precios, IVA, y los campos que necesitás para la remisión: id (ese valor es el carrito_item_id que usás en el body al emitir) y cantidad_disponible (cuánto podés remitir de ese ítem). Solo podés incluir ítems con cantidad_disponible mayor a cero; los que tengan 0 ya fueron remitidos.
{ "success": true, "codigo": "200", "message": "Operación realizada correctamente.", "data": [ { "id": "dcb9f237-32ea-4a95-ab07-62d51a59e9fc", "mercaderia": null, "servicio": { "id": "47e62259-8850-4e5d-a653-9fb32061ebb2", "descripcion": "Ejemplo de servicio", "descripcion_larga": "", "observacion": "", "codigo_interno": "02-SRV0012", "servicio_clasificacion_id": "00000000-0000-4000-8000-000000000000", "imagen_url": null, "unidad_medida": { "id": "5f49c6c1-d622-4f5b-9d8b-2d1636b584ab", "codigo_sifen": "77", "representacion": "UNI", "descripcion": "Unidad" }, "precio_unitario": { "0": 0, "5": 0, "10": 5980 }, "moneda": "PYG", "establecimiento_id": "06dabe45-cbb5-425e-b1c3-13a67d7114e0" }, "precio_unitario": 5980, "precio_unitario_original": 5980, "total": 5980, "cantidad": 1, "iva": { "iva_tipo": 10, "monto": 543.63636364, "afectacion": 100 }, "cantidad_original": 1, "cantidad_remitida": 0, "cantidad_disponible": 1, "cantidad_devuelta": 0 } ]}En el ejemplo, el ítem tiene id dcb9f237-32ea-4a95-ab07-62d51a59e9fc y cantidad_disponible: 1. Para incluirlo en la remisión usás ese id como carrito_item_id y la cantidad a remitir (en este caso 1). En la respuesta real, data puede traer muchos ítems; solo usá los que tengan cantidad_disponible mayor a cero.
✅ Con esta lista ya sabés qué carrito_item_id usar y cuánto podés remitir por ítem.
Paso 3: Construir los datos de emisión y datos generales
Sección titulada «Paso 3: Construir los datos de emisión y datos generales»⚠️ IMPORTANTE: Pasos preparatorios vs envío final
Sección titulada «⚠️ IMPORTANTE: Pasos preparatorios vs envío final»Este tutorial explica cómo preparar todos los datos para enviarlos en una sola llamada al endpoint final. Los pasos 3 a 8 son de preparación: construís cada parte del JSON; en el paso final juntás todo y enviás.
Necesitás el ID de ciudad para los objetos salida y destino. Podés obtenerlo con GET /ciudades (ver obtener ciudad ID).
datos_emision
Sección titulada «datos_emision»Datos del timbrado y punto de expedición con los que se emite la nota de remisión.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
numero_timbrado | string | Sí | Número de timbrado. |
punto_expedicion | string | Sí | Punto de expedición. |
numero_establecimiento | string | Sí | Número de establecimiento. |
Datos generales (raíz del body)
Sección titulada «Datos generales (raíz del body)»| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
carrito_id | string | Sí | ID del carrito (el mismo que usaste en Paso 1). |
motivo_codigo | number | Sí | Código del motivo del traslado (ver Motivo código). |
responsable_emision | number | Sí | Quién es responsable de la emisión (ver Responsable de emisión). |
kilometros_estimados | number | Sí | Kilómetros estimados del traslado. |
transportista | object | Sí | Objeto con los datos del transportista. |
transportista
Sección titulada «transportista»| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
tipo_persona | number | Sí | Tipo de persona (ver Tipos de personas). |
tipo_documento | number | Sí | Tipo de documento (ver Tipos de documentos). |
documento | string | Sí | Número de documento. |
nombre | string | Sí | Nombre completo. |
nacionalidad | string | Sí | Nacionalidad. |
fecha_nacimiento | string | Sí | Fecha de nacimiento. |
whatsapp | string | Sí | WhatsApp. |
email | string | Sí | Email. |
direccion | string | Sí | Dirección. |
ciudad_id | string | Sí | ID de la ciudad. |
Ejemplo (datos de emisión y datos generales)
Sección titulada «Ejemplo (datos de emisión y datos generales)»{ "datos_emision": { "numero_timbrado": "12345678", "punto_expedicion": "001", "numero_establecimiento": "001" }, "carrito_id": "a01aa396-dd43-48de-988f-2c07618ac33e", "motivo_codigo": 1, "responsable_emision": 1, "kilometros_estimados": 12, "transportista": { "tipo_persona": 1, "tipo_documento": 0, "documento": "12345678-9", "nombre": "Transportista Ejemplo", "nacionalidad": "PRY", "fecha_nacimiento": "11/09/2005", "whatsapp": "+595981234567", "direccion": "Dirección de transportista", "ciudad_id": "67ef2e9f-0fa7-43e7-ad5e-87a694e56341" }}Paso 4: Construir el objeto chofer
Sección titulada «Paso 4: Construir el objeto chofer»Datos del chofer que realiza el traslado.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
numero_documento | string | Sí | Número de documento (CI u otro). |
nombre | string | Sí | Nombre completo del chofer. |
domicilio_fiscal | string | Sí | Domicilio fiscal del chofer. |
Ejemplo (chofer)
Sección titulada «Ejemplo (chofer)»{ "chofer": { "numero_documento": "1234567", "nombre": "Chofer Ejemplo", "domicilio_fiscal": "Dirección de chofer" }}Paso 5: Construir el objeto transporte
Sección titulada «Paso 5: Construir el objeto transporte»Datos del tipo de transporte, modalidad, responsable del flete y fechas del traslado.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
tipo | number | Sí | Tipo de transporte (ver Tipo de transporte). |
modalidad | number | Sí | Modalidad del transporte (ver Modalidad de transporte). |
responsable_costo_flete | number | Sí | Quién asume el costo del flete (ver Responsable costo flete). |
codigo_condicion_negocio | string | Sí | Código de la condición de negocio (ver Códigos de las condiciones de negocio). |
fecha_inicio_traslado | string | Sí | Fecha de inicio (formato DD/MM/YYYY). |
fecha_fin_traslado | string | Sí | Fecha de fin (formato DD/MM/YYYY). |
Ejemplo (transporte)
Sección titulada «Ejemplo (transporte)»{ "transporte": { "tipo": 1, "modalidad": 1, "responsable_costo_flete": 1, "codigo_condicion_negocio": "FOB", "fecha_inicio_traslado": "02/02/2026", "fecha_fin_traslado": "02/02/2026" }}Paso 6: Construir el objeto vehiculo
Sección titulada «Paso 6: Construir el objeto vehiculo»Datos del vehículo utilizado en el traslado.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
tipo_vehiculo | number | Sí | Tipo de vehículo (ver tablas). |
marca | string | Sí | Marca del vehículo. |
tipo_identificacion | number | Sí | Tipo de identificación (ej. matrícula). |
numero_matricula | string | Sí | Número de matrícula u otro identificador. |
Ejemplo (vehiculo)
Sección titulada «Ejemplo (vehiculo)»{ "vehiculo": { "tipo_vehiculo": 1, "marca": "Vehículo Ejemplo", "tipo_identificacion": 2, "numero_matricula": "ABC123" }}Paso 7: Construir salida y destino
Sección titulada «Paso 7: Construir salida y destino»Punto de salida y punto de destino del traslado. Para ambos necesitás un ciudad_id (consulta GET /ciudades si no lo tenés; ver obtener ciudad).
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
direccion | string | Sí | Dirección de salida. |
ciudad_id | string | Sí | UUID de la ciudad de salida. |
whatsapp | string | Sí | WhatsApp de contacto (ej. +595981234567). |
numero_casa | string | No | Número de casa (opcional). |
direccion_complementaria | string | No | Dirección complementaria (opcional). |
direccion_complementaria_2 | string | No | Segunda dirección complementaria (opcional). |
destino
Sección titulada «destino»| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
direccion | string | Sí | Dirección de destino. |
ciudad_id | string | Sí | UUID de la ciudad de destino. |
whatsapp | string | Sí | WhatsApp de contacto. |
numero_casa | string | No | Número de casa (opcional). |
direccion_complementaria | string | No | Dirección complementaria (opcional). |
direccion_complementaria_2 | string | No | Segunda dirección complementaria (opcional). |
Ejemplo (salida y destino)
Sección titulada «Ejemplo (salida y destino)»Campos obligatorios únicamente:
{ "salida": { "direccion": "Dirección de salida", "ciudad_id": "67ef2e9f-0fa7-43e7-ad5e-87a694e56341", "whatsapp": "+595981234567" }, "destino": { "direccion": "Dirección de destino", "ciudad_id": "67ef2e9f-0fa7-43e7-ad5e-87a694e56341", "whatsapp": "+595981234567" }}Con datos opcionales de dirección:
{ "salida": { "direccion": "Dirección de salida", "ciudad_id": "67ef2e9f-0fa7-43e7-ad5e-87a694e56341", "whatsapp": "+595981234567", "numero_casa": "123", "direccion_complementaria": "Entre Av. España y Brasil", "direccion_complementaria_2": "Edificio Torre Norte" }, "destino": { "direccion": "Dirección de destino", "ciudad_id": "67ef2e9f-0fa7-43e7-ad5e-87a694e56341", "whatsapp": "+595981234567", "numero_casa": "456", "direccion_complementaria": "Local 2" }}Paso 8: Construir el array items
Sección titulada «Paso 8: Construir el array items»El array items indica qué ítems del carrito se incluyen en esta nota de remisión y cuánta cantidad se remite de cada uno. Los carrito_item_id y las cantidades disponibles los obtuviste en el Paso 2 (consulta de ítems pendientes). La cantidad a remitir no puede superar cantidad_disponible de ese ítem.
Cada elemento del array tiene:
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
carrito_item_id | string | Sí | El id del ítem en la respuesta de items pendientes. |
cantidad | number | Sí | Cantidad a remitir (≤ cantidad_disponible del ítem). |
Ejemplo (array de items)
Sección titulada «Ejemplo (array de items)»Si en el Paso 2 un ítem tiene id: "dcb9f237-32ea-4a95-ab07-62d51a59e9fc" y cantidad_disponible: 1 (como en el ejemplo de respuesta anterior):
{ "items": [ { "carrito_item_id": "dcb9f237-32ea-4a95-ab07-62d51a59e9fc", "cantidad": 1 } ]}Podés incluir varios ítems en el mismo array, cada uno con su carrito_item_id y su cantidad.
Paso 9: Juntar todo y enviar (ENVÍO FINAL)
Sección titulada «Paso 9: Juntar todo y enviar (ENVÍO FINAL)»🚀 Ahora sí: enviamos todo junto
Sección titulada «🚀 Ahora sí: enviamos todo junto»Una vez que tenés preparados todos los objetos de los pasos anteriores (datos de emisión, chofer, transporte, vehículo, salida, destino e ítems), los juntás en un solo JSON y los enviás al endpoint de notas de remisión.
ℹ️ El campo
jsonDEviene enfalsepor defecto y la API te devuelve solo la estructura JSON de la respuesta. Si lo enviás entrue, además de emitir la nota de remisión, la respuesta incluye el XML del documento electrónico en formato JSON.
JSON completo de ejemplo
Sección titulada «JSON completo de ejemplo»{ "jsonDE": false, "datos_emision": { "numero_timbrado": "12345678", "punto_expedicion": "001", "numero_establecimiento": "001" }, "carrito_id": "a01aa396-dd43-48de-988f-2c07618ac33e", "motivo_codigo": 1, "responsable_emision": 1, "kilometros_estimados": 12, "transportista": { "tipo_persona": 1, "tipo_documento": 0, "documento": "12345678-9", "nombre": "Transportista Ejemplo", "nacionalidad": "PRY", "fecha_nacimiento": "11/09/2005", "whatsapp": "+595981234567", "direccion": "Dirección de transportista", "ciudad_id": "67ef2e9f-0fa7-43e7-ad5e-87a694e56341" }, "chofer": { "numero_documento": "1234567", "nombre": "Chofer Ejemplo", "domicilio_fiscal": "Dirección de chofer" }, "transporte": { "tipo": 1, "modalidad": 1, "responsable_costo_flete": 1, "codigo_condicion_negocio": "FOB", "fecha_inicio_traslado": "02/02/2026", "fecha_fin_traslado": "02/02/2026" }, "vehiculo": { "tipo_vehiculo": 1, "marca": "Vehículo Ejemplo", "tipo_identificacion": 2, "numero_matricula": "ABC123" }, "salida": { "direccion": "Dirección de salida", "ciudad_id": "67ef2e9f-0fa7-43e7-ad5e-87a694e56341", "whatsapp": "+595981234567" }, "destino": { "direccion": "Dirección de destino", "ciudad_id": "67ef2e9f-0fa7-43e7-ad5e-87a694e56341", "whatsapp": "+595981234567" }, "items": [ { "carrito_item_id": "dcb9f237-32ea-4a95-ab07-62d51a59e9fc", "cantidad": 1 } ]}Ejemplos de uso con curl
Sección titulada «Ejemplos de uso con curl»curl -X POST 'https://api.guarani.app/simplificado/notas/remision' \-H 'Content-Type: application/json' \-H 'x-api-key: Bearer <access_token>' \-d '{ "jsonDE": false, "datos_emision": { "numero_timbrado": "12345678", "punto_expedicion": "001", "numero_establecimiento": "001" }, "carrito_id": "a01aa396-dd43-48de-988f-2c07618ac33e", "motivo_codigo": 1, "responsable_emision": 1, "kilometros_estimados": 12, "transportista": { "tipo_persona": 1, "tipo_documento": 0, "documento": "12345678-9", "nombre": "Transportista Ejemplo", "nacionalidad": "PRY", "fecha_nacimiento": "11/09/2005", "whatsapp": "+595981234567", "email": "[email protected]", "direccion": "Dirección de transportista", "ciudad_id": "67ef2e9f-0fa7-43e7-ad5e-87a694e56341" }, "chofer": { "numero_documento": "1234567", "nombre": "Chofer Ejemplo", "domicilio_fiscal": "Dirección de chofer" }, "transporte": { "tipo": 1, "modalidad": 1, "responsable_costo_flete": 1, "codigo_condicion_negocio": "FOB", "fecha_inicio_traslado": "02/02/2026", "fecha_fin_traslado": "02/02/2026" }, "vehiculo": { "tipo_vehiculo": 1, "marca": "Vehículo Ejemplo", "tipo_identificacion": 2, "numero_matricula": "ABC123" }, "salida": { "direccion": "Dirección de salida", "ciudad_id": "67ef2e9f-0fa7-43e7-ad5e-87a694e56341", "whatsapp": "+595981234567" }, "destino": { "direccion": "Dirección de destino", "ciudad_id": "67ef2e9f-0fa7-43e7-ad5e-87a694e56341", "whatsapp": "+595981234567" }, "items": [ { "carrito_item_id": "dcb9f237-32ea-4a95-ab07-62d51a59e9fc", "cantidad": 1 } ]}' | jqNota: Reemplazá
<access_token>por tu token JWT válido.
Ejemplo de respuesta del backend
Sección titulada «Ejemplo de respuesta del backend»{ "success": true, "codigo": "200", "message": "Operación realizada correctamente.", "data": { "numero_timbrado": "12345678", "numero_documento": "001-001-0000001", "serie": "AA", "cdc": "018015804040010020000182120251028149230824767", "estado_sifen": { "estado": "Aprobado", "mensaje": "Autorización del DE satisfactoria" }, "xml": "https://api.guarani.app/sifen/xml/018015804040010020000182120251028149230824767", "qr": "https://ekuatia.set.gov.py/consultas-test/qr?nVersion=150&Id=018015804040010020000182120251028149230824767&dFeEmiDE=323032352d31302d32385430383a31383a3139&dRucRec=362889&dTotGralOpe=200000.00000000&dTotIVA=18181.81818182&cItems=2&DigestValue=724a4b68652f6635616934566442357036797070704b504b66736c514370696f554a2f3374676674484b453d&IdCSC=0001&cHashQR=90832ec96b3a6f8cd667640386206708099adf9af74bdea2116d30099897fecda" }}Una vez emitido el documento electrónico, esperá 10 minutos y luego consulta el estado del documento electrónico.
Ejemplo de consulta de estado de un documento electrónico
Sección titulada «Ejemplo de consulta de estado de un documento electrónico»curl -X GET "https://api.guarani.app/sifen/consultas/estado/cdc/{cdc}" \ -H "x-api-key: Bearer <access_token>" \ -H "Accept: application/json" | jqNota: Reemplaza
{cdc}por el CDC a consultar y<access_token>con un token JWT válido proporcionado por el equipo Guarani.
Respuestas de estado del CDC
Sección titulada «Respuestas de estado del CDC»Ejemplo de respuesta de estado aprobado
Sección titulada «Ejemplo de respuesta de estado aprobado»{ "success": true, "codigo": "200", "message": "Operación realizada correctamente.", "data": { "estado": "Aprobado", "mensaje": "Aprobado" }}Ejemplo de respuesta de estado rechazado
Sección titulada «Ejemplo de respuesta de estado rechazado»{ "success": false, "codigo": "400", "mensaje": "Error al consultar el CDC.", "error": { "estado": "Rechazado", "mensaje": "Motivo del rechazo" }}Ejemplo de respuesta de estado pendiente
Sección titulada «Ejemplo de respuesta de estado pendiente»{ "success": true, "codigo": "200", "message": "Operación realizada correctamente.", "data": { "estado": "Pendiente", "mensaje": "Pendiente" }}Resumen de todo el proceso
Sección titulada «Resumen de todo el proceso»Resumen de lo que hicimos:
1. Consultar el timbrado
Sección titulada «1. Consultar el timbrado»- ✅ Llamar a
GET /timbradospara obtenernumero_timbrado,numero_establecimientoypunto_expedicion
2. Consultar ítems disponibles
Sección titulada «2. Consultar ítems disponibles»- ✅ Llamar a
GET /notas/remision/carrito/{carrito_id}/items-pendientes - ✅ Obtener los
id(carrito_item_id) ycantidad_disponiblede cada ítem
3. Construcción (Preparar cada parte del body)
Sección titulada «3. Construcción (Preparar cada parte del body)»- ✅ Construir
datos_emision,carrito_id, motivo, transportista, etc. - ✅ Construir el objeto
chofer - ✅ Construir el objeto
transporteyvehiculo - ✅ Construir
salidaydestino(con ciudad_id) - ✅ Construir el array
itemsconcarrito_item_idycantidad
4. Envío final (Una sola llamada)
Sección titulada «4. Envío final (Una sola llamada)»- ✅ Juntar todo en un solo JSON
- ✅ Enviar al endpoint
POST /simplificado/notas/remision
¿Dónde encontrar más información?
Sección titulada «¿Dónde encontrar más información?»- Si algo sale mal: (ver
Tabla de errores) - Tablas de referencia (códigos usados en este tutorial):
- Tipos de documentos —
tipo_documentodel transportista - Tipos de personas —
tipo_personadel transportista - Motivo código de la nota de remisión —
motivo_codigo - Responsable de emisión de la nota de remisión —
responsable_emision - Tipo de transporte —
transporte.tipo - Modalidad de transporte —
transporte.modalidad - Responsable costo flete —
transporte.responsable_costo_flete - Códigos de las condiciones de negocio —
transporte.codigo_condicion_negocio - Tipos de vehiculos —
vehiculo.tipo_vehiculo - Tipo de identificación del vehiculo —
vehiculo.tipo_identificacion - Tablas de referencia (índice completo)
- Tipos de documentos —
Consejos que te van a ayudar
Sección titulada «Consejos que te van a ayudar»- Consultá primero el timbrado y los ítems pendientes del carrito para usar
carrito_item_idy cantidades correctas - No superes
cantidad_disponiblede cada ítem al armar el arrayitems - Revisá el formato de las fechas (DD/MM/YYYY) y teléfonos (+595xxxxxxxxx)
- Tené a mano el
ciudad_idpara salida y destino (consultaGET /ciudadessi hace falta) - Si tenés dudas, revisá la documentación de cada endpoint y las tablas de referencia (ver también la lista en «¿Dónde encontrar más información?»)