curl -X GET "https://api.nevatal.com/api/v1/billing/invoices/pdf-export?from=2026-08-01&to=2026-08-31" \
-H "Authorization: Bearer nvtl_your_api_key" \
-o invoices.zip
HTTP/1.1 200 OK
Content-Type: application/zip
Content-Disposition: attachment; filename="invoices_2026-08-01_2026-08-31.zip"
Content-Length: 1843220
{
"success": false,
"error": "The end date must be on or after the start date.",
"code": "VALIDATION_ERROR",
"correlationId": "req-1d2e",
"details": { "field": "to" }
}
{
"success": false,
"error": "The range has more invoices than can be downloaded together. Narrow the date range.",
"code": "INVOICE_EXPORT_TOO_LARGE",
"correlationId": "req-8f4a",
"details": { "count": 181, "max": 100 }
}
{
"success": false,
"error": "There are no issued invoices in that date range.",
"code": "INVOICE_EXPORT_EMPTY",
"correlationId": "req-3b7c"
}
Billing
Export Invoice PDFs
Download a ZIP with the PDF of every invoice issued in a date range, plus a CSV manifest
GET
/
api
/
v1
/
billing
/
invoices
/
pdf-export
curl -X GET "https://api.nevatal.com/api/v1/billing/invoices/pdf-export?from=2026-08-01&to=2026-08-31" \
-H "Authorization: Bearer nvtl_your_api_key" \
-o invoices.zip
HTTP/1.1 200 OK
Content-Type: application/zip
Content-Disposition: attachment; filename="invoices_2026-08-01_2026-08-31.zip"
Content-Length: 1843220
{
"success": false,
"error": "The end date must be on or after the start date.",
"code": "VALIDATION_ERROR",
"correlationId": "req-1d2e",
"details": { "field": "to" }
}
{
"success": false,
"error": "The range has more invoices than can be downloaded together. Narrow the date range.",
"code": "INVOICE_EXPORT_TOO_LARGE",
"correlationId": "req-8f4a",
"details": { "count": 181, "max": 100 }
}
{
"success": false,
"error": "There are no issued invoices in that date range.",
"code": "INVOICE_EXPORT_EMPTY",
"correlationId": "req-3b7c"
}
Returns a ZIP containing one PDF per issued invoice in the requested range
(same rules as Download Invoice PDF
for which PDF each invoice kind gets) plus a CSV manifest listing every invoice
in the range — including the ones a PDF could not be produced for. Payer
accounts (cuentas a convenio) are included. Drafts are never included.
Nothing is persisted; the ZIP is built fresh per request.
UTF-8 with BOM. One header row plus one row per invoice in range, including
skipped ones. Formula-injection guard on cells starting with
Query Parameters
string
required
Start date,
YYYY-MM-DD, inclusive. Filters by the invoice’s emission
date (issuedAt; legacy invoices without it fall back to issueDate) as
a Colombian calendar day (America/Bogota).string
required
End date,
YYYY-MM-DD, inclusive. Must be on or after from.string
default:"all"
One of
all, electronic, manual. electronic includes both Alegra FEVs
and external-provider FEVs.Rules
- Includes invoices in status
issued,partially_paid,paid,voidedorfiled. Drafts are excluded. - Maximum 100 invoices per request. A larger range is rejected outright
(never silently truncated) — see
INVOICE_EXPORT_TOO_LARGEbelow. The cap and the default range are also available from the form-schema endpoint. - One export at a time per clinic (the Alegra credential is shared across
the whole deployment): a second concurrent request gets
429 INVOICE_EXPORT_IN_PROGRESS. The endpoint also caps at 10 exports per minute per clinic. - A provider failure is per-invoice, never fatal to the export: if Alegra
can’t produce a given invoice’s PDF, that row is skipped and recorded in the
manifest with a reason; the rest of the ZIP still ships. If Alegra is down
or rejects the credential, the remaining Alegra invoices in that request are
all skipped as
provider_unavailablewhile Nevatal-generated PDFs (manual, external) still ship. A provider failure never produces a500or aborts the ZIP. - ZIP and manifest are ordered by emission date, ascending.
File names
- The displayed invoice number is the DIAN number when available, otherwise
Nevatal’s internal number; sanitized to
[A-Za-z0-9._-]. - PDF:
<number>.pdf, or<number>-VOIDED.pdffor a voided invoice. - ZIP:
invoices_<from>_<to>.zip. Manifest:manifest.csv. - A name collision inside the ZIP gets a
-2,-3, … suffix.
Response
200 returns the ZIP as application/zip, with Content-Disposition: attachment and Content-Length. A 200 can still contain skipped rows —
check the manifest’s Reason column rather than assuming every invoice in
range got a PDF.
Every non-2xx response is the standard JSON error envelope, never binary.
ZIP contents
invoices_2026-08-01_2026-08-31.zip
├── manifest.csv
├── SETP990000123.pdf ← Alegra official PDF
├── FE-4521.pdf ← external FEV (Nevatal internal support copy)
├── INV-2026-0001-00042.pdf ← manual (Nevatal)
└── INV-2026-0001-00043-VOIDED.pdf
manifest.csv
UTF-8 with BOM. One header row plus one row per invoice in range, including
skipped ones. Formula-injection guard on cells starting with =, +, -,
@ (prefixed with ').
| # | Column | Value |
|---|---|---|
| 1 | Number | Displayed number (DIAN or internal) |
| 2 | Internal number | Nevatal’s own invoiceNumber |
| 3 | Type | Electronic · Electronic (external provider) · Manual |
| 4 | Emission date | YYYY-MM-DD, Colombian calendar day |
| 5 | Customer | Patient or payer name |
| 6 | Total | Amount due |
| 7 | Currency | e.g. COP |
| 8 | Status | Issued · Partially paid · Paid · Voided · Filed |
| 9 | PDF included | Yes / No |
| 10 | File | PDF file name inside the ZIP; empty if skipped |
| 11 | Reason | Empty if included; otherwise one of the reasons below |
Skip reasons
| Reason | Meaning |
|---|---|
not_accepted | DIAN rejected this electronic invoice — no official graphical representation exists. |
missing_provider_document | This electronic invoice has no document registered with the provider. |
provider_file_not_available | Alegra doesn’t have the PDF of this invoice available. |
provider_unavailable | Alegra could not be reached — download again later. |
generation_failed | The PDF of this invoice could not be generated. |
Errors
| Status | Code | When |
|---|---|---|
400 | VALIDATION_ERROR | from/to missing or invalid, to < from, or invalid invoiceType |
400 | INVOICE_EXPORT_TOO_LARGE | More than maxInvoices in range; details: { count, max } |
401 | — | Missing or invalid token |
403 | — | Caller lacks BILLING:read |
404 | INVOICE_EXPORT_EMPTY | No issued invoices of the requested type in that range |
429 | INVOICE_EXPORT_IN_PROGRESS | The clinic already has an export running, or exceeded 10 exports/minute |
curl -X GET "https://api.nevatal.com/api/v1/billing/invoices/pdf-export?from=2026-08-01&to=2026-08-31" \
-H "Authorization: Bearer nvtl_your_api_key" \
-o invoices.zip
HTTP/1.1 200 OK
Content-Type: application/zip
Content-Disposition: attachment; filename="invoices_2026-08-01_2026-08-31.zip"
Content-Length: 1843220
{
"success": false,
"error": "The end date must be on or after the start date.",
"code": "VALIDATION_ERROR",
"correlationId": "req-1d2e",
"details": { "field": "to" }
}
{
"success": false,
"error": "The range has more invoices than can be downloaded together. Narrow the date range.",
"code": "INVOICE_EXPORT_TOO_LARGE",
"correlationId": "req-8f4a",
"details": { "count": 181, "max": 100 }
}
{
"success": false,
"error": "There are no issued invoices in that date range.",
"code": "INVOICE_EXPORT_EMPTY",
"correlationId": "req-3b7c"
}

