File Uploads
Upload files with the presigned GET /uploads flow, confirm them, and list uploaded files.
Files don’t go through the JSON /v1 endpoints - binary uploads use a presigned flow instead. You ask Blue for a one-time upload URL, PUT the file’s bytes straight to that URL, then confirm the upload. This keeps large binaries off the API and lets the upload go directly to object storage.
The flow is three steps:
GET /uploads- authenticate with your Bearer token; Blue returns a presigned target.PUTto the returnedurl- send the raw file bytes with the returnedContent-Type.PUT /uploads/{uid}/confirm- finalize the file so it appears in the workspace.
/uploads sits outside the /v1 JSON surface - it returns a presigned target rather than an operation result, and the binary PUT in step 2 goes to the storage url Blue hands back, not to a Blue API path at all.
Step 1: request a presigned upload
GET /uploads with the same Bearer token you use everywhere else, plus an x-bloo-project-id header naming the workspace the file belongs to (uploads are scoped to a workspace, so this header is required in addition to x-bloo-company-id). The file name and size go in the query string; Blue derives the content type from the file name’s extension.
curl "https://rest.blue.app/uploads?filename=report.pdf&size=248913" \
-H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
-H "x-bloo-company-id: YOUR_COMPANY_ID" \
-H "x-bloo-project-id: YOUR_WORKSPACE_ID"| Query param | Required | Description |
|---|---|---|
filename | Yes | The file name, with extension - Blue derives the content type from it. |
size | No | File size in bytes. Validated against the workspace’s upload limit. |
key | No | A custom file ID. Omit it and Blue generates one (returned as X-Key). |
The response carries the upload target:
{
"url": "https://STORAGE_HOST/PATH?X-Amz-Signature=...",
"method": "PUT",
"headers": {
"Content-Type": "application/pdf"
},
"fields": {
"Content-Type": "application/pdf",
"Key": "acme/launch/abc123/report.pdf",
"X-Key": "abc123"
}
}| Field | Description |
|---|---|
url | The presigned URL to PUT the file bytes to. Single-use and time-limited. Use it verbatim. |
method | The HTTP method for the upload - always PUT. |
headers | Headers you must send on the upload request - send the Content-Type exactly as returned (the signature is bound to it). |
fields | Storage metadata: Content-Type, the storage Key, and X-Key - the file’s uid, which you pass to the confirm step. |
Step 2: upload the file
Send the raw bytes to url with the Content-Type from headers. Do not send your Bearer token here - the URL is already signed, and the request goes to storage, not to Blue’s API:
curl "https://STORAGE_HOST/PATH?X-Amz-Signature=..." \
-X PUT \
-H "Content-Type: application/pdf" \
--data-binary @report.pdfA 2xx response means the bytes landed. The signed URL is single-use and expires, so request a fresh one for each file.
Step 3: confirm the upload
Finalize the file with its uid - the X-Key value from step 1 - so it’s marked complete and shows up in the workspace:
curl "https://rest.blue.app/uploads/abc123/confirm" \
-X PUT \
-H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN"Blue schedules a background check just after the presign window closes that reconciles the file row against storage - so an upload eventually resolves even if you skip the confirm call. Calling confirm yourself just makes the file available immediately.
List uploaded files
Use the list-files operation to see the files in a workspace. It’s a standard RPC call and pages like any other list operation:
curl https://rest.blue.app/v1/list-files \
-X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
-H "x-bloo-company-id: YOUR_COMPANY_ID" \
-d '{
"workspaceId": "WORKSPACE_ID",
"skip": 0,
"limit": 50
}'The response is an items array of file metadata plus a pageInfo object (see Pagination):
{
"items": [
{
"id": "clm4n8qwx000008l0g4oxdqn7",
"uid": "abc123",
"name": "report.pdf",
"size": 248913,
"type": "application/pdf",
"extension": "pdf",
"status": "CONFIRMED",
"shared": false,
"createdAt": "2026-06-21T12:34:56.789Z",
"updatedAt": "2026-06-21T12:34:56.789Z",
"folder": null,
"todo": null,
"user": { "id": "clm...", "fullName": "Ada Lovelace", "email": "ada@example.com" }
}
],
"pageInfo": {
"totalItems": 1,
"hasNextPage": false
}
}Related
- Making Requests - the RPC call style
list-filesuses. - Pagination - paging through
list-files. - Authentication - the Bearer token for the presign step.