Skip to main content

Overview

The e-invoice.be API allows you to create documents directly from PDF files. This is useful when:
  • You have existing PDF invoices you want to send via Peppol
  • Your system generates PDF invoices but not structured data
  • You want to digitize paper invoices
  • You’re migrating from traditional PDF invoicing to e-invoicing

How It Works

There are two modes for PDF document creation:
  1. PDF with JSON metadata - Provide both PDF and structured data
  2. PDF with auto-extraction - Let AI extract invoice data from the PDF (optional feature)

Method 1: PDF with JSON Metadata

This is the recommended approach - you provide both the PDF and the structured invoice data.

Step 1: Prepare Your Data

You’ll need:
  • The PDF file
  • Invoice data in JSON format (same as regular invoice creation)

Step 2: Upload PDF with Metadata

curl -X POST "https://api.e-invoice.be/api/documents/pdf" \
     -H "Authorization: Bearer YOUR_API_KEY" \
     -F "[email protected]" \
     -F 'data={
       "document_type": "INVOICE",
       "invoice_id": "INV-2024-001",
       "invoice_date": "2024-10-24",
       "currency": "EUR",
       "vendor_name": "Your Company BVBA",
       "vendor_tax_id": "0208:0123456789",
       "vendor_address": "Main Street 123, 1000 Brussels, Belgium",
       "customer_name": "Customer Company NV",
       "customer_tax_id": "0208:0987654321",
       "customer_address": "Customer Lane 456, 2000 Antwerp, Belgium",
       "items": [
         {
           "description": "Professional Services",
           "quantity": 10,
           "unit": "C62",
           "unit_price": 100.00,
           "tax_rate": "21.00"
         }
       ]
     }'

Response

{
  "id": "doc_abc123",
  "type": "INVOICE",
  "state": "DRAFT",
  "invoice_number": "INV-2024-001",
  "has_pdf": true,
  "created_at": 1729468923
}

Step 3: Send via Peppol

curl -X POST "https://api.e-invoice.be/api/documents/doc_abc123/send" \
     -H "Authorization: Bearer YOUR_API_KEY"

Method 2: PDF with Auto-Extraction (Optional)

PDF auto-extraction is an optional feature that requires AI-powered data extraction. Contact [email protected] to enable this feature for your account.
With auto-extraction enabled, you can upload a PDF and have the system extract invoice data automatically.

Upload PDF for Auto-Extraction

curl -X POST "https://api.e-invoice.be/api/documents/pdf" \
     -H "Authorization: Bearer YOUR_API_KEY" \
     -F "[email protected]" \
     -F "auto_extract=true"

Response

{
  "id": "doc_abc123",
  "type": "INVOICE",
  "state": "DRAFT",
  "invoice_number": "INV-2024-001",
  "extracted_data": {
    "invoice_number": "INV-2024-001",
    "issue_date": "2024-10-24",
    "total_amount": 1210.00,
    "supplier_name": "Your Company",
    "customer_name": "Customer Company"
  },
  "extraction_confidence": 0.95,
  "requires_review": false
}
Auto-extracted data should always be reviewed before sending, especially for the first few invoices. The extraction_confidence score indicates how confident the system is in the extracted data.

Code Examples

Node.js - PDF with Metadata

const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');

async function uploadPDFInvoice(pdfPath, invoiceData) {
  const formData = new FormData();

  // Add PDF file
  formData.append('pdf', fs.createReadStream(pdfPath));

  // Add invoice data as JSON
  formData.append('data', JSON.stringify(invoiceData));

  try {
    const response = await axios.post(
      'https://api.e-invoice.be/api/documents/pdf',
      formData,
      {
        headers: {
          'Authorization': `Bearer ${process.env.E_INVOICE_API_KEY}`,
          ...formData.getHeaders()
        }
      }
    );

    console.log('Document created:', response.data.id);
    return response.data;

  } catch (error) {
    console.error('Error:', error.response?.data || error.message);
  }
}

// Usage
const invoiceData = {
  document_type: 'INVOICE',
  invoice_id: 'INV-2024-001',
  invoice_date: '2024-10-24',
  currency: 'EUR',
  vendor_name: 'Your Company BVBA',
  vendor_tax_id: '0208:0123456789',
  vendor_address: 'Main Street 123, 1000 Brussels, Belgium',
  customer_name: 'Customer Company NV',
  customer_tax_id: '0208:0987654321',
  customer_address: 'Customer Lane 456, 2000 Antwerp, Belgium',
  items: [
    {
      description: 'Professional Services',
      quantity: 10,
      unit: 'C62',
      unit_price: 100.00,
      tax_rate: '21.00'
    }
  ]
};

uploadPDFInvoice('./invoice.pdf', invoiceData);

Python - PDF with Metadata

import requests
import os
import json

API_KEY = os.environ.get('E_INVOICE_API_KEY')
BASE_URL = 'https://api.e-invoice.be'

def upload_pdf_invoice(pdf_path, invoice_data):
    headers = {
        'Authorization': f'Bearer {API_KEY}'
    }

    files = {
        'pdf': open(pdf_path, 'rb'),
        'data': (None, json.dumps(invoice_data), 'application/json')
    }

    try:
        response = requests.post(
            f'{BASE_URL}/api/documents/pdf',
            headers=headers,
            files=files
        )

        response.raise_for_status()
        print(f'Document created: {response.json()["id"]}')
        return response.json()

    except Exception as error:
        print(f'Error: {error}')

# Usage
invoice_data = {
    'document_type': 'INVOICE',
    'invoice_id': 'INV-2024-001',
    'invoice_date': '2024-10-24',
    'currency': 'EUR',
    'vendor_name': 'Your Company BVBA',
    'vendor_tax_id': '0208:0123456789',
    'vendor_address': 'Main Street 123, 1000 Brussels, Belgium',
    'customer_name': 'Customer Company NV',
    'customer_tax_id': '0208:0987654321',
    'customer_address': 'Customer Lane 456, 2000 Antwerp, Belgium',
    'items': [
        {
            'description': 'Professional Services',
            'quantity': 10,
            'unit': 'C62',
            'unit_price': 100.00,
            'tax_rate': '21.00'
        }
    ]
}

upload_pdf_invoice('./invoice.pdf', invoice_data)

Node.js - PDF with Auto-Extraction

const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');

async function uploadPDFWithAutoExtraction(pdfPath) {
  const formData = new FormData();

  formData.append('pdf', fs.createReadStream(pdfPath));
  formData.append('auto_extract', 'true');

  try {
    const response = await axios.post(
      'https://api.e-invoice.be/api/documents/pdf',
      formData,
      {
        headers: {
          'Authorization': `Bearer ${process.env.E_INVOICE_API_KEY}`,
          ...formData.getHeaders()
        }
      }
    );

    console.log('Document created:', response.data.id);
    console.log('Extraction confidence:', response.data.extraction_confidence);

    if (response.data.requires_review) {
      console.log('⚠️  Please review extracted data before sending');
      console.log('Extracted data:', response.data.extracted_data);
    }

    return response.data;

  } catch (error) {
    console.error('Error:', error.response?.data || error.message);
  }
}

// Usage
uploadPDFWithAutoExtraction('./invoice.pdf');

Complete Workflow Example

Here’s a complete example that validates, creates, and sends a PDF invoice:
const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');

const api = axios.create({
  baseURL: 'https://api.e-invoice.be',
  headers: {
    'Authorization': `Bearer ${process.env.E_INVOICE_API_KEY}`
  }
});

async function createAndSendPDFInvoice(pdfPath, invoiceData) {
  try {
    // 1. Validate JSON data first
    console.log('Validating invoice data...');
    const validation = await api.post('/api/validate/json', invoiceData);

    if (!validation.data.valid) {
      console.error('Validation failed:', validation.data.errors);
      return;
    }

    console.log('✓ Invoice data is valid');

    // 2. Upload PDF with metadata
    console.log('Uploading PDF invoice...');
    const formData = new FormData();
    formData.append('pdf', fs.createReadStream(pdfPath));
    formData.append('data', JSON.stringify(invoiceData));

    const document = await api.post('/api/documents/pdf', formData, {
      headers: formData.getHeaders()
    });

    console.log('✓ Document created:', document.data.id);

    // 3. Send via Peppol
    console.log('Sending document...');
    const result = await api.post(`/api/documents/${document.data.id}/send`);
    console.log('✓ Document sent:', result.data.state);

    return document.data;

  } catch (error) {
    console.error('Error:', error.response?.data || error.message);
  }
}

// Usage
const invoiceData = {
  document_type: 'INVOICE',
  invoice_id: 'INV-2024-001',
  invoice_date: '2024-10-24',
  currency: 'EUR',
  vendor_name: 'Your Company BVBA',
  vendor_tax_id: '0208:0123456789',
  vendor_address: 'Main Street 123, 1000 Brussels, Belgium',
  customer_name: 'Customer Company NV',
  customer_tax_id: '0208:0987654321',
  customer_address: 'Customer Lane 456, 2000 Antwerp, Belgium',
  items: [
    {
      description: 'Professional Services',
      quantity: 10,
      unit: 'C62',
      unit_price: 100.00,
      tax_rate: '21.00'
    }
  ]
};

createAndSendPDFInvoice('./invoice.pdf', invoiceData);

PDF Requirements

File Format

  • Format: PDF (Portable Document Format)
  • Max size: 10 MB
  • Version: PDF 1.4 or higher
  • Content: Must contain readable text (not just images)
Scanned PDFs (images only) require OCR processing. For best results with auto-extraction, use PDFs generated from digital sources.

Best Practices for PDFs

  1. Use text-based PDFs: Generated from software rather than scanned
  2. Clear layout: Structured format with clear sections
  3. Readable fonts: Standard fonts, minimum 8pt size
  4. Complete information: All required invoice fields visible
  5. Single invoice per PDF: Don’t combine multiple invoices

Attachments vs PDF Documents

There’s a difference between:
  1. PDF as document (POST /api/documents/pdf) - PDF is the main invoice
  2. PDF as attachment (POST /api/documents/{id}/attachments) - Adding supporting PDFs to existing documents

Adding PDF Attachments to Existing Documents

# First create the document (JSON or UBL)
curl -X POST "https://api.e-invoice.be/api/documents/" \
     -H "Authorization: Bearer YOUR_API_KEY" \
     -d '{ invoice data }'

# Then add PDF as attachment
curl -X POST "https://api.e-invoice.be/api/documents/doc_abc123/attachments" \
     -H "Authorization: Bearer YOUR_API_KEY" \
     -F "[email protected]" \
     -F "description=Invoice PDF copy"

Retrieving PDF Documents

Get Document with PDF

curl -X GET "https://api.e-invoice.be/api/documents/doc_abc123" \
     -H "Authorization: Bearer YOUR_API_KEY"
Response includes has_pdf flag:
{
  "id": "doc_abc123",
  "type": "INVOICE",
  "invoice_number": "INV-2024-001",
  "has_pdf": true,
  "pdf_url": "https://api.e-invoice.be/api/documents/doc_abc123/pdf"
}

Download PDF

curl -X GET "https://api.e-invoice.be/api/documents/doc_abc123/pdf" \
     -H "Authorization: Bearer YOUR_API_KEY" \
     --output invoice.pdf

Auto-Extraction Confidence Levels

When using auto-extraction, the system returns a confidence score:
ConfidenceMeaningAction
0.95 - 1.0Very HighGenerally safe to use
0.80 - 0.94HighReview key fields (amounts, dates)
0.60 - 0.79MediumManual review required
< 0.60LowManual data entry recommended
if (response.data.extraction_confidence < 0.80) {
  console.warn('Low confidence - manual review required');
  // Present extracted data to user for verification
  reviewExtractionData(response.data.extracted_data);
} else {
  // Proceed with extracted data
  sendDocument(response.data.id);
}

Common Issues

PDF Too Large

Error: File size exceeds maximum limit Solution:
  • Compress the PDF
  • Use a lower resolution for images within the PDF
  • Split into multiple documents if necessary

Invalid PDF Format

Error: Invalid PDF file or corrupted Solution:
  • Ensure file is a valid PDF
  • Try re-generating the PDF
  • Check for file corruption

Extraction Failed

Error: Could not extract data from PDF Solution:
  • Provide JSON metadata instead
  • Ensure PDF contains readable text
  • Check if PDF is encrypted or password-protected

Missing Required Fields

Error: Missing required field: customer_tax_id Solution: Ensure all required Peppol fields are in the JSON metadata:
  • Vendor and customer Peppol IDs (vendor_tax_id, customer_tax_id)
  • Invoice ID, date, currency
  • At least one item with description, quantity, unit price, and tax rate

Best Practices

Even if using auto-extraction, providing complete JSON metadata ensures:
  • Accurate UBL generation
  • Proper Peppol compliance
  • Faster processing
  • No extraction errors
// ✓ Good: Provide complete data
formData.append('data', JSON.stringify(completeInvoiceData));

// ✗ Risky: Rely only on extraction
formData.append('auto_extract', 'true');
Validate your JSON data before uploading:
// Validate first
await api.post('/api/validate/json', invoiceData);

// Then upload PDF
await api.post('/api/documents/pdf', formData);
Store original PDFs for audit purposes:
const backup = `./backup/${invoiceNumber}.pdf`;
fs.copyFileSync(pdfPath, backup);
Name PDFs clearly for tracking:
✓ Good: INV-2024-001_CustomerName.pdf
✗ Poor: invoice.pdf
Track extraction confidence over time:
const stats = {
  total: 0,
  high_confidence: 0,
  requires_review: 0
};

if (response.data.extraction_confidence > 0.9) {
  stats.high_confidence++;
}

Next Steps