Uploads
Reserves a slot for one file and returns where to send it. Files go straight to storage, never through the API: (1) call this, (2) PUT the bytes to upload_url with the given headers, (3) reference the returned id in the write that uses the file. A type, file name extension (missing, not accepted for the purpose, or not matching content_type) or size the purpose does not allow is refused here, before anything is uploaded. The contents are checked when a write uses the upload (422 invalid_file). Designers may use every purpose except quote_file and withdrawal_invoice; integrators may use quote_file and withdrawal_invoice (with the quotes:write scope) and extra_image (with the extras:write scope).
Three steps
- Create an upload with the file's purpose, name, type and size.
- Send the bytes to
upload_urlwith themethodandheadersit gives. - Reference the upload id in the write that uses the file.
import { readFile } from 'node:fs/promises';
const file = await readFile('tracker.3mf');
// 1. Reserve a slot.
const upload = await fetch(`${process.env.DAPI_API_URL}/v2/uploads`, {
method: 'POST',
headers: {
'x-api-key': process.env.DAPI_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
purpose: 'design_file',
file_name: 'tracker.3mf',
content_type: 'model/3mf',
size_bytes: file.byteLength,
}),
}).then((r) => r.json());
// 2. Send the bytes straight to storage.
await fetch(upload.upload_url, {
method: upload.method,
headers: upload.headers,
body: file,
});
// 3. Use upload.id in the write, for example a new design.Purposes and limits
What the file is for. Each purpose accepts its own types and size:
extra_image: a photo of an extra part; image/png, image/jpeg, image/webp; file names ending in .png, .jpg, .jpeg, .jfif, .webp (or no extension); up to 25,000,000 bytes (25 MB).product_image: a product or variant photo; image/png, image/jpeg, image/webp; file names ending in .png, .jpg, .jpeg, .jfif, .webp (or no extension); up to 25,000,000 bytes (25 MB).design_file: a printable model (.3mf, .stl or .obj); model/3mf, model/stl, model/obj, application/octet-stream; file names ending in .3mf, .stl, .obj; up to 150,000,000 bytes (150 MB).attachment: a production document for the farm (PDF, image or short video); application/pdf, image/png, image/jpeg, video/mp4; file names ending in .pdf, .png, .jpg, .jpeg, .jfif, .mp4, .m4v (or no extension); up to 25,000,000 bytes (25 MB).qc_photo: a photo for a QC message or issue report; image/png, image/jpeg, image/webp; file names ending in .png, .jpg, .jpeg, .jfif, .webp (or no extension); up to 25,000,000 bytes (25 MB).compliance_document: a product safety document (PDF or image); application/pdf, image/png, image/jpeg; file names ending in .pdf, .png, .jpg, .jpeg, .jfif (or no extension); up to 25,000,000 bytes (25 MB).quote_file: a model to quote (.stl, .3mf, .obj, .step or .stp); integrators only; model/stl, model/3mf, model/obj, model/step, application/step, application/sla, application/vnd.ms-pki.stl, application/octet-stream; file names ending in .stl, .3mf, .obj, .step, .stp; up to 262,144,000 bytes (250 MiB).withdrawal_invoice: an invoice (PDF, in USD) for a withdrawal request; integrators only; application/pdf; file names ending in .pdf; up to 10,485,760 bytes (10 MiB). The extension must matchcontent_type. When a write uses the upload, its contents are checked against that type (the first bytes of an image, PDF or video; the header and structure of a model), and a file that is not what it claims is refused with 422invalid_file.
Expiry
After this the upload URL stops working and the id can no longer be referenced. Uploads not used by then are deleted.
Errors like upload_expired, upload_purpose_mismatch and file_too_large name the problem in message.