Authentication
Create an account and open your workspace. Send the API key in the Authorization header. Keep it on your server, never in public browser code.
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Base URL: https://pdf.kvadrati.com
Turnstile protects website forms. The conversion API uses your API key and does not need a Turnstile token.
POST /pdf/from-htmlHTML → PDF
Send HTML and an optional filename. The result is a binary A4 PDF with backgrounds included.
| Field | Description |
|---|
html | Required string. HTML document with CSS. |
fileName | Optional string. The .pdf extension is added automatically. |
{
"html": "<html><body><h1>Hello PDF</h1></body></html>",
"fileName": "report.pdf"
}
200 OK · Content-Type: application/pdf
POST /pdf/from-urlURL → PDF
Send a publicly accessible URL. The service fetches its HTML and resolves relative resource links. Pages requiring sign-in or an interactive session are not suitable.
{
"url": "https://example.com/report",
"fileName": "report.pdf"
}
The URL must use HTTP or HTTPS. Only use content you are authorised to access and convert.
Integration examples
cURL
curl https://pdf.kvadrati.com/pdf/from-html \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"html":"<h1>Hello PDF</h1>","fileName":"report.pdf"}' \
--output report.pdf
Python
import os
import requests
response = requests.post(
"https://pdf.kvadrati.com/pdf/from-html",
headers={"Authorization": "Bearer " + os.environ["PDF_API_KEY"]},
json={"html": "<h1>Hello PDF</h1>", "fileName": "report.pdf"},
timeout=60,
)
response.raise_for_status()
with open("report.pdf", "wb") as file:
file.write(response.content)
C# / .NET 10
using System.Net.Http.Headers;
using System.Net.Http.Json;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Bearer", Environment.GetEnvironmentVariable("PDF_API_KEY"));
using var response = await client.PostAsJsonAsync(
"https://pdf.kvadrati.com/pdf/from-html",
new { html = "<h1>Hello PDF</h1>", fileName = "report.pdf" });
response.EnsureSuccessStatusCode();
await File.WriteAllBytesAsync("report.pdf", await response.Content.ReadAsByteArrayAsync());
Limits and errors
A free account has 2 conversions per day. The daily period uses UTC; a failed conversion can consume an attempt. Enquire for higher volumes.
| HTTP | Meaning |
|---|
| 400 | Invalid or missing API key, empty input or daily quota reached. |
| 429 | Too many requests. Wait before retrying. |
| 500 | Content retrieval or PDF generation failed. |
Check HTTP status before saving a response. Error responses are not PDF files.
GET /pdf/pingA simple service availability check, without an API key.