Files, charts and download links
Upload an image or a PDF once and refer to it by id. Put a chart in a document from numbers. Make the result smaller. Hand it to someone who has no key, with an address that expires and can be revoked.
Stored files
| Call | What |
|---|---|
POST /api/v1/compose/files | Upload a file and get a fileId. Send multipart/form-data with a part named file, or JSON {"fileBase64": "...", "fileName": "..."}, or the raw bytes with any other content type. Needs documents:compose. |
GET /api/v1/compose/files and /files/{fileId} | The organisation’s files, or one file’s facts. Needs documents:read. |
DELETE /api/v1/compose/files/{fileId} | Delete the bytes and the id now. |
- The bytes decide the type. PNG, JPEG, WebP and PDF are accepted; the name and the declared content type are never trusted. SVG is refused (it is a script container).
- A PDF is refused (
FILE_REJECTED,details.reason) if it is encrypted, damaged, has more than 500 pages or carries active content: JavaScript, launch actions, embedded files or forms that submit. - Files are encrypted at rest and belong to your organisation: another organisation’s id answers
404 STORED_FILE_NOT_FOUND, like one that does not exist. They expire after 30 days by default (we can set up to 365 days for your organisation on request); uploading the same bytes again returns the same id and moves the expiry forward. - One file at most
asset_bytes(10 MB by default); a limited number of files per organisation (FILE_LIMIT_REACHED). Uploads accept anIdempotency-Key.
Using a file
An image in the payload. Where the payload would carry a
data:image/... URI for :::img or an HTML img src, send the id instead:
{ "receipt": { "$fileId": "7d3f6a52-..." } }
It is replaced by the image before the render, at most 20 per request. Your payload is stored with the reference, never with the pixels.
PDFs after the document. settings.attachments takes up to 5 ids of stored PDFs, appended in
order after the generated pages and before watermark, colour, compression, metadata and password, so those
apply to everything. The annotations of the appended pages are dropped, so no link or form field from someone
else’s PDF reaches the result. The pages count toward your page limit.
Charts
See the :::chart code: a bar, line or pie chart from numbers
in the payload, in Word and HTML templates.
Compression
settings.compressionLevel (none, lossless, balanced, small) is described in
the settings table. Measured on real templates with scripts/measure_compression.py:
output from Word templates shrinks 27 to 60 % even with lossless (fonts, structure) and with no image loss; output from
HTML templates is already tight and can grow, which is why the file is never returned larger than it was; a photo-heavy page shrinks by
about 98 % with balanced, at 150 dpi.
Signed download links
| Call | What |
|---|---|
POST /api/v1/compose/documents/{id}/download-links | {"expiresInSeconds"?, "singleUse"?}. Mints a link. The url and token are in this answer only. |
GET /api/v1/compose/documents/{id}/download-links | The links of a document and their state: active, used, expired, revoked. Never the tokens. |
DELETE .../download-links/{linkId} and DELETE .../download-links | Revoke one link, or every live link of the document. |
GET /dl/{token} | Public: no key, no cookie. Returns the PDF. |
These need documents:download. The console’s document page lists the links and revokes them too.
- Short by default: 1 hour. You may ask for up to your organisation’s maximum (48 hours by default; we can set another for your organisation on request, never more than seven days); more is refused, never silently shortened.
- Tamper-resistant: the token is signed over the link, your organisation, the document and the document’s SHA-256. A token for one document cannot fetch another, or another organisation’s. The answer of a mint carries the SHA-256 so you can check what you downloaded.
- Revocable, at once.
singleUse: trueburns the link on its first request, even if the client then fails to read the body. - Answers:
404 DOWNLOAD_LINK_INVALIDfor an address that is unknown, altered, revoked or spent (one answer, so it cannot be probed);410 DOWNLOAD_LINK_EXPIREDfor a genuine one past its time. Rate limited per caller address; never cached (Cache-Control: no-store). - Every mint, use and revocation is an audit entry. A document composed
datalesshas nothing to link to. - The token is part of the URL path, so it can appear in access logs along the way. That is why the default is short and why you can revoke.
PDF/A: converted, not verified
settings.pdfA asks for a best-effort conversion. We do not validate the result against a PDF/A checker, so we never say the
file conforms: every conversion returns the warning PDFA_NOT_VERIFIED and output.compose.pdfa.verified is
false. Validate the file yourself if you need to rely on it.