🧩

PDF Merge API

Post a list of public PDF links. We fetch them, concatenate them in the order you gave, and hand back a public URL to the merged file β€” valid for one hour.

Free β€” weekly limit, or $20/mo unlocked β†’

Endpoints

POST https://trilogicppp.com/api/pdf-merge

Downloads every PDF you list, merges them in order, returns a public link to the result.

GET https://trilogicppp.com/api/pdf-merge/download/:token

Serves the merged PDF. No API key needed β€” the token is the secret. Re-fetchable as often as you like until it expires (1 hour). Append ?dl=1 to force a download instead of the browser viewer.

Request

Headers

HeaderValue
Content-Typeapplication/json
X-API-KeyYour API key

Body (JSON)

FieldTypeDescription
urls string[] Public http(s) links to the PDFs, in the order they should appear. 2 to 50 entries, 100 MB per file, 300 MB total.
filename string Name of the merged file. Default: merged.pdf (optional)

Example Request

curl -X POST https://trilogicppp.com/api/pdf-merge \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d '{
    "urls": [
      "https://example.com/invoice-a.pdf",
      "https://example.com/invoice-b.pdf"
    ],
    "filename": "invoices-q3.pdf"
  }'

Response

200 OK

{
  "url":        "https://trilogicppp.com/api/pdf-merge/download/550e8400-e29b-...",
  "expires_at": "2026-09-17T14:30:00.000Z",
  "token":      "550e8400-e29b-41d4-a716-446655440000",
  "filename":   "invoices-q3.pdf",
  "sources":    2,
  "pages":      14,
  "bytes":      248113
}

Errors

StatusMeaning
400Fewer than 2 URLs, more than 50, or a malformed link
401Missing or invalid API key
403A URL resolves to a private / internal address
404Download token not found or expired
413A source exceeds 100 MB, or the job exceeds 300 MB
415A URL returned something that isn't a PDF
429Weekly limit reached
502A source was unreachable or returned an error status
504A source took too long to download (30 s per file)

Every error carries a stable code alongside the human message β€” e.g. not_a_pdf, blocked_host, source_too_large.

Code Samples

JavaScript (fetch)

const res = await fetch('https://trilogicppp.com/api/pdf-merge', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'your-key',
  },
  body: JSON.stringify({
    urls: ['https://example.com/a.pdf', 'https://example.com/b.pdf'],
  }),
});
const { url, pages } = await res.json();
console.log(url, pages); // public link + page count

Python (requests)

import requests

r = requests.post(
    'https://trilogicppp.com/api/pdf-merge',
    headers={'X-API-Key': 'your-key'},
    json={'urls': ['https://example.com/a.pdf', 'https://example.com/b.pdf'],
          'filename': 'report.pdf'},
)
print(r.json()['url'])  # public link, valid 1 hour

PHP

$ch = curl_init('https://trilogicppp.com/api/pdf-merge');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json', 'X-API-Key: your-key'],
    CURLOPT_POSTFIELDS     => json_encode(['urls' => [
        'https://example.com/a.pdf',
        'https://example.com/b.pdf',
    ]]),
]);
$data = json_decode(curl_exec($ch), true);
echo $data['url'];

Try it live