Saltar al contenido principal

Descargar archivos

Todo DTE procesado genera archivos descargables. Hay un único endpoint para todos: /api/connect/file/{id_or_ref}. Funciona para ventas (Factura, CCF, NC, Exportación) y SUEX sin que necesites saber a qué tipo pertenece el documento — el API busca automáticamente.

Autenticación dual

El endpoint de descarga acepta dos formas de enviar tu API key:

MétodoUsoEstado
Header Authorization: Bearer odt_xxxIntegraciones backend, código de servidorRecomendado
Query param ?key=odt_xxxEnlaces compartibles, navegador, correosFallback deprecado

El resto del API (emisión, consulta, invalidación) requiere exclusivamente el header. El query param existe solo aquí, solo para descargas, y únicamente porque hay casos donde no puedes inyectar el header:

  • Compartir un link de ticket con un cliente para que lo imprima.
  • Embeber el ticket en un correo transaccional con un enlace directo.
  • Abrir el ticket en el navegador haciendo clic desde una tabla de tu app.
El query param ?key= está deprecado

Se mantiene por compatibilidad con integraciones previas, pero eventualmente será removido. Para cualquier integración nueva usa el header Authorization. Si un enlace debe ser compartible sin backend propio, la mejor práctica es proxear la descarga desde tu servidor (tu backend hace la llamada con header, y expone un link corto propio al cliente final).

Si usas ?key= trata esos URLs como secretos. Cualquiera con el link puede descargar el archivo. No los publiques en logs, repos o chats públicos.

Detalles técnicos

MétodoGET
URLhttps://ocote.io/api/connect/file/{id_or_ref}?type=TIPO
AutenticaciónHeader Authorization: Bearer odt_xxx o query ?key=odt_xxx

El {id_or_ref} puede ser UUID o external_ref. El API busca automáticamente en ventas y SUEX; no necesitas saber a qué tabla pertenece.

Tipos de archivo (type=)

type=Contenido
ticketPDF térmico 8×21 cm listo para imprimir.
invoicePDF tamaño carta del documento, con formato oficial.
jsonJSON firmado (JWS) con sello MH.

Disponibilidad por tipo de documento

No todos los tipos de archivo aplican a todos los DTE. Esta es la matriz autoritativa:

Tipo de DTEticketinvoicejson
Factura (01)
Crédito Fiscal (03)
Nota de Crédito (05)
Exportación (11)
Sujeto Excluido (14)
  • ticket solo existe para Factura (01). Pedirlo para cualquier otro tipo devuelve 404.
  • invoice es el PDF carta; sirve para archivo contable o envío por correo.
  • json es el comprobante fiscal firmado; solo está disponible cuando dte_success: true (sello MH recibido).

URLs vienen precocinadas en los responses

Cuando emites o consultas un DTE exitosamente, los URLs listos para usar vienen en el response (ticket_url, invoice_url, json_url — según el tipo). Úsalos tal cual con tu header Authorization — no necesitas construirlos a mano.

{
"ticket_url": "https://ocote.io/api/connect/file/a1b2c3d4-.../...?type=ticket",
"invoice_url": "https://ocote.io/api/connect/file/a1b2c3d4-.../...?type=invoice",
"json_url": "https://ocote.io/api/connect/file/a1b2c3d4-.../...?type=json"
}

Nota: los URLs ya no incluyen ?key= en el response. Para descargar, manda tu API key en el header.

Ejemplos

Descargar ticket desde terminal (header Authorization)

curl
curl -o ticket.pdf \
-H "Authorization: Bearer odt_xxx" \
"https://ocote.io/api/connect/file/VENTA-2026-0042?type=ticket"

Resultado: archivo ticket.pdf en tu directorio local.

Descargar PDF carta

curl
curl -o factura.pdf \
-H "Authorization: Bearer odt_xxx" \
"https://ocote.io/api/connect/file/VENTA-2026-0042?type=invoice"

Descargar JSON firmado

curl
curl -o dte.json \
-H "Authorization: Bearer odt_xxx" \
"https://ocote.io/api/connect/file/VENTA-2026-0042?type=json"

El JSON es el JWS (JSON Web Signature) completo del DTE firmado, con el sello MH. Sirve para archivo contable, auditorías, o re-envío al receptor.

Abrir ticket desde el navegador (fallback ?key=)

El navegador no permite setear headers arbitrarios en una petición GET directa. Para esos casos, usa el fallback deprecado:

https://ocote.io/api/connect/file/VENTA-2026-0042?type=ticket&key=odt_xxx

Pégalo en la barra del navegador. El PDF se abre directamente. Recuerda que el URL contiene tu API key — no lo compartas en canales públicos.

Embeber en un correo (fallback ?key=)

<p>Gracias por tu compra. Puedes descargar tu ticket aquí:</p>
<a href="https://ocote.io/api/connect/file/VENTA-2026-0042?type=ticket&key=odt_xxx">
Descargar ticket (PDF)
</a>
Protege tu API key

El correo de arriba contiene tu API key en el link. Si el cliente reenvía el correo, el destinatario hereda acceso a descargar otros archivos de tu cuenta si averigua el patrón de UUIDs. Mejor práctica: proxea la descarga desde tu backend (tu backend hace la llamada con header Authorization, y expone un link corto propio al cliente final, por ejemplo https://tu-app.com/ticket/abc123 que tu backend resuelve internamente).

Disponibilidad de archivos por estado

  • ticket: disponible desde que el documento pasa por el DTE processor (is_dte: true), aunque esté en contingencia. El ticket incluye nota del estado de transmisión si no está sellado.
  • invoice: disponible cuando dte_success: true (documento aceptado con sello MH).
  • json: disponible solo cuando dte_success: true. Para documentos en contingencia o rechazados, el endpoint responde 404 con Archivo no disponible.

Errores

HTTPMensajeCausa
401API key requerida (header Authorization: Bearer odt_xxx)Falta header y ?key=.
401API key invalidaKey mal escrita, desactivada, o de otra empresa.
400type debe ser uno de: ticket, invoice, jsonValor de type no soportado.
404Documento no encontradoEl id_or_ref no existe en tu empresa.
404Archivo no disponibleEl archivo aún no se generó (documento en contingencia o no sellado).
404Ticket solo disponible para Factura (01)Pediste type=ticket para un DTE tipo 03, 05, 11 o 14.
404SUEX no genera ticket PDFPediste type=ticket para un documento tipo 14.

Ver también

  • Consultar estado — para obtener los URLs actualizados de cualquier documento.
  • Autenticación — detalle general del header Authorization.
  • Contingencia — por qué el json_url puede venir vacío temporalmente.