QAPI está en beta — la API puede cambiar sin previo aviso. Usa sandbox para pruebas.
QAPIQAPIDocs · by DTEVIA
Referencia

Estados de Factura

Ciclo de vida completo de una factura QAPI — de PENDING a CERTIFIED, FAILED o CANCELLED.

Estados de Factura

Cada factura en QAPI pasa por un ciclo de vida bien definido. El campo status en GET /v1/invoices/:id siempre refleja el estado actual.

Diagrama de estados

POST /v1/invoices  (responde 202 con status "PROCESSING")


   PENDING ──────────────────────────────────────────┐
       │  (pipeline async inicia)                     │
       ▼                                              │
   SIGNING ── firma del XML falla ──────► FAILED      │
       │                                              │
       ▼                                              │
  CERTIFYING ── certificador falla ─────► FAILED      │
       │                                              │
       └──── certificador responde OK ──► CERTIFIED   │

  CERTIFIED ──── POST /invoices/:id/cancel ──► CANCELLED

PROCESSING solo aparece en la respuesta 202

El body del 202 Accepted devuelve status: "PROCESSING" como resumen de "tu factura está en el pipeline". Al consultar con GET /v1/invoices/:id verás el estado persistido real: PENDING, SIGNING, CERTIFYING, o uno de los finales. Trata los tres transitorios como equivalentes: "todavía no hay resultado, sigue esperando".


Detalle de cada estado

Prop

Type


Campos disponibles por estado

CERTIFIED

{
  "id": "inv_01jx...",
  "status": "CERTIFIED",
  "tipo_dte": "FACT",
  "moneda": "GTQ",
  "gran_total": 112.00,
  "numero_acceso": 543219876,
  "certificador": "TOTALDOC",
  "uuid_sat": "550E8400-E29B-41D4-A716-446655440000",
  "serie": "A",
  "numero_dte": 42,
  "pdf_url": "https://print.totaldoc.io/pdf?uuid=550E8400-...",
  "referencia_interna": "ORD-2026-001",
  "integrity_checksum": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
  "created_at": "2026-06-08T16:00:00.000Z",
  "updated_at": "2026-06-08T16:00:02.000Z",
  "certified_at": "2026-06-08T16:00:02.000Z"
}

FAILED

{
  "id": "inv_01jx...",
  "status": "FAILED",
  "tipo_dte": "FACT",
  "gran_total": 112.00,
  "certificador": "TOTALDOC",
  "error_code": "CERT_FAILED",
  "error_message": "NIT del emisor no encontrado en el padrón SAT",
  "created_at": "2026-06-08T16:00:00.000Z",
  "updated_at": "2026-06-08T16:00:05.000Z"
}

CANCELLED

{
  "id": "inv_01jx...",
  "status": "CANCELLED",
  "tipo_dte": "FACT",
  "gran_total": 112.00,
  "uuid_sat": "550e8400-e29b-41d4-a716-446655440000",
  "certified_at": "2026-06-08T16:00:02.000Z",
  "cancelled_at": "2026-06-09T10:30:00.000Z"
}

Transiciones permitidas

DesdeHaciaCómo
PENDINGSIGNINGAutomático — pipeline interno inicia
SIGNINGCERTIFYINGAutomático — XML firmado correctamente
SIGNINGFAILEDAutomático — la firma falla (error_code: SIGN_FAILED)
CERTIFYINGCERTIFIEDAutomático — certificador responde OK
CERTIFYINGFAILEDAutomático — certificador falla o timeout (error_code: CERT_FAILED)
CERTIFIEDCANCELLEDManual — POST /v1/invoices/:id/cancel

Solo CERTIFIED se puede cancelar

Si intentas cancelar una factura que no está en estado CERTIFIED (por ejemplo SIGNING, CERTIFYING o FAILED), recibirás 409 INVALID_STATUS.

FAILED no es cancelable

Una factura FAILED no tiene validez tributaria — no llegó a la SAT. No es necesario cancelarla. Simplemente crea una nueva factura con los datos corregidos.


Polling recomendado

En entorno live, la certificación tarda entre 1 y 10 segundos dependiendo del certificador. En entorno test (MOCK), es casi instantáneo.

Estrategia de polling con backoff:

async function waitForCertification(id: string, apiKey: string) {
  const delays = [1000, 2000, 2000, 3000, 3000, 5000, 5000, 10000];

  for (const delay of delays) {
    await new Promise(r => setTimeout(r, delay));

    const res = await fetch(`https://api.dtevia.com.gt/v1/invoices/${id}`, {
      headers: { Authorization: `Bearer ${apiKey}` },
    });
    const invoice = await res.json();

    if (invoice.status === 'CERTIFIED') return invoice;
    if (invoice.status === 'FAILED') throw new Error(invoice.error_message);
  }

  throw new Error('Timeout: la certificación tardó más de lo esperado');
}

Como alternativa al polling, configura un webhook para recibir invoice.certified e invoice.failed automáticamente.


Webhook events por estado

Estado finalEvento webhook disparado
CERTIFIEDinvoice.certified
FAILEDinvoice.failed
CANCELLEDinvoice.cancelled

Los estados transitorios (PENDING, SIGNING, CERTIFYING) no disparan webhooks — solo los finales. El evento invoice.test se dispara manualmente desde el dashboard.

El error_code de una factura FAILED es SIGN_FAILED (falló la firma) o CERT_FAILED (falló la certificación) — es un namespace distinto al de los errores HTTP del catálogo de errores.

On this page