Timbre

Componentes

Cada bloque que una guía puede usar, en una sola página, para verlos juntos.

Esta parte todavía está en construcción y puede cambiar.

Esta página no documenta el producto: existe para revisar los componentes. Si algo se ve mal acá, se ve mal en todas las guías.

Es una página de prueba, y está de última a propósito. Cada sección de abajo usa un bloque distinto, con los estados que ese bloque puede tomar, para poder mirarlos todos juntos —en claro y en oscuro, en una pantalla y en un teléfono— sin navegar entre ocho guías.

Cuando la documentación se abra al público, esta página se borra.

Texto

Un párrafo normal, para tener contra qué comparar todo lo demás. Lleva código en línea, un enlace interno, un enlace externo, negrita y cursiva. La medida está limitada, así que este párrafo debería cortar bastante antes del borde derecho de la columna aunque la ventana sea ancha.

Una cita. Sirve para separar algo dicho por otro —una resolución, un artículo— del texto que lo explica.

  • Un ítem
  • Otro ítem
    • Uno anidado
  • Un tercero
  1. Primero
  2. Segundo
  3. Tercero

Avisos

Cuatro tonos, y cada uno significa algo distinto. El tono es una decisión sobre consecuencia, no sobre decoración.

Informativo: algo que conviene saber, pero que no cambia lo que hay que hacer.

Aceptado

Confirma un resultado. Hacienda aceptó el documento y no hay nada más que hacer.

Esto cuesta si lo ignorás

Un consecutivo gastado no se recupera. La numeración fiscal no tiene huecos ni marcha atrás.

Esto ya está roto

El documento quedó en permanent_error. No se revive reintentando: se corrige el problema y se emite uno nuevo.

Pasos

  1. Cotizá

    Preguntá cuánto impuesto lleva la venta. No crea nada y no consume consecutivos.

  2. Emití

    Mandá el documento con Idempotency-Key. Si repetís la petición con la misma llave, recibís el documento que ya existe.

  3. Esperá el veredicto

    Seguí el estado o, mejor, registrá un webhook y dejá que Timbre te avise.

Tarjetas

Campos

CampoTipoDescripción
issuerIdobligatoriostringQué emisor factura.
documentType"FE" | "TE" | "NC" | "ND"Qué tipo de comprobante se emite. Por defecto "FE".
finalizebooleanCrear y finalizar en una sola llamada. Por defecto false.
linesobligatorioLine[]Las líneas de la venta. Al menos una.

Tabla

EstadoTerminalQué significa
draftnoCreado, sin clave ni consecutivo
queuednoEn cola de trabajo
acceptedAceptado por Hacienda
rejectedRechazado
permanent_errorFalló de forma definitiva

Archivos

content

docs

emitir.mdx

estados.mdx

meta.json

api

openapi.core.json

source.config.ts

Preguntas

¿Puedo cambiar de ambiente con un parámetro?

No. Un proyecto está fijado a sandbox o a production, y cambiar de ambiente significa otro proyecto con otra llave. Un parámetro que elige ambiente es un parámetro que alguien manda mal una vez y presenta un documento de prueba como real.

¿Timbre genera el PDF?

Sí, pero no es el documento legal —eso es el XML firmado— y solo lo genera para documentos que Hacienda aceptó.

¿Por qué los montos son texto?

Un número en JSON es un double, y un double no representa exactamente los decimales que la ley obliga a declarar. La diferencia aparece como un colón de más en un total que Hacienda rechaza.

Código

Un bloque suelto lleva su lenguaje arriba y el botón de copiar al pasar el mouse:

Respuesta
{
  "clave": "50601012600310112345600100001010000000001199999999",
  "estado": "accepted",
  "consecutivo": "00100001010000000001"
}

Uno largo, para comprobar que desborda hacia adentro y no empuja la página:

echo "esta línea es deliberadamente larguísima para comprobar que el bloque de código scrollea dentro de su propio marco y no hace que la página entera se mueva de lado"

Y el de los ejemplos de la API. La franja no dice el lenguaje —«cURL» encima de un comando que empieza con curl no informa de nada— sino qué es el bloque, que es lo que hay que averiguar cuando una página alterna los dos:

Petición
curl https://api.timbre.cr/internal/v1/issuers \
  -H "Authorization: Bearer timbre_sk_…"

Con nombre de archivo

Cuando el bloque es un archivo, el nombre importa más que el lenguaje y ocupa su lugar:

lib/timbre.ts
export const timbre = createClient({
  apiKey: process.env.TIMBRE_API_KEY,
})

Anotaciones

Las marcas van en un comentario del propio código, así que el ejemplo sigue siendo válido si alguien lo copia: el comentario desaparece al renderizar.

factura.ts
const quote = await timbre.quotes.create({
  issuerId, 
  lines,
})

const invoice = await timbre.invoices.create({
  issuerId,
  finalize: true,
})

El :4 cuenta las líneas siguientes, así que la marca vive en su propia línea y ninguna herramienta que reformatee el archivo puede moverla a la línea equivocada.

Un diff, para explicar un cambio en lugar de mostrar dos bloques enteros:

const response = await fetch(url, {
  headers: {
    Authorization: `Bearer ${key}`, 
    Authorization: `Bearer ${process.env.TIMBRE_API_KEY}`, 
  },
})

Y una palabra suelta, cuando lo que importa es un identificador y no la línea:

Respuesta
{ "estado": "permanent_error" } 

Sin copiar

Una respuesta de ejemplo no es algo que nadie deba pegar en ningún lado, así que no ofrece el botón:

timbre_sk_ejemplo_no_es_una_llave_real

Encabezados

Un encabezado de nivel tres

Para ver la sangría en el índice de la derecha y comprobar que el ancla queda debajo de la barra pegajosa y no tapada por ella.

Un encabezado de nivel cuatro

El más profundo que las guías usan.