Estados
Los once estados de un documento y cómo seguirlo hasta el veredicto.
Emitir no es instantáneo. El documento se firma, se presenta y Hacienda lo resuelve cuando lo resuelve; Timbre lo sigue mientras tanto.
Si lo que necesitás es mirar un documento, no integrarlo en tu sistema, el panel ya te lo muestra: Facturas lista todos, con filtros por estado, tipo, contribuyente y fecha, y cada uno abre a su línea de tiempo completa. Lo de abajo es para seguirlo por código.
curl https://api.timbrecr.com/core/v1/invoices/{id} \
-H "Authorization: Bearer timbre_sk_…"Los once estados
status dice en qué punto del camino está el documento, y puede tomar once valores:
| Estado | Qué significa |
|---|---|
draft | Creado, sin clave ni consecutivo |
finalized | Numerado; el proceso arrancó |
queued | En cola de trabajo |
generated | XML armado y validado contra los XSD |
signed | Firmado con XAdES |
submitted | Presentado a Hacienda |
processing | Hacienda lo recibió y todavía no resuelve |
accepted | Aceptado |
rejected | Rechazado |
retry_pending | Falló algo transitorio; se reintenta solo |
permanent_error | Falló de forma definitiva |
Los tres en negrita son terminales: de ahí no se mueve.
retry_pending no requiere nada de tu parte: Timbre reintenta con espera
creciente. permanent_error sí: algo del documento o del entorno está mal y no
va a mejorar reintentando.
Un documento rejected no tiene validez: no lleva nota de crédito ni se le
entrega al cliente, se corrige y se emite uno nuevo. Cuando eso ocurre en
producción, y también ante un permanent_error, Timbre le escribe a quienes
administran la organización en el panel, una sola vez por documento, además de
avisarle a tu sistema por el webhook.
Los totales del documento
Desde que se finaliza, la consulta trae también emissionDate (la fecha de
emisión con la que Hacienda lo registra) y summary: los totales del
resumen tal como se calcularon y firmaron, sin recalcular nada. Ahí están las
ventas gravadas, exentas, exoneradas y no sujetas, el impuesto total y, en
taxBreakdown, el impuesto por código y tarifa de IVA. Los montos vienen en la
moneda del documento, como texto con cinco decimales, y exchangeRate es el
tipo de cambio que declaró (1 en colones). En un borrador los dos vienen en
null.
{
"emissionDate": "2026-09-30T23:30:00.000Z",
"summary": {
"currency": "CRC",
"exchangeRate": "1",
"totalGravado": "10000.00000",
"totalExento": "0.00000",
"totalVentaNeta": "10000.00000",
"totalImpuesto": "1300.00000",
"totalComprobante": "11300.00000",
"taxBreakdown": [
{ "codigo": "01", "codigoTarifaIVA": "08", "totalMontoImpuesto": "1300.00000" }
]
}
}Si lo que buscás es el total del mes por contribuyente, el panel ya lo suma: Reportes muestra las ventas y el IVA por tarifa de los documentos aceptados, en colones, con las notas de crédito restadas, y lo exporta a CSV.
No consultes en bucle
Podés consultar el documento, y para una prueba manual está bien. Para producción usá el webhook: Timbre te avisa cuando hay veredicto, en lugar de que preguntes cada pocos segundos por documentos que no cambiaron.
La historia completa
status dice dónde está el documento ahora. La historia dice cómo llegó ahí, transición por transición:
curl https://api.timbrecr.com/core/v1/invoices/{id}/events \
-H "Authorization: Bearer timbre_sk_…"Cada transición queda registrada, en orden y solo se agrega: nada las edita ni las borra. Siempre se puede reconstruir qué pasó y cuándo, que es lo que hace falta cuando algo salió mal hace tres semanas.
Y provenance explica de dónde salió cada decisión de impuesto:
curl https://api.timbrecr.com/core/v1/invoices/{id}/provenance \
-H "Authorization: Bearer timbre_sk_…"Reintentar a mano
Timbre reintenta solo casi todo. Hay un único caso en que te toca a vos volver a encaminar un documento:
curl -X POST https://api.timbrecr.com/core/v1/invoices/{id}/retry \
-H "Authorization: Bearer timbre_sk_…"Ese caso: el documento quedó en finalized
(numerado, pero nunca encolado, porque la cola no estaba disponible) y lo
volvés a encaminar. Si ya está en queued, la llamada no hace nada y responde
lo mismo.
No revive un permanent_error. Desde cualquier otro estado la respuesta es
409 con invalid_transition. Un documento que falló definitivamente se
resuelve emitiendo uno nuevo, no reintentando el que ya se gastó.