Guarantees

Verifiable documents

Every document Renderly generates is verifiable. At issuance time we compute the SHA-256 of the bytes and register the issuance. Later, anyone can prove that a file is intact and was generated by you — without having to take our word for it, by checking the bytes.

How it works

Verification is by content integrity. SHA-256 is a fingerprint of the file bytes: change a single byte and the hash changes completely. Because we keep the issuance hash, we can confirm whether a file in hand is exactly what was issued — or whether it was tampered with.

  1. 1Issuance. When rendering, we compute the SHA-256 of the delivered bytes and record an issuance (with organization, template, format and pages).
  2. 2Discreet seal. By default the output carries a verification seal — a QR pointing to the public page /verify/<id>.
  3. 3Verification. Later, send the file bytes to POST /api/verify. We recompute the hash and look for the matching issuance.
  4. 4Verdict. If the hash matches, the file is intact (verified) and we return the issuance metadata. If it does not match, it is not_found — tampered with or never issued by us.

The verification data in the render response

The response of /v1/render already carries everything that links the file to its issuance, in the headers:

render response headers
HTTP/1.1 200 OK
Content-Type: application/pdf
X-Render-Ms: 842
X-Render-Bytes: 18234
X-Render-Engine: native
X-Renderly-Document-Hash: 3b2f9c...e41a
X-Renderly-Verify-Id: 9f1c2d34-...-a1b2
X-Renderly-Verify-Url: https://api.renderly.dev/verify/9f1c2d34-...-a1b2
HeaderWhat for
X-Renderly-Document-HashThe SHA-256 of the bytes. Keep it for future checking.
X-Renderly-Verify-IdThe issuance id; it composes the public verification URL.
X-Renderly-Verify-UrlDirect link to the /verify/<id> page.
Verify-Id and Verify-Url are conditional
They only appear when the issuance was successfully registered. The X-Renderly-Document-Hash always comes in the success response.

Verification endpoint

POST/api/verifyPublic, no authentication.

The request body is the raw bytes of the file — not JSON, not base64, not multipart. We recompute the hash of those bytes and look for the issuance. It is this “check the file, not the URL” approach that makes verification tamper-proof: nobody has to trust the QR, only the content.

curl

curl — send the PDF bytes
curl -X POST https://api.renderly.dev/api/verify \
  --data-binary @invoice.pdf

JavaScript

node
import { readFile } from "node:fs/promises"

const bytes = await readFile("invoice.pdf")

const res = await fetch("https://api.renderly.dev/api/verify", {
  method: "POST",
  body: bytes, // the raw PDF BYTES — not JSON, not base64
})

const result = await res.json()
// { status: "verified", hash, issuance: { ... } }
console.log(result.status, result.issuance?.organization)

Python

python
import requests

with open("invoice.pdf", "rb") as f:
    bytes_ = f.read()

res = requests.post("https://api.renderly.dev/api/verify", data=bytes_, timeout=30)
print(res.json())

Verification responses

Verified — status: verified

The hash matches a registered issuance. We return its metadata.

200 — verified
{
  "status": "verified",
  "hash": "3b2f9c...e41a",
  "issuance": {
    "id": "9f1c2d34-...-a1b2",
    "issuedAt": "2026-06-15T13:42:08.512Z",
    "organization": "Acme Inc",
    "templateName": "Invoice",
    "format": "PDF",
    "pages": 2,
    "docHash": "7a1e...c0"
  }
}
issuance fieldMeaning
idIssuance identifier (the same as in /verify/<id>).
issuedAtIssuance date and time (ISO 8601).
organizationName of the organization that issued it.
templateNameName of the template used (if any).
formatPDF or PNG.
pagesNumber of pages (when applicable).
docHashHash of the canonical document model (independent of the bytes).

Not found — status: not_found

The hash does not match any issuance. This means one of two things: the file was tampered with after issuance, or was never generated by Renderly.

200 — not_found
{
  "status": "not_found",
  "hash": "00ab...ff"
}
HTTPstatusCause
200verifiedBytes match an issuance.
200not_foundBytes do not match any issuance.
400emptyNo file sent in the body.
413too_largeFile larger than 25 MB.

Public page /verify/<id>

Each issuance has a public page at /verify/<id>. It shows the issuance metadata (who issued it, when, template, format and the start of the hash) and offers an upload to check the bytes right there. It is the page the verification seal QR points to — any recipient of the document can open it and confirm provenance.

Check the bytes, not the URL
Even on the public page, the real proof comes from sending the file: we compare the hash of what you uploaded against the record. A QR copied onto a fake document will not pass — the bytes will not match.

The verification seal

Every output carries a discreet verification seal — the Renderly mark + a QR pointing to the /verify/<id> page — and this is default and mandatory on every plan. It is the heart of Renderly: anyone can check that the document is authentic, without having to trust you. The watermark parameter is accepted for compatibility, but ignored.

Want the seal with your own look?
On Enterprise you can co-brand the seal, make it more discreet, or remove it entirely (white-label). On every other plan the seal is mandatory, locked and always on top — nothing can cover the QR or the mark. Talk to us.

For the full security and privacy posture (zero-retention, encryption, what we store), see Security & Trust.

Next
Errors
Complete table of error codes and how to handle each one.