Manage invoice attachments

This guide explains how to add, read, and interpret attachments when working with invoices via API or XML.

Choose a workflow

  • Create with JSON: create the invoice first, then add attachments with add_attachment or add_attachments.
  • Import XML with embedded attachments: include attachments inside the XML and import the file.
  • Import PDF with embedded XML (received invoices): if the PDF contains an embedded XML (Factur-X/ZUGFeRD), B2Brouter can extract it and create the received invoice.

Important principles

  • XML is the legal, structured source. Your PDF must be consistent with the XML data. Do not try to change the XML structure to match a custom PDF layout; the XML must follow standardized schemas so any receiver can process it.
  • Attachments are complementary. A PDF (or any attachment) is not an electronic invoice and does not enable automated processing by itself. Use attachments as supporting documents, not as the primary data source.

Add attachments to an existing invoice

Add a single attachment (recommended for PDF preview)

First, you must create or import an invoice.

After creating the invoice, an attachment is added by making a POST request to the /invoices/{id}/add_attachment endpoint. The request must send the raw file bytes as the body and include the file name using the filename query parameter.

If the attached PDF should be used as the visual and legal representation of the invoice, the use_as_pdf_view=true parameter must also be provided.

curl -X POST \
  'https://api-staging.b2brouter.net/invoices/12345/add_attachment?filename=invoice.pdf&use_as_pdf_view=true' \
  -H 'X-B2B-API-Key: {YOUR_API_KEY}' \
  -H 'X-B2B-API-Version: {YOUR_API_VERSION}' \
  -H 'Content-Type: application/octet-stream' \
  --data-binary '@invoice.pdf'

Notes:

  • The API expects Content-Type: application/octet-stream.
  • Raw bytes are recommended; base64 or data-URI payloads also work.
  • use_as_pdf_view=true marks the PDF as the visual/legal PDF (only one per invoice).
  • If you modify the invoice later, the same PDF is still used unless replaced.

Add multiple attachments (ZIP)

Use the ZIP endpoint when you need to upload multiple files in one call.

zip attachments.zip file1.pdf file2.xml
curl -X POST \
  'https://api-staging.b2brouter.net/invoices/12345/add_attachments' \
  -H 'X-B2B-API-Key: {YOUR_API_KEY}' \
  -H 'X-B2B-API-Version: {YOUR_API_VERSION}' \
  -H 'accept: application/json' \
  -F '[email protected]'

If you need to set a PDF as the invoice preview, first upload that PDF using the add_attachment endpoint with the use_as_pdf_view=true query parameter, and then upload the rest with the add_attachments endpoint.

Add attachments when importing an invoice XML

If you already generate XML (UBL, Facturae, CII, etc.), you can embed attachments in the XML and import the file. The attachments will be extracted and stored automatically.

UBL (Peppol)

<cac:AdditionalDocumentReference>
  <cbc:ID>ATT-1</cbc:ID>
  <cac:Attachment>
    <cbc:EmbeddedDocumentBinaryObject
      mimeCode="application/pdf"
      filename="invoice.pdf">BASE64_DATA</cbc:EmbeddedDocumentBinaryObject>
  </cac:Attachment>
</cac:AdditionalDocumentReference>

Facturae

<AdditionalData>
  <RelatedDocuments>
    <Attachment>
      <AttachmentCompressionAlgorithm>NONE</AttachmentCompressionAlgorithm>
      <AttachmentFormat>PDF</AttachmentFormat>
      <AttachmentEncoding>BASE64</AttachmentEncoding>
      <AttachmentDescription>invoice.pdf</AttachmentDescription>
      <AttachmentData>BASE64_DATA</AttachmentData>
    </Attachment>
  </RelatedDocuments>
</AdditionalData>

CII / ZUGFeRD

<ram:AdditionalReferencedDocument>
  <ram:AttachmentBinaryObject
    mimeCode="application/pdf"
    filename="invoice.pdf">BASE64_DATA</ram:AttachmentBinaryObject>
</ram:AdditionalReferencedDocument>

Encoding details:

  • Base64 is the default encoding.
  • If the XML includes an explicit encoding code, supported values are BASE64, BER, and DER.
  • In Facturae, AttachmentCompressionAlgorithm can be ZIP or GZIP.
  • If compression is not defined, content is decoded as plain base64.

Use your own PDF in ZUGFeRD / Factur-X

To send a hybrid PDF (PDF + embedded XML) using your own layout:

  1. Choose a hybrid document type in the contact (for example: pdf.a.invoice.with.xml.cii.cross_industry_invoice.facturx.en16931).
  2. Create the invoice as usual.
  3. Upload your PDF with use_as_pdf_view=true.
  4. Send the invoice.

Contact example:

{
  "contact": {
    "name": "Example GmbH",
    "tin_scheme": "9930",
    "tin_value": "DE8******3",
    "transport_type_code": "email",
    "document_type_code": "pdf.a.invoice.with.xml.cii.cross_industry_invoice.facturx.en16931"
  }
}

To list available document types, use the document types endpoint GET /document_types.

How attachments appear in API responses

  • The attachments array in get invoice endpoint GET /invoices/{id} includes the normal files you uploaded to the invoice (it does not include the PDF marked as pdf_view).
  • A PDF uploaded with use_as_pdf_view=true is used as the visual/legal PDF and does not appear in the attachments array.
  • After sending an issued invoice, download_legal_url points to the legal PDF (generated by B2Brouter or your pdf_view if provided).

Read attachments from received invoices

When you retrieve a received invoice, the response includes an attachments array with download links:

{
  "attachments": [
    {
      "link": "/attachments/download/253526/2025-02-10_1_original.pdf",
      "content_type": "application/pdf"
    }
  ]
}

To download the file use the endpoint GET /attachments/download/{id}/{filename}

Include your API key header when downloading. The id comes from the link.

Delete attachments

Deletion is possible from the web app, but there is no public API endpoint. If an attachment was imported incorrectly and you need an automated flow, the recommended approach is to delete the invoice and submit it again without the wrong attachment.

Limits and transport constraints

  • B2Brouter allows up to 50 MB per file. If you send by email, the total attachment size is limited to 40 MB. Some networks may enforce lower limits (10–20 MB), depending on the channel.
  • Expected formats: PDF and XML, plus common office files (for example CSV). Executable or script formats are blocked (for example .exe, .js, .bat, .sh, .jar, .ps1, .html, .gif).
  • Some transports are configured as "without embedded attachments" (detached), so attachments are not included in the XML sent to the receiver.
  • Some recipient systems ignore embedded attachments even if they are present.
  • If the invoice is not successfully sent, the recipient will not see the PDF regardless of attachments.
  • The endpoint add_attachment requires Content-Type: application/octet-stream and a filename query parameter.