Saltearse al contenido

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.

URL Base: https://api.guarani.app

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:

  1. Consultar el timbrado (autorización de la SET)
  2. Consultar los ítems disponibles del carrito (qué ítems pueden incluirse en la remisión)
  3. Construir los datos de la remisión (emisión, chofer, transporte, vehículo, salida, destino, ítems)
  4. 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.


¿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

Hacé una consulta al endpoint de timbrados:

Ventana de terminal
curl -X GET "https://api.guarani.app/timbrados?page=1&limit=100" \
-H "x-api-key: Bearer <access_token>" \
-H "Accept: application/json" | jq

Nota: 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.


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.

Ventana de terminal
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>' | jq

Nota: Reemplazá <access_token> y {carrito_id} por tu token JWT válido y el ID del carrito respectivamente.

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 del timbrado y punto de expedición con los que se emite la nota de remisión.

CampoTipoRequeridoDescripción
numero_timbradostringNúmero de timbrado.
punto_expedicionstringPunto de expedición.
numero_establecimientostringNúmero de establecimiento.
CampoTipoRequeridoDescripción
carrito_idstringID del carrito (el mismo que usaste en Paso 1).
motivo_codigonumberCódigo del motivo del traslado (ver Motivo código).
responsable_emisionnumberQuién es responsable de la emisión (ver Responsable de emisión).
kilometros_estimadosnumberKilómetros estimados del traslado.
transportistaobjectObjeto con los datos del transportista.
CampoTipoRequeridoDescripción
tipo_personanumberTipo de persona (ver Tipos de personas).
tipo_documentonumberTipo de documento (ver Tipos de documentos).
documentostringNúmero de documento.
nombrestringNombre completo.
nacionalidadstringNacionalidad.
fecha_nacimientostringFecha de nacimiento.
whatsappstringWhatsApp.
emailstringEmail.
direccionstringDirección.
ciudad_idstringID 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",
"email": "[email protected]",
"direccion": "Dirección de transportista",
"ciudad_id": "67ef2e9f-0fa7-43e7-ad5e-87a694e56341"
}
}

Datos del chofer que realiza el traslado.

CampoTipoRequeridoDescripción
numero_documentostringNúmero de documento (CI u otro).
nombrestringNombre completo del chofer.
domicilio_fiscalstringDomicilio fiscal del chofer.
{
"chofer": {
"numero_documento": "1234567",
"nombre": "Chofer Ejemplo",
"domicilio_fiscal": "Dirección de chofer"
}
}

Datos del tipo de transporte, modalidad, responsable del flete y fechas del traslado.

CampoTipoRequeridoDescripción
tiponumberTipo de transporte (ver Tipo de transporte).
modalidadnumberModalidad del transporte (ver Modalidad de transporte).
responsable_costo_fletenumberQuién asume el costo del flete (ver Responsable costo flete).
codigo_condicion_negociostringCódigo de la condición de negocio (ver Códigos de las condiciones de negocio).
fecha_inicio_trasladostringFecha de inicio (formato DD/MM/YYYY).
fecha_fin_trasladostringFecha de fin (formato DD/MM/YYYY).
{
"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"
}
}

Datos del vehículo utilizado en el traslado.

CampoTipoRequeridoDescripción
tipo_vehiculonumberTipo de vehículo (ver tablas).
marcastringMarca del vehículo.
tipo_identificacionnumberTipo de identificación (ej. matrícula).
numero_matriculastringNúmero de matrícula u otro identificador.
{
"vehiculo": {
"tipo_vehiculo": 1,
"marca": "Vehículo Ejemplo",
"tipo_identificacion": 2,
"numero_matricula": "ABC123"
}
}

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).

CampoTipoRequeridoDescripción
direccionstringDirección de salida.
ciudad_idstringUUID de la ciudad de salida.
whatsappstringWhatsApp de contacto (ej. +595981234567).
numero_casastringNoNúmero de casa (opcional).
direccion_complementariastringNoDirección complementaria (opcional).
direccion_complementaria_2stringNoSegunda dirección complementaria (opcional).
CampoTipoRequeridoDescripción
direccionstringDirección de destino.
ciudad_idstringUUID de la ciudad de destino.
whatsappstringWhatsApp de contacto.
numero_casastringNoNúmero de casa (opcional).
direccion_complementariastringNoDirección complementaria (opcional).
direccion_complementaria_2stringNoSegunda dirección complementaria (opcional).

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"
}
}

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:

CampoTipoRequeridoDescripción
carrito_item_idstringEl id del ítem en la respuesta de items pendientes.
cantidadnumberCantidad a remitir (≤ cantidad_disponible del ítem).

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.


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 jsonDE viene en false por defecto y la API te devuelve solo la estructura JSON de la respuesta. Si lo enviás en true, además de emitir la nota de remisión, la respuesta incluye el XML del documento electrónico en formato JSON.

{
"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
}
]
}
Ventana de terminal
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
}
]
}' | jq

Nota: Reemplazá <access_token> por tu token JWT válido.


{
"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»
Ventana de terminal
curl -X GET "https://api.guarani.app/sifen/consultas/estado/cdc/{cdc}" \
-H "x-api-key: Bearer <access_token>" \
-H "Accept: application/json" | jq

Nota: Reemplaza {cdc} por el CDC a consultar y <access_token> con un token JWT válido proporcionado por el equipo Guarani.

{
"success": true,
"codigo": "200",
"message": "Operación realizada correctamente.",
"data": {
"estado": "Aprobado",
"mensaje": "Aprobado"
}
}
{
"success": false,
"codigo": "400",
"mensaje": "Error al consultar el CDC.",
"error": {
"estado": "Rechazado",
"mensaje": "Motivo del rechazo"
}
}
{
"success": true,
"codigo": "200",
"message": "Operación realizada correctamente.",
"data": {
"estado": "Pendiente",
"mensaje": "Pendiente"
}
}

Resumen de lo que hicimos:

  • ✅ Llamar a GET /timbrados para obtener numero_timbrado, numero_establecimiento y punto_expedicion
  • ✅ Llamar a GET /notas/remision/carrito/{carrito_id}/items-pendientes
  • ✅ Obtener los id (carrito_item_id) y cantidad_disponible de 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 transporte y vehiculo
  • ✅ Construir salida y destino (con ciudad_id)
  • ✅ Construir el array items con carrito_item_id y cantidad
  • ✅ Juntar todo en un solo JSON
  • ✅ Enviar al endpoint POST /simplificado/notas/remision


  1. Consultá primero el timbrado y los ítems pendientes del carrito para usar carrito_item_id y cantidades correctas
  2. No superes cantidad_disponible de cada ítem al armar el array items
  3. Revisá el formato de las fechas (DD/MM/YYYY) y teléfonos (+595xxxxxxxxx)
  4. Tené a mano el ciudad_id para salida y destino (consulta GET /ciudades si hace falta)
  5. 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?»)