· 12 min read
How to generate PDF invoices from JSON without layout libraries
Practical guide: from a JSON dictionary to a multi-page PDF invoice with a single REST call — no mPDF, iText, or X/Y coordinates.
Generating PDF invoices from application data is a standard requirement for almost every web application, business management system, and ERP. Yet anyone who has tried to implement this feature knows it quickly turns into a development nightmare.
Writing code to manually calculate pixel coordinates (X and Y), handle page breaks for tables with dozens of rows, prevent text from being cut in half, and configure custom fonts takes hours of work. And every time the sales team or the client asks for a layout change (even just moving the logo), the developer has to touch the source code again, retest, and redeploy.
In this guide we will show how to leave that outdated approach behind and generate a professional multi-page PDF invoice from a simple JSON dictionary, using a single HTTP REST call and delegating layout management to an external cloud engine — with no layout libraries in your stack (PHP, Node.js, C#, Python).
The problem with traditional PDF libraries (mPDF, FPDF, iText, PDFSharp)
Old-style PDF rendering libraries (whether in PHP, Node.js, C#, or Python) present three fundamental problems for modern software houses:
- Coupling between data and layout: the code that fetches data from the database is mixed with the graphic instructions that draw the tables.
- Poor flexibility: changing an invoice template requires code changes and deploy cycles.
- Resource consumption: generating large PDFs is a CPU-intensive operation that can slow down the main application if it is not properly isolated.
Separating data from design is the solution: the backend application only needs to collect the data, format it into a clean JSON object, and send it to a document generation API that returns a ready PDF. If you are looking for how to generate PDFs from JSON, create PDF invoices via API, or an alternative to C# / PHP / Node PDF libraries, this is the modern JSON-to-PDF pattern.
Step 1: structure the invoice JSON payload
The first step is to define the data structure. A well-designed JSON dictionary for an invoice must contain issuer data, customer data, document metadata, and the array of line items.
Here is an example of a standardized payload (copy it and adapt it to your template schema):
{
"documento": {
"tipo": "Fattura Differita",
"numero": "FPA-2026-1044",
"data": "18/07/2026",
"valuta": "EUR"
},
"emittente": {
"ragione_sociale": "Sviluppo Software S.r.l.",
"partita_iva": "IT01234567890",
"indirizzo": "Via dell'Innovazione 42",
"cap_citta": "66034 Lanciano (CH)",
"email": "amministrazione@softwarehouse.it"
},
"cliente": {
"ragione_sociale": "Azienda Cliente SpA",
"partita_iva": "IT09876543210",
"indirizzo": "Corso Vittorio Emanuele II, 100",
"cap_citta": "00100 Roma (RM)"
},
"righe_fattura": [
{
"codice": "SW-SAAS-01",
"descrizione": "Abbonamento Cloud SaaS QuartzAPI - Licenza Enterprise (Mensile)",
"quantita": 1,
"prezzo_unitario": 249.00,
"aliquota_iva": 22
},
{
"codice": "CONS-PRO-02",
"descrizione": "Attività di integrazione sistemi ERP e configurazione Webhook",
"quantita": 8,
"prezzo_unitario": 75.00,
"aliquota_iva": 22
}
],
"totali": {
"imponibile": 849.00,
"imposta": 186.78,
"totale_documento": 1035.78
}
}
Step 2: configure the template on the cloud portal
Instead of coding foreach loops to print table rows in the PDF,
you upload a graphic template (visual Template Builder) to the QuartzAPI portal. In the template you insert
placeholders that match the JSON keys (e.g. a field bound to cliente.ragione_sociale).
The engine reads the righe_fattura array and automatically iterates the table Details band,
calculating where to break the page if items span 2, 3, or more pages, while keeping the header
and footer. No X/Y coordinates to write in your business application.
Step 3: call the Web API to generate the PDF
Once the template is configured (template code in the portal, e.g. INVOICE1) and you have the API key,
your application sends an HTTP POST request. QuartzAPI generates the PDF and can save it in a document
folder (folderId) ready for download and email delivery.
Endpoint: POST …/index.php?r=api/v1-jobs/generate-document
— body with templateCode, data (the JSON above) and optional folderId.
Documentation: Web API.
Example in Node.js (Axios)
const axios = require('axios');
const payloadFattura = { /* ... the JSON defined above ... */ };
async function generaFattura() {
try {
const response = await axios.post(
'https://backend.quartzapi.com/index.php?r=api/v1-jobs/generate-document',
{
templateCode: 'INVOICE1',
folderId: 'fld_ESEMPIO_CARTELLA',
externalId: 'FPA-2026-1044',
outputFormat: 'pdf',
data: payloadFattura
},
{
headers: {
Authorization: 'Bearer TUO_API_KEY_SEGRETA',
'Content-Type': 'application/json'
}
}
);
console.log('PDF generated successfully!', response.data);
// result.documentId and downloadUrl for secure download
} catch (error) {
console.error(
'Error during PDF generation:',
error.response ? error.response.data : error.message
);
}
}
generaFattura();
Example in PHP (cURL)
<?php
$payloadFattura = [ /* ... the JSON dictionary as a PHP array ... */ ];
$ch = curl_init('https://backend.quartzapi.com/index.php?r=api/v1-jobs/generate-document');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
'templateCode' => 'INVOICE1',
'folderId' => 'fld_ESEMPIO_CARTELLA',
'externalId' => 'FPA-2026-1044',
'outputFormat' => 'pdf',
'data' => $payloadFattura,
]));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer TUO_API_KEY_SEGRETA',
'Content-Type: application/json',
]);
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo 'cURL error: ' . curl_error($ch);
} else {
$data = json_decode($response, true);
echo 'Document saved. documentId: ' . ($data['result']['documentId'] ?? '');
}
curl_close($ch);
Next steps: download and automatic email delivery
One of the biggest advantages of an API-based approach is flexibility after generation. Since the PDF is stored in the portal folders:
-
On-demand download: download the file with
GET …/index.php?r=api/v1-documents/download&uid={documentId}. -
Built-in email delivery: call
POST …/index.php?r=api/v1-jobs/send-documentpassing thedocumentIdand the recipients. You can use the SMTP configured on the API key, without managing a complex mailer in your business app.
Conclusions
Treating PDF documents as graphic code to maintain is technical debt that software houses can no longer afford. Moving to a JSON-to-PDF architecture via API reduces development time, isolates the computational load, and allows non-technical roles to update templates without touching a single line of application code.
Ready to remove PDF libraries from your code? QuartzAPI is in public Beta: sign up for free, get your API key, and test invoice and report generation by sending your JSON objects.
Ready-to-use snippets
- Copy the JSON and the Node/PHP examples above and replace
INVOICE1/ API key. - In the portal: Templates → JSON Postman for a body already aligned with your template.
- Full reference: Web API documentation.