Generate PDF
curl --request POST \
--url https://api.pdfdyno.com/v1/pdf/generate \
--header 'Content-Type: <content-type>' \
--data '
{
"data": {},
"template": "<string>"
}
'import requests
url = "https://api.pdfdyno.com/v1/pdf/generate"
payload = {
"data": {},
"template": "<string>"
}
headers = {"Content-Type": "<content-type>"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': '<content-type>'},
body: JSON.stringify({data: {}, template: '<string>'})
};
fetch('https://api.pdfdyno.com/v1/pdf/generate', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.pdfdyno.com/v1/pdf/generate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'data' => [
],
'template' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: <content-type>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.pdfdyno.com/v1/pdf/generate"
payload := strings.NewReader("{\n \"data\": {},\n \"template\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "<content-type>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.pdfdyno.com/v1/pdf/generate")
.header("Content-Type", "<content-type>")
.body("{\n \"data\": {},\n \"template\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.pdfdyno.com/v1/pdf/generate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = '<content-type>'
request.body = "{\n \"data\": {},\n \"template\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"error": "Invalid Typst syntax on line 2"
}
{
"error": "Missing or invalid API Key"
}
{
"error": "Payload exceeds 10MB limit"
}
{
"error": "Rate limit exceeded"
}
{
"error": "An unexpected error occurred during document compilation."
}
{
"error": "Service temporarily unavailable. Please try again later."
}
API Reference
Generate PDF
Generates a PDF document from a JSON payload and a Typst template string.
POST
/
v1
/
pdf
/
generate
Generate PDF
curl --request POST \
--url https://api.pdfdyno.com/v1/pdf/generate \
--header 'Content-Type: <content-type>' \
--data '
{
"data": {},
"template": "<string>"
}
'import requests
url = "https://api.pdfdyno.com/v1/pdf/generate"
payload = {
"data": {},
"template": "<string>"
}
headers = {"Content-Type": "<content-type>"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': '<content-type>'},
body: JSON.stringify({data: {}, template: '<string>'})
};
fetch('https://api.pdfdyno.com/v1/pdf/generate', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.pdfdyno.com/v1/pdf/generate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'data' => [
],
'template' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: <content-type>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.pdfdyno.com/v1/pdf/generate"
payload := strings.NewReader("{\n \"data\": {},\n \"template\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "<content-type>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.pdfdyno.com/v1/pdf/generate")
.header("Content-Type", "<content-type>")
.body("{\n \"data\": {},\n \"template\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.pdfdyno.com/v1/pdf/generate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = '<content-type>'
request.body = "{\n \"data\": {},\n \"template\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"error": "Invalid Typst syntax on line 2"
}
{
"error": "Missing or invalid API Key"
}
{
"error": "Payload exceeds 10MB limit"
}
{
"error": "Rate limit exceeded"
}
{
"error": "An unexpected error occurred during document compilation."
}
{
"error": "Service temporarily unavailable. Please try again later."
}
Zero Data Retention Policy: PDFDyno operates purely in-memory. The JSON payload, the Typst template, and the generated PDF are instantly and permanently deleted from our servers the moment the HTTP response is sent. We do not store any of your data.
Authentication
This endpoint requires a Bearer token. Pass your API key in theAuthorization header.
Authorization: Bearer sk_live_YOUR_API_KEY
System Limits
- Max Payload Size:
10 MB - Max Timeout:
10 seconds(Documents must compile within this time) - Rate Limit:
100 requests / minute(on Starter plan) - Typst Version:
0.11.0
Request Headers
string
required
Must be
application/json.Request Body
object
required
The JSON data object containing the dynamic variables you want to inject into your PDF. The backend automatically injects this data into your template as a
#data variable.string
required
The raw Typst markup template string. Use
#data.field to access variables from your data.Example Request
curl -X POST https://api.pdfdyno.com/v1/pdf/generate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template": "= #data.title\n\nThis is a report.",
"data": {
"title": "Monthly Report"
}
}' \
--output report.pdf
const response = await fetch('https://api.pdfdyno.com/v1/pdf/generate', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
template: "= #data.title\n\nThis is a report.",
data: {
title: "Monthly Report"
}
})
});
const buffer = Buffer.from(await response.arrayBuffer());
import requests
response = requests.post(
"https://api.pdfdyno.com/v1/pdf/generate",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={
"template": "= #data.title\n\nThis is a report.",
"data": {"title": "Monthly Report"},
}
)
with open("report.pdf", "wb") as f:
f.write(response.content)
Response Headers
PDFDyno returns the following headers on every request to help you handle rate limits gracefully.The number of requests remaining in the current one-minute window.
Returned on every request (and particularly with
429 Too Many Requests). A UNIX timestamp indicating when the rate limit window resets.Response Body
Returns the raw PDF binary.{
"error": "Invalid Typst syntax on line 2"
}
{
"error": "Missing or invalid API Key"
}
{
"error": "Payload exceeds 10MB limit"
}
{
"error": "Rate limit exceeded"
}
{
"error": "An unexpected error occurred during document compilation."
}
{
"error": "Service temporarily unavailable. Please try again later."
}