Skip to main content

Overview

The AnulacionFactura method allows you to cancel an invoice that was previously accepted by SIAT. This is required when an invoice needs to be voided due to errors, returns, or other business reasons.

Method Signature

func (s *SiatCompraVentaService) AnulacionFactura(
    ctx context.Context,
    config config.Config,
    request AnulacionFacturaRequest,
) (*soap.EnvelopeResponse[compra_venta.AnulacionFacturaResponse], error)

Parameters

ctx
context.Context
required
Go context for request lifecycle management, cancellation, and timeouts
config
config.Config
required
Configuration containing the API token for authentication
type Config struct {
    Token string // API key from SIAT
}
request
AnulacionFacturaRequest
required
Opaque request built using models.CompraVenta.NewAnulacionFacturaRequest() builder

Building the Request

Use the AnulacionFacturaBuilder to construct the cancellation request:
request := models.CompraVenta.NewAnulacionFacturaRequest().
    WithCodigoAmbiente(2).              // 2 = Producción
    WithCodigoDocumentoSector(1).       // Tipo de documento sector
    WithCodigoEmision(1).               // 1 = En línea
    WithCodigoModalidad(1).             // 1 = Electrónica
    WithCodigoPuntoVenta(0).            // Código del punto de venta
    WithCodigoSistema("ABC123DEF").     // Código del sistema
    WithCodigoSucursal(0).              // Código de la sucursal
    WithCufd("CUFD_VIGENTE").           // CUFD vigente
    WithCuf("CUF_DE_LA_FACTURA").       // CUF de la factura a anular
    WithCuis("C2FC682B").               // CUIS del punto de venta
    WithNit(123456789).                 // NIT del emisor
    WithTipoFacturaDocumento(1).        // Tipo de factura
    WithCodigoMotivo(1).                // Código del motivo de anulación
    Build()

Request Fields

CodigoAmbiente
int
required
Execution environment: 1 = Testing, 2 = Production
CodigoDocumentoSector
int
required
Document sector type code from SIAT catalogs
CodigoEmision
int
required
Emission type: 1 = Online, 2 = Offline
CodigoModalidad
int
required
Modality code: 1 = Electronic, 2 = Computer/Manual
CodigoPuntoVenta
int
required
Point of sale code registered in SIAT
CodigoSistema
string
required
System code obtained during system registration
CodigoSucursal
int
required
Branch/office code registered in SIAT
Cufd
string
required
CUFD (Código Único de Factura Diario) - must be currently valid
Cuf
string
required
CUF (Código Único de Factura) of the invoice to be canceled - this is the unique identifier of the invoice you want to void
Cuis
string
required
CUIS (Código Único de Inicio de Sistema) - system initialization code
Nit
int64
required
Tax identification number (NIT) of the issuer
TipoFacturaDocumento
int
required
Invoice/document type code from SIAT catalogs
CodigoMotivo
int
required
Cancellation reason code from SIAT catalog:
  • 1 = Error in invoice
  • 2 = Product return
  • 3 = Other reasons (check SIAT documentation for complete list)

Response

Returns a SOAP envelope containing AnulacionFacturaResponse:
type AnulacionFacturaResponse struct {
    RespuestaServicioFacturacion RespuestaServicioFacturacion
}

type RespuestaServicioFacturacion struct {
    Transaccion       bool
    CodigoRecepcion   string
    CodigoEstado      int
    CodigoDescripcion string
    MensajesList      []MensajeServicio
}
Transaccion
boolean
true if the cancellation was successful, false otherwise
CodigoRecepcion
string
Reception code for the cancellation operation (present on success)
CodigoEstado
int
Status code indicating the result of the operation
CodigoDescripcion
string
Human-readable description of the operation result
MensajesList
[]MensajeServicio
List of messages, warnings, or errorsEach message contains:
  • Codigo (int): Message code
  • Descripcion (string): Message description

Example

Complete example of canceling an invoice:
package main

import (
    "context"
    "fmt"
    "log"

    "github.com/ron86i/go-siat"
    "github.com/ron86i/go-siat/pkg/config"
    "github.com/ron86i/go-siat/pkg/models"
)

func main() {
    // Initialize SIAT client
    client, err := siat.New("https://pilotosiatservicios.impuestos.gob.bo/v2", nil)
    if err != nil {
        log.Fatal(err)
    }

    ctx := context.Background()
    cfg := config.Config{Token: "YOUR_API_TOKEN"}

    // CUF of the invoice to cancel
    cufToCancel := "ABC123XYZ789..."

    // Build cancellation request
    request := models.CompraVenta.NewAnulacionFacturaRequest().
        WithCodigoAmbiente(2).
        WithCodigoDocumentoSector(1).
        WithCodigoEmision(1).
        WithCodigoModalidad(1).
        WithCodigoPuntoVenta(0).
        WithCodigoSistema("ABC123DEF").
        WithCodigoSucursal(0).
        WithCufd("CUFD_VIGENTE").
        WithCuf(cufToCancel).
        WithCuis("C2FC682B").
        WithNit(123456789).
        WithTipoFacturaDocumento(1).
        WithCodigoMotivo(1). // 1 = Error in invoice
        Build()

    // Submit cancellation
    resp, err := client.CompraVenta.AnulacionFactura(ctx, cfg, request)
    if err != nil {
        log.Fatalf("Error canceling invoice: %v", err)
    }

    // Check response
    if resp.Body.Content.RespuestaServicioFacturacion.Transaccion {
        fmt.Printf("Invoice successfully canceled!\n")
        fmt.Printf("Reception code: %s\n",
            resp.Body.Content.RespuestaServicioFacturacion.CodigoRecepcion)
    } else {
        fmt.Printf("Cancellation failed: %s\n",
            resp.Body.Content.RespuestaServicioFacturacion.CodigoDescripcion)
        
        // Show validation messages
        for _, msg := range resp.Body.Content.RespuestaServicioFacturacion.MensajesList {
            fmt.Printf("  [%d] %s\n", msg.Codigo, msg.Descripcion)
        }
    }
}

Error Handling

Handle both network errors and SIAT validation errors:
resp, err := client.CompraVenta.AnulacionFactura(ctx, cfg, request)
if err != nil {
    // Network or HTTP error
    log.Printf("Request failed: %v", err)
    return
}

// Check SIAT response
if !resp.Body.Content.RespuestaServicioFacturacion.Transaccion {
    // SIAT rejected the cancellation
    log.Printf("Cancellation rejected: %s",
        resp.Body.Content.RespuestaServicioFacturacion.CodigoDescripcion)
    
    // Common reasons for rejection:
    // - Invoice not found (invalid CUF)
    // - Invoice already canceled
    // - Invalid credentials (CUFD/CUIS expired)
    // - Invalid cancellation reason code
    
    for _, msg := range resp.Body.Content.RespuestaServicioFacturacion.MensajesList {
        log.Printf("  Code %d: %s", msg.Codigo, msg.Descripcion)
    }
}

Common Cancellation Reasons

When using WithCodigoMotivo(), use the appropriate reason code:
CodeReasonWhen to Use
1Error in invoiceInvoice contains incorrect data
2Product returnCustomer returned products
3+Other reasonsCheck SIAT documentation for complete list
The exact list of cancellation reason codes may vary. Always refer to the latest SIAT catalogs for the complete and up-to-date list.

Important Considerations

An invoice can only be canceled if it was previously accepted by SIAT. You cannot cancel rejected invoices.
The CUFD used for cancellation must be valid at the time of the cancellation request. If your CUFD has expired, you must obtain a new one before attempting to cancel an invoice.
Keep track of cancellation reception codes in your system for audit purposes. SIAT provides these codes as proof of the cancellation operation.

RecepcionFactura

Submit invoices to SIAT

Overview

CompraVenta service overview

Build docs developers (and LLMs) love