Files
Open in the interactive reference
In practice: a file field is a string on the wire. In a request it takes an upload reference you get by uploading the file first; in a response it holds a handle you exchange for the file. Both are short-lived and opaque, and neither is the file's id.
The OpenAPI document marks a file field as { "type": "string", "x-file": true }, and this reference shows its type as file. Filters and data-set parameters stay plain strings.
Uploading a file
- Send the file as
multipart/form-datatoPOST /public/files/{namespace}/{operationId}, with theApi-Versionheader.operationIdnames the endpoint you will call with it;namespaceis the segment after/public/api/in your base URL. Name each file part as you like: the answer maps each name to an upload reference underdata. - Call the endpoint and pass the reference as the file field's value. The platform swaps it for the stored file before the endpoint runs.
- A reference works only for the user who uploaded it and only for the endpoint it was uploaded for, and expires after a few minutes. Upload right before the call.
- A file field accepts nothing else. A handle you read from a record, an id or an expired reference is answered with
400Invalid input, the field's path indiagnostics, and the endpoint does not run. To keep a file a record already has, leave the field out. - One request takes up to 10 files of at most 15 MB each, under distinct part names.
- With an
Idempotency-Key, a retry replays the stored response even after its reference has expired. The key covers the body as sent, so a retry that sends a new reference for the same file is a different request; see Idempotency.
Downloading a file
Send a handle to GET /public/files/{handle} for the file's content, or to GET /public/files/{handle}/metadata for its name, type and size. Fetch the file soon after reading the record.
- A handle works for the user your access token acts as, with any of that user's tokens. For a system access token, that is the integration's system user. Another user's handle is answered with
404. - It works only while you may still call the endpoint that returned it. Once that grant is gone, the handle is answered with
404. - It expires after a short time, and stops working when the file is removed. Don't store handles: when you need the file again, read the record again for a new one.
- Treat it as opaque. Reading the same record twice can return two different handles for the same file, so don't compare handles or read anything out of them.
The file endpoint
/public/files is on the same host as the API, but not under /public/api/<namespace>. It takes the same Authorization header as every other request. Uploads need Api-Version; downloads don't.
GET /public/files/{handle}returns the content.Content-Typeis the file's type, orapplication/octet-streamwhen it is unknown, andContent-Disposition: attachmentcarries the file name.HEAD /public/files/{handle}answers with the same headers and aContent-Length, without the content.GET /public/files/{handle}/metadatareturnsfileName,mimeTypeandsizein bytes underdata.mimeTypeandsizeare left out when they are unknown.
Every answer carries Cache-Control: private, no-store. Let your client follow redirects, and don't send the Authorization header on to another host: the content may be served from a different location in a later release.
Status codes
| Status | Meaning, and what to do |
|---|---|
200 |
The upload references, the content, or the metadata. |
400 |
An upload without Api-Version, with more than 10 files, with two parts of the same name, or a body that is not valid multipart/form-data. On the endpoint call: a file field that holds anything but a valid upload reference. |
401 |
No valid access token, as on every request; see Authentication. |
403 |
An upload for an endpoint your token may not call. Uploading needs the same permission as the call itself. |
404 |
On an upload: no endpoint of that name, or one without a file field. On a download: the handle is unknown or expired, belongs to another user, comes from an endpoint you may no longer call, or the file was removed. The answer is the same for all of them on purpose. Read the record again for a new handle; sending the same handle again will not help. |
413 |
A file larger than 15 MB. |
429 |
Too many requests, as on every request; see Rate limits and retries. |
Examples
1. Upload the file
curl -X POST 'https://<your-tenant-host>/public/files/<namespace>/createLibraryBook' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Api-Version: v1' \
-F 'cover=@cover.svg;type=image/svg+xml' \
-F 'sampleChapter=@chapter.pdf;type=application/pdf'
HTTP/1.1 200 OK
Cache-Control: private, no-store
{ "data": { "cover": "u1.fIrOBkgwx7mXZLV3PekHTg.1nIoVCd…",
"sampleChapter": "u1.QzsD8qBFrYJ-MoO0b_iehQ.KArJ_qL0…" } }
2. Send the references as the file fields
curl -X POST '<base URL>/library/books' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Api-Version: v1' \
-H 'Content-Type: application/json' \
-d '{ "title": "The Curl Handbook", …,
"cover": "u1.fIrOBkgwx7mXZLV3PekHTg.1nIoVCd…",
"sampleChapter": "u1.QzsD8qBFrYJ-MoO0b_iehQ.KArJ_qL0…" }'
HTTP/1.1 200 OK
{ "data": { "id": "d04e243e-002c-4fdc-b48b-1692e098c28d" } }
3. Read the record: each file field is a handle
{
"data": {
"id": "d04e243e-002c-4fdc-b48b-1692e098c28d",
"title": "The Curl Handbook",
"cover": "v1.PSa6ZvU-WUeMWfgZMo_oFg.b63x0zr…",
"sampleChapter": "v1.jNEmR2brBKl2Zi8GhcFZnQ.r7Kgu7X…"
}
}
4. Read a file's metadata, or download it
curl 'https://<your-tenant-host>/public/files/'"$FILE_HANDLE"'/metadata' \
-H "Authorization: Bearer $ACCESS_TOKEN"
{ "data": { "fileName": "chapter.pdf", "mimeType": "application/pdf", "size": 37 } }
curl -OJ 'https://<your-tenant-host>/public/files/'"$FILE_HANDLE" \
-H "Authorization: Bearer $ACCESS_TOKEN"
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Length: 37
Content-Disposition: attachment; filename=chapter.pdf
Cache-Control: private, no-store
X-Content-Type-Options: nosniff
Anything but an upload reference in a file field
{
"error": {
"message": "Invalid input",
"diagnostics": [
{
"path": [
"cover"
],
"message": "Expected a file reference returned by the file upload endpoint for this action, to this caller, that has not expired"
}
]
}
}
A handle that is expired, unknown or not yours
{
"error": {
"message": "The requested file could not be found"
}
}