SnowBee PDF renderer POST /render Render a public SnowBee document, cache the PDF in R2, and return its public URL. The response is returned after storage completes; this service does not print. Send Content-Type: application/json with this body (maximum 4096 bytes): { "tenantId": "00000000-0000-0000-0000-000000000001", "jobId": "00000000-0000-0000-0000-000000000002", "sourceUrl": "https://app.snowbee.no/public_documents//" } tenantId and jobId must be UUIDs. sourceUrl must use the configured HTTPS origin and /public_documents/ path. Any document type is accepted. Query parameters are retained; credentials and fragments are rejected. Signing (shared HMAC secret required): X-SB-Timestamp: Unix time in milliseconds (13 digits, within 2 minutes) X-SB-Nonce: random base64url value (22-64 characters; use 16 random bytes) X-SB-Signature: base64url(HMAC-SHA256(secret, UTF-8 canonical string)) Canonical string, joined with LF newlines and no trailing newline: v1 POST /render Use unpadded base64url. Sign the exact body you send; do not reserialize it. The signing secret is never included in the request. Node.js example (set RENDER_HMAC_SECRET in your environment): import {createHash, createHmac, randomBytes, randomUUID} from "node:crypto" const body = JSON.stringify({ tenantId: randomUUID(), jobId: randomUUID(), sourceUrl: "https://app.snowbee.no/public_documents//" }) const timestamp = Date.now().toString() const nonce = randomBytes(16).toString("base64url") const hash = createHash("sha256").update(body).digest("hex") const canonical = ["v1", "POST", "/render", timestamp, nonce, hash].join("\n") const signature = createHmac("sha256", process.env.RENDER_HMAC_SECRET) .update(canonical).digest("base64url") const response = await fetch("https://pdf-renderer.snowbee.dev/render", { method: "POST", body, headers: {"Content-Type": "application/json", "X-SB-Timestamp": timestamp, "X-SB-Nonce": nonce, "X-SB-Signature": signature} }) console.log(response.status, await response.json()) Success (HTTP 200): {url, objectKey, size, cached} url: public PDF download URL objectKey: print-jobs//.pdf size: PDF size in bytes cached: true when an existing PDF was reused Retry with the same tenantId, jobId and sourceUrl to reuse the cached PDF. Use a new jobId for a new render; changing sourceUrl for a cached job returns 409. Generate a fresh timestamp, nonce and signature for each request. Cached PDFs expire after seven days. Print-job deadlines are enforced by SnowBee. Errors: 400 invalid request, 401 invalid signature or timestamp, 409 job/source conflict, 413 request too large, 500 invalid configuration, 502 rendering or storage failed. Error responses contain an "error" field.