Downloading files
Every processed DTE generates downloadable files. A single endpoint serves them all: /api/connect/file/{id_or_ref}. It works for sales (Invoice, CCF, Credit Note, Export) and SUEX — you don't need to know which type the document belongs to; the API looks up both automatically.
Dual authentication
The download endpoint accepts two ways to send your API key:
| Method | Use case | Status |
|---|---|---|
Header Authorization: Bearer odt_xxx | Backend integrations, server-side code | Recommended |
Query param ?key=odt_xxx | Shareable links, browser, emails | Deprecated fallback |
The rest of the API (issue, query, invalidate) requires the header exclusively. The query param exists only here, only for downloads, and only because there are cases where you can't inject the header:
- Sharing a ticket link with a customer so they can print it.
- Embedding the ticket in a transactional email with a direct link.
- Opening the ticket in the browser by clicking from a table in your app.
?key= query param is deprecatedKept for compatibility with previous integrations, but will eventually be removed. For any new integration use the Authorization header. If a link must be shareable without your own backend, the best practice is to proxy the download from your server (your backend makes the call with the header, and exposes a short link of your own to the end customer).
If you use ?key= treat those URLs as secrets. Anyone with the link can download the file. Don't publish them in logs, repos, or public chats.
Technical details
| Method | GET |
| URL | https://ocote.io/api/connect/file/{id_or_ref}?type=TYPE |
| Authentication | Header Authorization: Bearer odt_xxx or query ?key=odt_xxx |
The {id_or_ref} can be a UUID or external_ref. The API looks up sales and SUEX automatically; you don't need to know which table the document belongs to.
File types (type=)
type= | Contents |
|---|---|
ticket | 8×21 cm thermal PDF ready to print. |
invoice | Letter-sized PDF of the document, with official formatting. |
json | Signed JSON (JWS) with the MH stamp. |
Availability by document type
Not every file type applies to every DTE. This is the authoritative matrix:
| DTE type | ticket | invoice | json |
|---|---|---|---|
| Invoice (01) | Yes | Yes | Yes |
| CCF (03) | — | Yes | Yes |
| Credit Note (05) | — | Yes | Yes |
| Export (11) | — | Yes | Yes |
| SUEX (14) | — | Yes | Yes |
ticketonly exists for Invoice (01). Requesting it for any other type returns 404.invoiceis the letter-sized PDF; useful for bookkeeping or emailing to the receiver.jsonis the signed fiscal document; only available whendte_success: true(MH stamp received).
URLs come pre-built in responses
When you issue or query a DTE successfully, ready-to-use URLs come in the response (ticket_url, invoice_url, json_url — depending on the type). Use them as-is with your Authorization header — no need to build them by hand.
{
"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"
}
Note: the URLs no longer include ?key= in the response. To download, send your API key in the header.
Examples
Download ticket from terminal (Authorization header)
curl -o ticket.pdf \
-H "Authorization: Bearer odt_xxx" \
"https://ocote.io/api/connect/file/SALE-2026-0042?type=ticket"
Result: ticket.pdf file in your local directory.
Download letter PDF
curl -o invoice.pdf \
-H "Authorization: Bearer odt_xxx" \
"https://ocote.io/api/connect/file/SALE-2026-0042?type=invoice"
Download signed JSON
curl -o dte.json \
-H "Authorization: Bearer odt_xxx" \
"https://ocote.io/api/connect/file/SALE-2026-0042?type=json"
The JSON is the full JWS (JSON Web Signature) of the signed DTE, with the MH stamp. Use it for bookkeeping archives, audits, or re-sending to the recipient.
Open ticket in the browser (?key= fallback)
Browsers don't allow setting arbitrary headers in a direct GET request. For those cases, use the deprecated fallback:
https://ocote.io/api/connect/file/SALE-2026-0042?type=ticket&key=odt_xxx
Paste it in the browser's address bar. The PDF opens directly. Remember the URL contains your API key — don't share it in public channels.
Embed in an email (?key= fallback)
<p>Thanks for your purchase. You can download your ticket here:</p>
<a href="https://ocote.io/api/connect/file/SALE-2026-0042?type=ticket&key=odt_xxx">
Download ticket (PDF)
</a>
The email above contains your API key in the link. If the customer forwards the email, the recipient inherits access to download other files from your account if they figure out the UUID pattern. Best practice: proxy the download from your backend (your backend makes the call with the Authorization header, and exposes a short link of your own to the end customer, e.g. https://your-app.com/ticket/abc123 that your backend resolves internally).
File availability by state
ticket: available as soon as the document passes through the DTE processor (is_dte: true), even in contingency. The ticket includes a note about the transmission status if not stamped.invoice: available whendte_success: true(document accepted with MH stamp).json: available only whendte_success: true. For documents in contingency or rejected, the endpoint responds 404 withFile not available.
Errors
| HTTP | Message | Cause |
|---|---|---|
| 401 | API key requerida (header Authorization: Bearer odt_xxx) | Missing header and ?key=. |
| 401 | API key invalida | Key misspelled, disabled, or belongs to another company. |
| 400 | type debe ser uno de: ticket, invoice, json | Unsupported type value. |
| 404 | Documento no encontrado | id_or_ref doesn't exist in your company. |
| 404 | Archivo no disponible | File not yet generated (contingency or not stamped). |
| 404 | Ticket solo disponible para Factura (01) | You requested type=ticket for a DTE of type 03, 05, 11, or 14. |
| 404 | SUEX no genera ticket PDF | You requested type=ticket for a type 14 document. |
See also
- Check status — to get up-to-date URLs for any document.
- Authentication — general detail on the Authorization header.
- Contingency — why
json_urlmay temporarily be empty.