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

  1. Send the file as multipart/form-data to POST /public/files/{namespace}/{operationId}, with the Api-Version header. operationId names the endpoint you will call with it; namespace is 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 under data.
  2. 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.

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.

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.

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"
  }
}