Skip to main content

Como funciona

CUCU usa API Keys con formato estilo Stripe para autenticacion. Un solo header (X-API-Key) en cada request es todo lo que necesitas. Sin OAuth, sin tokens temporales, sin flujos complejos. La key determina automaticamente el tenant (empresa), el ambiente (sandbox o produccion) y los permisos de acceso.
X-API-Key: YOUR_API_KEY
           ──┬───  ──┬──
             │       └── Ambiente: test (sandbox) o live (produccion)
             └────────── Prefijo: siempre "sk_" (secret key)

Tipos de API Keys

Las keys de sandbox conectan al SIAT Piloto del SIN. Las facturas emitidas son de prueba y no tienen validez fiscal.
PropiedadValor
Prefijosk_test_
Ambiente SIATPiloto (ambiente 2)
Validez fiscalNo
CostoIncluido en tu plan
Uso recomendadoDesarrollo, testing, demos, integracion
# Ejemplo de key sandbox
X-API-Key: YOUR_API_KEY
Activa tu plan en app.cucu.bo/signup para obtener tu API Key de sandbox. Las keys sandbox tienen acceso completo al SIAT piloto.

Autenticacion via header

Incluye tu API Key en el header X-API-Key de cada request. No se acepta autenticacion via query params, body, ni Basic Auth.
curl -X GET https://sandbox.cucu.bo/api/v1/invoices \
  -H "X-API-Key: YOUR_API_KEY"

Buenas practicas de seguridad

Variables de entorno

Almacena la API Key en variables de entorno o en un secret manager (Vault, Infisical, AWS Secrets Manager). Nunca hardcodees la key directamente en el codigo fuente.

Separa ambientes

Usa sk_test_ en desarrollo y testing, sk_live_ exclusivamente en produccion. Nunca mezcles keys entre ambientes en el mismo despliegue.

Solo backend

Las keys sk_live_ deben vivir exclusivamente en tu servidor backend. Nunca las expongas en aplicaciones frontend, moviles o repositorios publicos.

Rota periodicamente

Regenera tu API Key desde el dashboard si sospechas una filtracion o como practica periodica. La key anterior se revoca inmediatamente al generar una nueva.

Patrones recomendados por lenguaje

// .env
CUCU_API_KEY=sk_live_...

// app.js
import 'dotenv/config';

const cucuClient = {
  baseUrl: process.env.CUCU_BASE_URL || 'https://api.cucu.bo',
  apiKey: process.env.CUCU_API_KEY,

  async request(method, path, body) {
    const response = await fetch(`${this.baseUrl}${path}`, {
      method,
      headers: {
        'Content-Type': 'application/json',
        'X-API-Key': this.apiKey
      },
      body: body ? JSON.stringify(body) : undefined
    });
    return response.json();
  }
};
# .env
CUCU_API_KEY=sk_live_...

# client.py
import os
import requests

class CucuClient:
    def __init__(self):
        self.base_url = os.environ.get('CUCU_BASE_URL', 'https://api.cucu.bo')
        self.api_key = os.environ['CUCU_API_KEY']
        self.session = requests.Session()
        self.session.headers.update({
            'Content-Type': 'application/json',
            'X-API-Key': self.api_key
        })

    def request(self, method, path, json=None):
        response = self.session.request(method, f'{self.base_url}{path}', json=json)
        return response.json()
// main.go
package main

import (
    "bytes"
    "encoding/json"
    "net/http"
    "os"
)

type CucuClient struct {
    BaseURL string
    APIKey  string
    Client  *http.Client
}

func NewCucuClient() *CucuClient {
    baseURL := os.Getenv("CUCU_BASE_URL")
    if baseURL == "" {
        baseURL = "https://api.cucu.bo"
    }
    return &CucuClient{
        BaseURL: baseURL,
        APIKey:  os.Getenv("CUCU_API_KEY"),
        Client:  &http.Client{},
    }
}

func (c *CucuClient) Request(method, path string, body interface{}) (*http.Response, error) {
    var buf bytes.Buffer
    if body != nil {
        json.NewEncoder(&buf).Encode(body)
    }
    req, _ := http.NewRequest(method, c.BaseURL+path, &buf)
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("X-API-Key", c.APIKey)
    return c.Client.Do(req)
}
<?php
// .env
// CUCU_API_KEY=sk_live_...

// CucuClient.php
class CucuClient {
    private string $baseUrl;
    private string $apiKey;

    public function __construct() {
        $this->baseUrl = getenv('CUCU_BASE_URL') ?: 'https://api.cucu.bo';
        $this->apiKey = getenv('CUCU_API_KEY');
    }

    public function request(string $method, string $path, ?array $body = null): array {
        $ch = curl_init($this->baseUrl . $path);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            "X-API-Key: {$this->apiKey}"
        ]);
        if ($body) {
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
        }
        $response = curl_exec($ch);
        curl_close($ch);
        return json_decode($response, true);
    }
}

Errores de autenticacion

Cuando la autenticacion falla, la API responde con un JSON estructurado que indica la causa exacta:
HTTP CodeCodigo internoCausaSolucion
401UNAUTHORIZEDAPI Key no enviadaIncluir header X-API-Key en el request
401UNAUTHORIZEDAPI Key invalidaVerificar que la key existe y no tiene errores tipograficos
401UNAUTHORIZEDAPI Key revocadaGenerar una nueva key desde el dashboard
401UNAUTHORIZEDTenant inactivoContactar soporte; la cuenta asociada esta desactivada
403FORBIDDENSin permisosLa key no tiene acceso al recurso solicitado
Ejemplo de respuesta de error:
{
  "success": false,
  "message": null,
  "data": null,
  "error": {
    "code": "UNAUTHORIZED",
    "details": "API Key invalida o tenant inactivo"
  },
  "timestamp": "2026-02-11T12:00:00"
}
Si recibes 401 de forma inesperada, verifica: (1) que el header sea X-API-Key (no Authorization), (2) que no haya espacios extra en la key, y (3) que estes usando la key del ambiente correcto (sk_test_ para sandbox, sk_live_ para produccion).

Endpoints publicos (sin autenticacion)

Estos endpoints no requieren API Key y pueden ser accedidos directamente:
EndpointMetodoDescripcion
/api/v1/pingGETHealth check del servidor
/api/v1/infoGETInformacion del servidor (version, uptime)
/api/v1/public/invoice/{cuf}/pdfGETDescarga publica del PDF de una factura
/api/v1/public/invoice/{cuf}/xmlGETDescarga publica del XML firmado
/api/v1/public/invoice/{cuf}/statusGETEstado publico de una factura
/f/{cuf}GETPagina publica de verificacion de factura (estilo SIAT)
/api/v1/ai/statusGETEstado de los servicios de IA (Qdrant, embeddings)
Los endpoints publicos de factura usan el CUF (Codigo Unico de Facturacion) como identificador. Esto permite compartir URLs de descarga directamente con clientes sin exponer credenciales.
Todos los demas endpoints requieren X-API-Key, incluyendo los endpoints de SIAT (/api/v1/siat/*), catalogos (/api/v1/siat/sync/*), facturacion (/api/v1/invoices), e IA (/api/v1/ai/chat). Cada endpoint valida que los recursos accedidos pertenezcan al tenant autenticado (proteccion cross-tenant).

Rotacion de API Keys

Rotar tu API Key es una practica recomendada de seguridad. Cuando generas una nueva key desde el dashboard, la key anterior se revoca inmediatamente.
1

Genera una nueva key

Accede a tu dashboard en app.cucu.bo y navega a Configuracion > API Keys. Haz clic en Regenerar key para el ambiente deseado (sandbox o produccion).
2

Actualiza tu aplicacion

Reemplaza la key antigua en tus variables de entorno o secret manager con la nueva key. Despliega la actualizacion.
3

Verifica la conexion

Haz un request de prueba al endpoint /ping con la nueva key para confirmar que funciona.
La rotacion es inmediata e irreversible. Al generar una nueva key, la anterior deja de funcionar al instante. Asegurate de actualizar todos los servicios que usen la key antes de rotarla, o implementa un mecanismo de rollout gradual.

SDKs (proximamente)

Estamos desarrollando SDKs oficiales para los lenguajes mas populares. Mientras tanto, la API REST funciona con cualquier cliente HTTP en cualquier lenguaje.

Node.js SDK

npm install @cucu/sdkEn desarrollo. Lanzamiento estimado Q2 2026.

Python SDK

pip install cucu-sdkEn desarrollo. Lanzamiento estimado Q2 2026.

Go SDK

go get github.com/cucuapi/cucu-goEn planificacion. Lanzamiento estimado Q3 2026.
Quieres que prioricemos un SDK en particular? Escribe a dev@cucu.bo y cuentanos que lenguaje usas. Tambien aceptamos contribuciones open source.