Skip to main content
POST
/
api
/
v1
/
invoices
/
{id}
/
credit-note
curl -X POST "https://sandbox.cucu.bo/api/v1/invoices/a1b2c3d4-e5f6-7890-abcd-ef1234567890/credit-note" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "pointOfSaleId": "660e8400-e29b-41d4-a716-446655440004",
    "notaType": "CREDITO",
    "paymentMethodCode": 1,
    "returnedDetails": [
      {
        "activityEconomic": "620100",
        "codeProductSin": "83141",
        "description": "Devolucion parcial - Servicio de software",
        "quantity": 1,
        "unitMeasure": 58,
        "priceUnit": 200.00
      }
    ]
  }'
const response = await fetch(
  'https://sandbox.cucu.bo/api/v1/invoices/a1b2c3d4-e5f6-7890-abcd-ef1234567890/credit-note',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      pointOfSaleId: '660e8400-e29b-41d4-a716-446655440004',
      notaType: 'CREDITO',
      paymentMethodCode: 1,
      returnedDetails: [{
        activityEconomic: '620100',
        codeProductSin: '83141',
        description: 'Devolucion parcial - Servicio de software',
        quantity: 1,
        unitMeasure: 58,
        priceUnit: 200.00
      }]
    })
  }
);
const data = await response.json();
import requests

response = requests.post(
    'https://sandbox.cucu.bo/api/v1/invoices/a1b2c3d4-e5f6-7890-abcd-ef1234567890/credit-note',
    headers={
        'Content-Type': 'application/json',
        'X-API-Key': 'YOUR_API_KEY'
    },
    json={
        'pointOfSaleId': '660e8400-e29b-41d4-a716-446655440004',
        'notaType': 'CREDITO',
        'paymentMethodCode': 1,
        'returnedDetails': [{
            'activityEconomic': '620100',
            'codeProductSin': '83141',
            'description': 'Devolucion parcial - Servicio de software',
            'quantity': 1,
            'unitMeasure': 58,
            'priceUnit': 200.00
        }]
    }
)
print(response.json())
{
  "success": true,
  "message": "Nota creada exitosamente",
  "data": {
    "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
    "invoiceNumber": 10,
    "cuf": "3983G8305613443F748GCBGCD4765FB93313BE59F1A7AF25FCFC9BG85",
    "state": "VALIDATED",
    "clientBusinessName": "EMPRESA DEMO S.R.L.",
    "amountTotal": 200.00,
    "emissionDate": "2026-02-22T10:30:00",
    "pdfUrl": "https://sandbox.cucu.bo/api/v1/public/invoice/3983G...G85/pdf",
    "xmlUrl": "https://sandbox.cucu.bo/api/v1/public/invoice/3983G...G85/xml"
  },
  "timestamp": "2026-02-22T10:30:00"
}
{
  "success": false,
  "error": {
    "code": "BAD_REQUEST",
    "details": "La factura original no tiene detalles suficientes para la devolucion solicitada"
  },
  "timestamp": "2026-02-22T10:30:00"
}
{
  "success": false,
  "error": {
    "code": "CONFLICT",
    "details": "La factura original no esta en estado VALIDATED"
  },
  "timestamp": "2026-02-22T10:30:00"
}
Crea y emite una Nota de Credito o Debito contra una factura original validada por el SIAT. La nota permite ajustar montos por devoluciones parciales o totales.
La factura original debe estar en estado VALIDATED. No se puede emitir una nota contra facturas rechazadas, anuladas o pendientes.

Path Parameters

ParametroTipoReqDescripcion
idUUIDSiUUID de la factura original contra la que se emite la nota

Headers

ParametroTipoReqDescripcion
X-API-KeystringSiTu API Key
Content-TypestringSiapplication/json

Request Body

CampoTipoReqDescripcion
pointOfSaleIdUUIDSiUUID del punto de venta registrado en SIAT
notaTypestringSiTipo de nota: CREDITO o DEBITO
documentSectorTypeintegerNoSector de la nota: 24 (estandar, default), 47 (Nota Descuento) o 48 (Nota ICE). Ver Notas Descuento e ICE
paymentMethodCodeintegerSiCodigo de metodo de pago (1-308). 1 = Efectivo
cardNumberstringNoNumero de tarjeta. Se ofusca automaticamente antes de guardar y emitir (ver nota de seguridad)
observationsstringNoObservaciones (max 500 caracteres)
isTicketbooleanNotrue para generar ticket 80mm ademas de A4
returnedDetailsarraySiItems devueltos/ajustados (minimo 1)
originalDetailsarrayNoSolo sector 48 (ICE): overlay de datos ICE por linea original. En sectores 24/47 se ignora. Ver Notas Descuento e ICE

returnedDetails[]

CampoTipoReqDescripcion
activityEconomicstringSiCodigo de actividad economica CAEB
codeProductSinstringSiCodigo de producto/servicio del catalogo SIN
codeProductstringNoCodigo interno del producto
descriptionstringSiDescripcion del producto o servicio devuelto (max 500)
quantitynumberSiCantidad devuelta (mayor a 0)
unitMeasureintegerSiUnidad de medida SIN. 58 = Servicio, 1 = Unidad
priceUnitnumberSiPrecio unitario en bolivianos (mayor a 0)
amountDiscountnumberNoDescuento aplicado al item (default 0)
serialNumberstringNoNumero de serie (si aplica)
imeiNumberstringNoNumero IMEI (si aplica)
curl -X POST "https://sandbox.cucu.bo/api/v1/invoices/a1b2c3d4-e5f6-7890-abcd-ef1234567890/credit-note" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "pointOfSaleId": "660e8400-e29b-41d4-a716-446655440004",
    "notaType": "CREDITO",
    "paymentMethodCode": 1,
    "returnedDetails": [
      {
        "activityEconomic": "620100",
        "codeProductSin": "83141",
        "description": "Devolucion parcial - Servicio de software",
        "quantity": 1,
        "unitMeasure": 58,
        "priceUnit": 200.00
      }
    ]
  }'
const response = await fetch(
  'https://sandbox.cucu.bo/api/v1/invoices/a1b2c3d4-e5f6-7890-abcd-ef1234567890/credit-note',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      pointOfSaleId: '660e8400-e29b-41d4-a716-446655440004',
      notaType: 'CREDITO',
      paymentMethodCode: 1,
      returnedDetails: [{
        activityEconomic: '620100',
        codeProductSin: '83141',
        description: 'Devolucion parcial - Servicio de software',
        quantity: 1,
        unitMeasure: 58,
        priceUnit: 200.00
      }]
    })
  }
);
const data = await response.json();
import requests

response = requests.post(
    'https://sandbox.cucu.bo/api/v1/invoices/a1b2c3d4-e5f6-7890-abcd-ef1234567890/credit-note',
    headers={
        'Content-Type': 'application/json',
        'X-API-Key': 'YOUR_API_KEY'
    },
    json={
        'pointOfSaleId': '660e8400-e29b-41d4-a716-446655440004',
        'notaType': 'CREDITO',
        'paymentMethodCode': 1,
        'returnedDetails': [{
            'activityEconomic': '620100',
            'codeProductSin': '83141',
            'description': 'Devolucion parcial - Servicio de software',
            'quantity': 1,
            'unitMeasure': 58,
            'priceUnit': 200.00
        }]
    }
)
print(response.json())
{
  "success": true,
  "message": "Nota creada exitosamente",
  "data": {
    "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
    "invoiceNumber": 10,
    "cuf": "3983G8305613443F748GCBGCD4765FB93313BE59F1A7AF25FCFC9BG85",
    "state": "VALIDATED",
    "clientBusinessName": "EMPRESA DEMO S.R.L.",
    "amountTotal": 200.00,
    "emissionDate": "2026-02-22T10:30:00",
    "pdfUrl": "https://sandbox.cucu.bo/api/v1/public/invoice/3983G...G85/pdf",
    "xmlUrl": "https://sandbox.cucu.bo/api/v1/public/invoice/3983G...G85/xml"
  },
  "timestamp": "2026-02-22T10:30:00"
}
{
  "success": false,
  "error": {
    "code": "BAD_REQUEST",
    "details": "La factura original no tiene detalles suficientes para la devolucion solicitada"
  },
  "timestamp": "2026-02-22T10:30:00"
}
{
  "success": false,
  "error": {
    "code": "CONFLICT",
    "details": "La factura original no esta en estado VALIDATED"
  },
  "timestamp": "2026-02-22T10:30:00"
}

Notas Descuento e ICE (sectores 47 y 48)

Ademas de la nota estandar (24), el campo documentSectorType permite emitir dos variantes especializadas:
SectorTipoCuando usarlo
24Nota Credito-Debito estandarDefault. Devoluciones/ajustes normales
47Nota Credito-Debito DescuentoLa factura original tenia descuento adicional prorrateado por item
48Nota Credito-Debito ICELa factura original tenia productos con Impuesto al Consumo Especifico (ICE)
No re-envies las lineas de la factura original. En los tres sectores, las lineas originales (codigoDetalleTransaccion=1) se clonan automaticamente desde la base de datos — espejan exacto la factura registrada en SIAT. Enviar tus propias lineas originales causaba rechazos SIAT [1049] (detalle diferente) y [1030] (monto original erroneo). Ahora solo mandas los items devueltos en returnedDetails.

Sector 47 — solo returnedDetails

Identico al 24 a nivel de request: mandas unicamente returnedDetails. El campo originalDetails, si viene, se ignora.

Sector 48 — returnedDetails + overlay ICE

La compra-venta original no almacena los montos ICE, asi que en el sector 48 esos numeros si vienen del request, en originalDetails, como un overlay minimal matcheado por nroItem. La base (actividad/producto/descripcion/cantidad/precio) se toma de la BD; en originalDetails solo importan los campos ICE:
CampoTipoDescripcion
nroItemintegerlineNumber de la linea original a la que aplica el overlay (lo obtienes de GET /invoices/{id}details[].lineNumber)
marcaIceinteger1 = considera ICE, 2 = no considera ICE. Obligatorio
montoIceEspecificonumberMonto ICE especifico de la linea (opcional)
montoIcePorcentualnumberMonto ICE porcentual de la linea (opcional)
En sectores 47/48, cada returnedDetails[].nroItem tambien referencia el lineNumber de la linea original que se devuelve (para el prorrateo del descuento). Consulta los numeros de linea de la factura original con GET /api/v1/invoices/{id}details[].lineNumber.
Ejemplo originalDetails (sector 48)
"originalDetails": [
  { "nroItem": 1, "marcaIce": 2, "montoIceEspecifico": 0, "montoIcePorcentual": 0 }
]
Modo estructural: si la factura original no tenia ICE, envia marcaIce: 2 con montos en 0. La nota se emite con la estructura ICE requerida por el XSD del sector 48 pero sin monto ICE real.

Comportamiento

  1. El sistema obtiene automaticamente los datos de la factura original (cliente, CUF, montos)
  2. Los returnedDetails se marcan con codigoDetalleTransaccion=2 (devolucion)
  3. Los items originales se clonan desde la base de datos con codigoDetalleTransaccion=1 (nunca del request)
  4. Se calcula: montoTotalOriginal, montoTotalDevuelto, montoDescuentoCreditoDebito, montoEfectivoCreditoDebito
  5. La nota se envia al SIAT via el WSDL de documento de ajuste (sector 24/47/48 segun documentSectorType)
  6. Se genera PDF (A4 + ticket opcional), XML y se envia email al cliente
Si la factura original tiene items con montoGiftCard > 0, el paymentMethodCode debe incluir el codigo 27 (Gift Card). Error SIAT 1050 si se omite.
La nota genera su propio CUF unico. Puedes acceder a ella via /f/{cuf} o los endpoints publicos, igual que una factura regular.
Seguridad — ofuscacion de tarjeta. Si envias cardNumber, la API conserva solo los 4 primeros y 4 ultimos digitos y reemplaza el resto por ceros antes de persistir y emitir el XML SIAT (ej: 41111111111111114111000000001111). El numero completo (PAN) nunca se guarda en la base de datos ni viaja al SIAT. Numeros de 8 digitos o menos se dejan tal cual.