Direct uploads
For files larger than a few megabytes, uploading through the API adds unnecessary latency. The presigned-URL flow lets your client upload the file directly to R2 storage, then tell CanvasMesh to attach it.
This is a three-step flow: presign → PUT → finalize.
1. Request a presigned URL
Section titled “1. Request a presigned URL”curl -X POST https://api.canvasmesh.app/v1/upload/presign \ -H "Authorization: Bearer $CANVASMESH_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "ext": "pdf", "size": 1048576, "mime": "application/pdf" }'Response:
{ "file_id": "fl_xyz789", "blob_key": "files/ab/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "upload_url": "https://<r2-presigned-url>...", "content_type": "application/pdf", "expires_in": 3600, "exists": false}If exists: true, the content-addressed hash already exists in storage and you can skip step 2.
2. PUT the file to the presigned URL
Section titled “2. PUT the file to the presigned URL”curl -X PUT "<upload_url>" \ -H "Content-Type: application/pdf" \ --data-binary @./large-file.pdfUse the exact Content-Type from the presign response. The URL expires after expires_in seconds.
3. Finalize
Section titled “3. Finalize”Tell CanvasMesh the upload completed so it reference-counts the blob:
curl -X POST https://api.canvasmesh.app/v1/upload/finalize \ -H "Authorization: Bearer $CANVASMESH_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "ext": "pdf", "size": 1048576, "mime": "application/pdf" }'4. Create a canvas from the file
Section titled “4. Create a canvas from the file”Instead of passing raw content, pass file_id:
curl -X POST https://api.canvasmesh.app/v1/canvases \ -H "Authorization: Bearer $CANVASMESH_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "file_id": "fl_xyz789", "title": "Q2 Report", "ext": "pdf" }'Deduplication
Section titled “Deduplication”Files are stored by SHA-256. Two identical uploads share one blob; deleting one canvas won’t delete content another canvas still references. This lets you upload the same large asset across many canvases without wasting storage.
When to use presigned uploads
Section titled “When to use presigned uploads”- Any file > 5 MB — direct upload is faster and avoids multipart limits on the Worker.
- Cases where the client already has the hash (e.g. content-addressed caches).
For small files, POST /v1/canvases with multipart is simpler.