How to download invoice PDFs from Xero
The Apideck Accounting unified API doesn't expose invoice PDF download as a unified operation, but you can retrieve them via the Proxy API. This guide shows how to do this for Xero.
The flow is two steps: use the unified GET /accounting/invoices endpoint to find the invoice you want, then use its id in a Proxy API call to download the PDF.
Xero's invoice endpoint serves both JSON and PDF off the same URL - only the Accept header changes the response type.
Prerequisites
An active Apideck Vault connection for Xero (
service-id: xero)The Apideck
consumer-id,app-id, andapi-keyAn invoice in Xero with a status of
SUBMITTED,AUTHORISED, orPAID(drafts cannot be rendered as PDF)The invoice must be of type
ACCREC(accounts receivable).ACCPAYinvoices don't support PDF rendering via the API.
Step 1: Find the invoice ID
Use the unified Accounting API to list invoices and find the one you want:
curl --location 'https://unify.apideck.com/accounting/invoices' \
--header 'Authorization: Bearer {APIDECK_API_KEY}' \
--header 'x-apideck-app-id: {APP_ID}' \
--header 'x-apideck-consumer-id: {CONSUMER_ID}' \
--header 'x-apideck-service-id: xero'
The response contains an array of invoices. Copy the id of the invoice you want as a PDF - you'll use it in the next step. The unified id is the same as Xero's InvoiceID GUID.
Step 2: Download the PDF via Proxy
curl --location 'https://unify.apideck.com/proxy' \
--header 'Authorization: Bearer {APIDECK_API_KEY}' \
--header 'x-apideck-app-id: {APP_ID}' \
--header 'x-apideck-consumer-id: {CONSUMER_ID}' \
--header 'x-apideck-service-id: xero' \
--header 'x-apideck-downstream-url: https://api.xero.com/api.xro/2.0/Invoices/{INVOICE_ID}' \
--header 'Accept: application/pdf' \
--output xero-invoice.pdf
The Apideck Proxy detects the binary response and base64-encodes it internally; API Gateway decodes it back to raw bytes before delivery, so your HTTP client receives a normal PDF binary.
Gotchas
Draft invoices won't render. Xero only generates PDFs for invoices in SUBMITTED, AUTHORISED, or PAID status. If you call the endpoint for a draft, you'll get a JSON error response instead of a PDF. To fix it, transition the invoice to one of the renderable statuses first.
The same URL serves JSON and PDF. If you accidentally send Accept: application/json (or no Accept header), you'll get the invoice's JSON representation back. Always set Accept: application/pdf explicitly.
