Skip to content

Invoicing in Bolivia with CUCU

This guide takes you from the credential to a complete sale → invoice → customer PDF flow using the cucu* nodes. If you prefer to talk directly to the SIN, see the Bolivia page.

  1. Create your CUCU account and generate an API key. It starts with sk_test_ (sandbox) or sk_live_ (production).
  2. In Floogos create a Bolivia CUCU credential and paste the key. The environment is set by the key prefix: if the credential’s Environment field contradicts it, the node stops without sending anything.
  3. Click Test credential. If it answers correctly you can use it in any cucu* node.
  4. Optional: set the default point of sale and the webhook secret (webhook_secret) if you will receive events.

Minimal flow: Webhook / Form → cucuEmitirFactura → cucuDocumento.

In cucuEmitirFactura:

FieldExample value
document_sector1 (purchase and sale)
client_document_number{{customer_nit}}
client_business_name{{business_name}}
details[{"description":"Development service","quantity":1,"priceUnit":500}]
default_activity_economic620100 (your CAEB)
default_code_product_sin83141
default_unit_measure58 (service)
idempotency_modeauto
output_keycucu

The node validates the data before calling the API and, if everything is correct, returns in data.cucu:

  • invoice.cuf, invoice.invoiceNumber and invoice.state (VALIDATED once the SIN accepted it).
  • urls.pdf, urls.xml and urls.verify (public verification link).
  • totals_check: compares the total you expected with the one the SIAT calculated.
  • replayed: true if it was a retry and CUCU returned the invoice already issued.

To send the PDF, add cucuDocumento with operation: email and cuf: {{data.cucu.invoice.cuf}}, or use download to get the file and attach it through another channel. You can also fill client_email on the issue and CUCU emails the invoice to the customer.

Case 2: use the official name from the registry

Section titled “Case 2: use the official name from the registry”

If the customer only gives a NIT, validate before issuing so the business name matches the registry:

  1. cucuValidarCliente with operation: padron, document_type: 5, document_number: {{customer_nit}} and output_key: cliente.
  2. In cucuEmitirFactura, use client_business_name: {{data.cliente.business_name}}.

Case 3: never duplicate invoices on retries

Section titled “Case 3: never duplicate invoices on retries”

Every issue carries an Idempotency-Key header:

  • auto (recommended): the key is computed from the execution, the node and the invoice content. If the workflow retries after a network cut, CUCU returns the invoice already issued (replayed: true).
  • manual: you write the key, for example the order id ({{order_id}}). Use it inside a loop, where two invoices can be identical.
  • off: no key. A timeout or a 5xx error is not retried, because it could duplicate the invoice. Only a 429 (rate limit) is retried.

Use cucuNotaCreditoDebito:

  • cuf: the original invoice.
  • nota_type: CREDITO or DEBITO.
  • document_sector: 24 for the credit/debit note.
  • returned_details: only the returned lines.
  • precheck: true checks the figures before sending to the SIAT.

cucuAnular with the invoice cuf and a motivo from the SIAT cancellation-reasons catalog (look it up with cucuCatalogo).

Always keep the two steps (issue and query) separate in the workflow and store what was issued so you retry only what is pending. More patterns in Bulk issuing.

With cucuContingencia you register the contingency event, issue in offline mode and send the package when the SIN is back. Events 5, 6 and 7 require a CAFC, requested from the SIN. cucuCufd lets you check or renew the point of sale’s CUFD.

  1. Create a workflow with a Webhook trigger and register its URL in CUCU (you can also do it with cucuWebhooks). Store the webhook secret in the credential.
  2. As the first node, add cucuVerificarWebhook: with no configuration it uses the original headers and body of the received request and checks the signature (Standard Webhooks).
  3. Continue only if the signature is valid. With tolerance_seconds you can reject events that are too old (0 = do not check).
SymptomCause and fix
The node stops without sendingThe key (sk_test_/sk_live_) contradicts the credential’s environment. Fix one of the two.
SIAT rejects the totalsCheck totals_check and additional_discount: the SIAT validates total = Σ subtotals − additional discount.
Sector fields missingEach sector requires its own data in sector_fields (rental, utilities, hospital…). The node message says which ones are missing.
Sectors 3 and 9CUCU’s documentation marks them as sandbox only.

cucuEmitirFactura · cucuDocumento · cucuValidarCliente · cucuNotaCreditoDebito · cucuAnular · cucuEmitirLote · cucuEmisionMasiva · cucuConsultar · cucuContingencia · cucuCufd · cucuCatalogo · cucuAdministrar · cucuWebhooks · cucuVerificarWebhook