Documents and files
List your generated documents, download stored PDFs through signed links, and fetch first-page thumbnails, your logo and your fonts.
On this page
Every PDF you generate becomes a document in your workspace's log. GET /v1/documents pages through that log. The other endpoints on this page serve files through signed links: URLs that carry their own exp and sig query parameters, so they work without an API key and can be handed to a browser or a customer. You never build these URLs yourself; the API returns them as url, thumbnail_url or brand.logo_url, and a link that was changed in any way stops working.
GET /v1/documents
Your workspace's documents, newest first. Test keys see only test documents; live keys see all of them.
curl "https://api.castpdf.com/v1/documents?limit=50" \
-H "Authorization: Bearer YOUR_API_KEY"let before = null;
do {
const url = new URL('https://api.castpdf.com/v1/documents');
url.searchParams.set('limit', '100');
if (before) url.searchParams.set('before', before);
const res = await fetch(url, { headers: { Authorization: 'Bearer YOUR_API_KEY' } });
const page = await res.json();
for (const doc of page.data) console.log(doc.id, doc.status);
before = page.next_before;
} while (before);import requests
params = {"limit": 100}
while True:
res = requests.get(
"https://api.castpdf.com/v1/documents",
headers={"Authorization": "Bearer YOUR_API_KEY"},
params=params,
timeout=30,
)
page = res.json()
for doc in page["data"]:
print(doc["id"], doc["status"])
if not page["next_before"]:
break
params["before"] = page["next_before"]{
"data": [
{
"id": "3f0c9a4e-6b1d-4c2a-9a57-0d8e4b7f21c3",
"status": "succeeded",
"pages": 2,
"bytes": 48213,
"mode": "print",
"test": false,
"template_id": "8d1f2c3b-4a5e-4f60-9b7a-1c2d3e4f5a6b",
"template_version": 4,
"error_code": null,
"created_at": "2026-09-30T10:15:02.123Z",
"expires_at": "2026-10-07T10:15:02.123Z",
"url": "https://api.castpdf.com/v1/files/3f0c9a4e-6b1d-4c2a-9a57-0d8e4b7f21c3?exp=1791368102&sig=Jx0k...",
"thumbnail_url": "https://api.castpdf.com/v1/thumbnails/documents/3f0c9a4e-6b1d-4c2a-9a57-0d8e4b7f21c3.png?exp=1790935200&sig=Qm4t...",
"delivery": null
}
],
"next_before": "2026-09-30T10:15:02.123456Z_3f0c9a4e-6b1d-4c2a-9a57-0d8e4b7f21c3"
}| Query parameter | Description |
|---|---|
limit | 1 to 100. Default 20. |
before | The previous page's next_before, to get the next page. A bare ISO 8601 timestamp also works and means "older than this". |
The response has cache-control: no-store. Each item is a document object, the same as GET /v1/pdf/:id returns; queued background PDFs appear only once they are made. next_before is null on the last page. Treat it as opaque and pass it back unchanged: it keeps documents made in the same instant from being skipped or repeated. Document records are kept for 120 days.
| Code | When |
|---|---|
invalid_request (400) | limit is out of range, or before is not a cursor or a valid timestamp |
GET /v1/files/:id
Downloads a stored PDF. It is the url returned by POST /v1/pdf (with response: "url"), GET /v1/pdf/:id and GET /v1/documents, and it needs no API key. It stops working when the file expires.
curl "https://api.castpdf.com/v1/files/3f0c9a4e-6b1d-4c2a-9a57-0d8e4b7f21c3?exp=1791368102&sig=Jx0k...&download=1" \
--output invoice-042.pdf| Query parameter | Description |
|---|---|
exp, sigRequired | The expiry and signature, as returned in the link. |
download | 1 to save the file instead of opening it in the browser (content-disposition: attachment). It is not part of the signature, so you can add it to any link. |
200 with the file and these headers:
| Header | Description |
|---|---|
content-type | application/pdf, or application/xml for an XRechnung e-invoice |
content-disposition | inline; filename="invoice-042.pdf" (opens in the browser), or attachment with download=1 |
cache-control | private, with a max-age of 300 seconds |
content-security-policy | sandbox |
x-content-type-options | nosniff |
| Code | When |
|---|---|
forbidden (403) | The signature does not match |
file_expired (410) | The link expired, or the file is no longer stored |
GET /v1/brand-assets/:file
Serves your team's logo or one of its uploaded fonts (set in the dashboard: Simple mode, Design panel). Templates get the logo's link as brand.logo_url (see your brand), and the dashboard shows it. The sig query parameter signs it, so it needs no API key; it does not expire, and a replaced logo gets a new URL. When CastPDF renders your PDFs it uses these files directly, without fetching the URL.
curl "https://api.castpdf.com/v1/brand-assets/0b6f2a4c-9d1e-4f3a-8b7c-5e6d7a8b9c10.png?sig=Hk2p..." --output logo.png200 with the file: image/png or image/jpeg for a logo (an SVG logo is turned into a PNG when you upload it), font/woff2, font/ttf or font/otf for a font.
| Header | Description |
|---|---|
cache-control | public, max-age=86400: a deleted file stops being served within a day |
access-control-allow-origin | *, so web pages may load your fonts |
cross-origin-resource-policy | cross-origin |
content-security-policy | sandbox; default-src 'none'; style-src 'unsafe-inline' |
x-content-type-options | nosniff |
| Code | When |
|---|---|
forbidden (403) | The signature does not match |
not_found (404) | The file was replaced or deleted |
GET /v1/thumbnails/documents/:file
A PNG of a stored PDF's first page, 480 px wide: the thumbnail_url of a document, which is null when nothing is stored. The :file is the document id followed by .png. Signed by its exp and sig parameters, so it needs no API key. The image is made from the stored PDF the first time it is asked for (nothing is rendered or counted) and is removed with the PDF.
curl "https://api.castpdf.com/v1/thumbnails/documents/3f0c9a4e-6b1d-4c2a-9a57-0d8e4b7f21c3.png?exp=1790935200&sig=Qm4t..." \
--output page-1.png200 with content-type: image/png, cache-control: private, max-age=3600, content-security-policy: default-src 'none' and x-content-type-options: nosniff. A thumbnail link lasts one to two hours (it is rounded to the hour, so the URL stays the same for an hour and browsers can cache it); ask the API again for a fresh one.
| Code | When |
|---|---|
forbidden (403) | A wrong or expired signature |
not_found (404) | The PDF is no longer stored |
GET /v1/thumbnails/templates/:file
A PNG of the first page of a template version, rendered with that version's sample data, 480 px wide. It is the thumbnail_url of a template; the :file is the template id followed by .png, and the v query parameter names the version, so every new version gets a new URL. The image is made the first time it is asked for, as a preview: not counted, not stored as a document and not watermarked. It is signed like the document thumbnails, lasts as long, and has the same headers.
curl "https://api.castpdf.com/v1/thumbnails/templates/8d1f2c3b-4a5e-4f60-9b7a-1c2d3e4f5a6b.png?v=4&exp=1790935200&sig=Lw8d..." \
--output template.png| Code | When |
|---|---|
invalid_request (400) | v is not a version number |
forbidden (403) | A wrong or expired signature |
not_found (404) | The template was deleted, or the version is newer than its current one |
rate_limited (429) | Every concurrent render slot of your team is busy; try again in a moment |