Overview
A Peppol invoice is a UBL XML file. A file that the receiver must get (for example a PDF copy of the invoice or a timesheet) must be embedded in that UBL. There are three methods to add a file to a document. Only two of them put the file in the UBL.This page is about files that go out with a document. To use a PDF as the input from which a document is created, see Create documents from PDF.
Add attachments when you create the document
Add anattachments array to the body of POST /api/documents/. The API embeds each file in the UBL as an AdditionalDocumentReference and stores it with the document.
string
required
File name with extension, for example
timesheet-2026-09.pdf. The receiver sees this name.string
default:"application/pdf"
MIME type of the file. See the permitted types below.
string
File content, base64 encoded. Always supply this field when you create a document.
integer
default:"0"
Optional. The API calculates the stored size from the decoded
file_data.peppol_ids of your company.
The API returns 201 Created with the document in the DRAFT state. The response below shows only the fields that are related to attachments.
Permitted file types
Peppol rule BR-CL-24 permits only these MIME types for a file that is embedded in the UBL:
If
file_type is not one of these values, the API uses the extension of file_name (.pdf, .png, .jpg, .jpeg, .csv, .xlsx, .ods) to find the MIME type that it writes to the UBL. Give each file a correct extension.
File size
The API does not publish a size limit for the files inattachments[]. Base64 makes the request body approximately one third larger than the file, and the receiving Access Point must accept the full UBL. Keep attachments small, and send large supporting files through a different channel.
The limits of 5 MB for each file and 25 MB for each batch apply to the PDF conversion endpoint only. See Create documents from PDF.
Validation is not a separate mandatory call.
POST /api/documents/ rejects a payload that does not pass the same rules. Use POST /api/validate/json while you develop, because it returns all rule failures and the generated UBL.Let the platform make the PDF
Add the query parameterconstruct_pdf=true to POST /api/documents/. The API then does these steps:
1
Generate the UBL
The API converts the JSON body to UBL and validates it.
2
Render the PDF
The API makes a PDF from that UBL.
3
Embed the PDF
The API adds the PDF to the attachments of the document, generates the UBL again with the PDF embedded, and validates the result.
attachments array, the generated PDF is added after those files, and the UBL contains all of them.
boolean
default:"false"
If
true, the API generates a PDF from the document, stores it as an attachment and embeds it in the UBL.invoice.json. Save this payload in that file:
Invoice
peppol_ids of your company.
File name of the generated PDF
- The name is
<invoice_id>-generated.pdf. - Each character of
invoice_idthat is not a letter, a digit,-,_or.becomes-. For example,INV/2026 001givesINV-2026-001-generated.pdf. - If the document has no
invoice_id, the name is a random UUID followed by-generated.pdf.
Errors
Deprecated upload endpoint
Existing integrations that use this endpoint send amultipart/form-data request with one file in the form field file:
cURL
List, download and delete attachments
These calls work for documents that you created and for documents that you received.List the attachments of a document
cURL
If the document has no attachments, this call returns
404 with the detail Document attachments not found. It does not return an empty array. Treat this response as an empty list.Download one attachment
Get the attachment to receive afile_url. This is a signed URL that is valid for 1 hour. Download the file from that URL with a plain GET request, without the Authorization header.
cURL
cURL
file_url. Request a new URL each time that you need the file.
Delete an attachment
You can delete an attachment only while the document is in theDRAFT or FAILED state.
cURL
For the states of a document, see Document lifecycle and delivery tracking.
Download the UBL
GET /api/documents/{document_id}/ubl returns the metadata of the UBL file of a document and a signed URL from which you can download the XML. Use it to see what the receiver gets, or to archive the UBL of a received document.
cURL
Fields that have no value are not in the response. The call returns
404 if the document has no UBL. Do not store signed_url. For a download sample in five languages, see Download the original UBL.
Uploaded UBL and received documents
You do not add attachments separately in these two cases. The files are already in the UBL.- Documents that you create from UBL. When you upload a UBL file with
POST /api/documents/ubl, the API extracts each embedded file and stores it as an attachment of the document. The UBL is not changed. See Send UBL documents. - Received documents. The API extracts each file that the sender embedded and stores it as an attachment. If the received UBL contains no PDF, the API generates a PDF from the UBL and stores it as an attachment with the name
<document_id>.pdf. Thus a received document usually has a PDF that you can show to a person. See Receive documents.
Test with a sandbox company
Develop and test with a sandbox company. A sandbox company runs in test mode: the API sends each document as UBL XML to the contact email address of the company, and nothing goes to the Peppol network. The API host and the endpoints are the same as for a production company. See Test mode and sandbox companies.
attachments[] or construct_pdf=true in a sandbox company, send it, and open the XML from the email. Each file is in an AdditionalDocumentReference element as base64 content.
Next Steps
Create e-invoices
Build the invoice body to which you add attachments.
Create documents from PDF
Use a PDF as the input for a new document.
Receive documents
Read received invoices and their attachments.
Validation during development
Examine the generated UBL before you create a document.