Reference
Examples
Minimal server-side Safeput integration examples.
Use Safeput only from trusted server-side code. The browser should send the file to your backend first; your backend creates the upload record and returns only the short-lived upload target to the browser.
Create an upload with TypeScript
const apiKey = process.env.SAFEPUT_API_KEY;
const response = await fetch("https://dev.safeput.dev/v1/uploads", { method: "POST", headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json", "Idempotency-Key": crypto.randomUUID(), }, body: JSON.stringify({ filename: "invoice.pdf", content_type: "application/pdf", size: 12_480, }),});
if (!response.ok) throw new Error(`Safeput returned ${response.status}`);
const { upload, upload_target: target } = await response.json();Send the exact bytes to target.url with target.method and every header from
target.headers. Do not attach your project API key to that request.
Wait for a terminal verdict
For a first integration, poll GET /v1/uploads/:id with a bounded delay. In a
production integration, prefer signed webhooks.
const terminal = new Set(["clean", "rejected", "failed", "expired"]);
while (!terminal.has(upload.status)) { await new Promise((resolve) => setTimeout(resolve, 1_500)); const response = await fetch( `https://dev.safeput.dev/v1/uploads/${upload.id}`, { headers: { Authorization: `Bearer ${apiKey}` } }, ); ({ upload } = await response.json());}Request a download URL only when upload.status === "clean" and
upload.download_available is true.
Last updated Aug 30, 2026