Overview
The go-siat SDK uses a fluent builder pattern to construct invoices safely and efficiently. The builder pattern ensures:
Type safety with opaque interfaces
Prevention of direct manipulation of internal structures
Clear, readable invoice construction code
Compile-time validation of required fields
Invoice Structure
A complete invoice consists of three main components:
Factura - The root invoice container
Cabecera - The header with issuer, customer, and transaction details
Detalle - Individual line items (products/services)
FacturaCompraVenta (Invoice)
├── Cabecera (Header)
│ ├── Issuer information
│ ├── Customer information
│ └── Transaction totals
└── Detalle[] (Line Items)
├── Product/service details
├── Quantities and prices
└── Subtotals
Building an Invoice
The header contains issuer, customer, and transaction information:
cabecera := models . CompraVenta . NewCabecera ().
// Issuer information
WithNitEmisor ( 123456789 ).
WithRazonSocialEmisor ( "Mi Empresa S.A." ).
WithMunicipio ( "La Paz" ).
WithDireccion ( "Av. Principal 123" ).
WithTelefono ( "+591 2 1234567" ).
// Invoice identification
WithNumeroFactura ( 1 ).
WithCuf ( "GENERATED_CUF" ).
WithCufd ( "DAILY_CUFD" ).
WithCodigoSucursal ( 0 ).
WithCodigoPuntoVenta ( 0 ).
WithFechaEmision ( "2024-01-15T14:30:00.000" ).
// Customer information
WithNombreRazonSocial ( "JUAN PEREZ" ).
WithCodigoTipoDocumentoIdentidad ( 1 ).
WithNumeroDocumento ( "5544332" ).
WithComplemento ( "1A" ).
WithCodigoCliente ( "CLI-001" ).
// Payment information
WithCodigoMetodoPago ( 1 ).
WithMontoTotal ( 100.0 ).
WithMontoTotalSujetoIva ( 100.0 ).
WithCodigoMoneda ( 1 ).
WithTipoCambio ( 1.0 ).
WithMontoTotalMoneda ( 100.0 ).
// Additional fields
WithLeyenda ( "Ley N° 453: El proveedor deberá suministrar el servicio..." ).
WithUsuario ( "admin" ).
WithCodigoDocumentoSector ( 1 ).
Build ()
2. Create Detalle (Line Items)
Add one or more line items describing the products or services:
detalle1 := models . CompraVenta . NewDetalle ().
WithActividadEconomica ( "461000" ).
WithCodigoProductoSin ( "12345" ).
WithCodigoProducto ( "PROD-001" ).
WithDescripcion ( "Producto de prueba" ).
WithCantidad ( 2.0 ).
WithUnidadMedida ( 57 ).
WithPrecioUnitario ( 50.0 ).
WithSubTotal ( 100.0 ).
Build ()
detalle2 := models . CompraVenta . NewDetalle ().
WithActividadEconomica ( "461000" ).
WithCodigoProductoSin ( "67890" ).
WithCodigoProducto ( "PROD-002" ).
WithDescripcion ( "Servicio adicional" ).
WithCantidad ( 1.0 ).
WithUnidadMedida ( 62 ).
WithPrecioUnitario ( 25.0 ).
WithMontoDescuento ( 5.0 ).
WithSubTotal ( 20.0 ).
Build ()
3. Assemble the Invoice
Combine the header and line items into a complete invoice:
factura := models . CompraVenta . NewFactura ().
WithCabecera ( cabecera ).
AddDetalle ( detalle1 ).
AddDetalle ( detalle2 ).
Build ()
Cabecera Builder Methods
Complete reference for all CabeceraBuilder methods:
Tax identification number (NIT) of the issuing company
Legal name of the issuing company
Municipality where the issuer is located (e.g., “La Paz”, “Santa Cruz”)
Physical address of the issuer
Contact phone number (optional)
Invoice Identification
Sequential invoice number
CUF (Código Único de Factura) - unique invoice code generated using models.CompraVenta.GenerarCUF()
CUFD (Código Único de Factura Diario) - daily invoice code
Branch/office code registered in SIAT
Emission date and time in format: "2006-01-02T15:04:05.000"
WithCodigoDocumentoSector
Document sector type code from SIAT catalogs
Customer’s name or legal name (optional)
WithCodigoTipoDocumentoIdentidad
Document type code:
1 = CI (Cédula de Identidad)
2 = CEX (Cédula de Extranjero)
3 = Pasaporte
4 = NIT
5 = Otro
Customer’s document number
Document complement (e.g., “1A”) - optional
Internal customer code in your system
Payment method code:
1 = Efectivo
2 = Tarjeta
3 = Cheque
4 = Otro
Card number (last 4 digits) - required if payment method is card
Total invoice amount including taxes
Total amount subject to VAT
Currency code:
1 = Boliviano (BOB)
2 = Dólar (USD)
3 = Euro (EUR)
Exchange rate (use 1.0 for BOB)
Total amount in the specified currency
Gift card amount applied (optional)
Additional discount amount (optional)
Additional Fields
Legal legend text (e.g., “Ley N° 453: El proveedor deberá suministrar el servicio…”)
Username of the person issuing the invoice
Exception code for offline invoicing (optional)
CAFC code for offline contingency mode (optional)
Detalle Builder Methods
Complete reference for all DetalleBuilder methods:
Economic activity code associated with the product/service
SIN product code from SIAT catalogs
Internal product code in your system
Product or service description
Unit of measure code from SIAT catalogs:
57 = Unidad
58 = Kilogramo
59 = Metro
62 = Servicio
(see SIAT catalogs for complete list)
Unit price of the product/service
Line item subtotal (quantity × unit price - discount)
Discount amount applied to this line item (optional)
Serial number for serialized products (optional)
IMEI number for mobile devices (optional)
Complete Example
Here’s a complete example building an invoice with multiple line items:
package main
import (
" encoding/xml "
" fmt "
" log "
" time "
" github.com/ron86i/go-siat/pkg/models "
)
func main () {
// Generate CUF
nit := int64 ( 123456789 )
fechaEmision := time . Now ()
cuf , err := models . CompraVenta . GenerarCUF (
nit , fechaEmision , 0 , 1 , 1 , 1 , 1 , 1 , 0 , "XYZ789" ,
)
if err != nil {
log . Fatal ( err )
}
// Build header
cabecera := models . CompraVenta . NewCabecera ().
WithNitEmisor ( nit ).
WithRazonSocialEmisor ( "ACME Corporation S.A." ).
WithMunicipio ( "La Paz" ).
WithDireccion ( "Av. 16 de Julio #1234" ).
WithTelefono ( "+591 2 1234567" ).
WithNumeroFactura ( 1001 ).
WithCuf ( cuf ).
WithCufd ( "CUFD123456789" ).
WithCodigoSucursal ( 0 ).
WithCodigoPuntoVenta ( 0 ).
WithFechaEmision ( fechaEmision . Format ( "2006-01-02T15:04:05.000" )).
WithNombreRazonSocial ( "Juan Pérez" ).
WithCodigoTipoDocumentoIdentidad ( 1 ).
WithNumeroDocumento ( "12345678" ).
WithComplemento ( "1A" ).
WithCodigoCliente ( "CUST-001" ).
WithCodigoMetodoPago ( 1 ).
WithMontoTotal ( 250.0 ).
WithMontoTotalSujetoIva ( 250.0 ).
WithCodigoMoneda ( 1 ).
WithTipoCambio ( 1.0 ).
WithMontoTotalMoneda ( 250.0 ).
WithLeyenda ( "Ley N° 453: El proveedor deberá suministrar el servicio..." ).
WithUsuario ( "admin" ).
WithCodigoDocumentoSector ( 1 ).
Build ()
// Build line items
detalle1 := models . CompraVenta . NewDetalle ().
WithActividadEconomica ( "461000" ).
WithCodigoProductoSin ( "12345" ).
WithCodigoProducto ( "LAPTOP-001" ).
WithDescripcion ( "Laptop Dell Inspiron 15" ).
WithCantidad ( 1.0 ).
WithUnidadMedida ( 57 ).
WithPrecioUnitario ( 200.0 ).
WithSubTotal ( 200.0 ).
WithNumeroSerie ( "SN123456789" ).
Build ()
detalle2 := models . CompraVenta . NewDetalle ().
WithActividadEconomica ( "461000" ).
WithCodigoProductoSin ( "67890" ).
WithCodigoProducto ( "MOUSE-001" ).
WithDescripcion ( "Mouse inalámbrico" ).
WithCantidad ( 2.0 ).
WithUnidadMedida ( 57 ).
WithPrecioUnitario ( 30.0 ).
WithMontoDescuento ( 10.0 ).
WithSubTotal ( 50.0 ).
Build ()
// Assemble invoice
factura := models . CompraVenta . NewFactura ().
WithCabecera ( cabecera ).
AddDetalle ( detalle1 ).
AddDetalle ( detalle2 ).
Build ()
// Marshal to XML
xmlData , err := xml . MarshalIndent ( factura , "" , " " )
if err != nil {
log . Fatal ( err )
}
fmt . Println ( string ( xmlData ))
}
Working with Optional Fields
Some fields use the Nilable[T] type internally to support SIAT’s requirement for explicit nil values. The builders handle this automatically:
// Optional string field
cabecera := models . CompraVenta . NewCabecera ().
WithTelefono ( "+591 2 1234567" ). // Sets value
// ... other fields
Build ()
// Optional numeric field
detalle := models . CompraVenta . NewDetalle ().
WithMontoDescuento ( 15.5 ). // Sets value
// ... other fields
Build ()
// Omitting optional fields is fine - they will be nil in the XML
detalle := models . CompraVenta . NewDetalle ().
// No WithMontoDescuento() call
// ... other fields
Build ()
XML Output
The built invoice marshals to XML compatible with SIAT’s XSD schema:
< facturaElectronicaCompraVenta
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation = "facturaElectronicaCompraVenta.xsd" >
< cabecera >
< nitEmisor > 123456789 </ nitEmisor >
< razonSocialEmisor > Mi Empresa S.A. </ razonSocialEmisor >
< municipio > La Paz </ municipio >
< telefono > +591 2 1234567 </ telefono >
<!-- ... more fields ... -->
</ cabecera >
< detalle >
< actividadEconomica > 461000 </ actividadEconomica >
< codigoProductoSin > 12345 </ codigoProductoSin >
<!-- ... more fields ... -->
</ detalle >
</ facturaElectronicaCompraVenta >
Next Steps
After building your invoice:
Marshal to XML : Use xml.Marshal(factura)
Sign : Use models.CompraVenta.SignXML()
Compress : Use gzip compression
Hash : Calculate SHA256 hash
Submit : Use RecepcionFactura service method
See the RecepcionFactura page for the complete submission workflow.
RecepcionFactura Submit invoices to SIAT
Overview CompraVenta service overview