---
title: "Create file upload session"
method: POST
path: "/api/v1/files/uploads"
tags: ["Files"]
---

# Create file upload session

`POST /api/v1/files/uploads`

## Request

- Base URL: `https://api.studio.kaitoi.io` (the document declares no server; this is the origin it was published from)
- URL: `https://api.studio.kaitoi.io/api/v1/files/uploads`
- Auth: HTTP bearer

Creates a direct-to-storage upload session. This endpoint does not upload the file bytes. Use the returned instructions as follows:

1. Send a separate PUT request to `upload.url` using `upload.method` and every header in `upload.headers`. Do not send the API Bearer token to that URL; the signed URL is the temporary upload credential.
2. After the PUT succeeds, call `POST /files/uploads/{upload_id}/complete` with this response's `uploadId`.
3. Use the completed response's `fileId` as a file input in later API calls.

For large files, `storageMethod` may be `multipart`; in that case, PUT each item in `parts` and pass the returned ETags to the complete endpoint. If the session was created with `sha256`, the API verifies the stored object checksum before completion; multipart completions must include `actualSha256`. Use Idempotency-Key so retries return the same reservation and signed URL.

## Headers

- `Idempotency-Key` string, nullable
- `authorization` string, nullable

## Request body

- PublicFileUploadCreateRequest
  - `filename` string, required: Original filename.
  - `contentType` string: Media type to attach to the uploaded object.
  - `sizeBytes` integer, required: Exact file size in bytes. This reserves storage quota before bytes are uploaded.
  - `sha256` string, nullable: Optional lowercase hex SHA-256. Recommended so the API can verify end-to-end object integrity before completing the upload.
  - `externalId` string, nullable: Developer-provided external file identifier.
  - `externalUserId` string, nullable: Developer-provided end-user identifier.
  - `externalWorkspaceId` string, nullable: Developer-provided workspace/team identifier.

## Response `201`

Upload session and signed upload instructions.

- PublicFileUploadSession
  - `uploadId` string, required: Upload session id. Use this with POST /files/uploads/{uploadId}/complete.
  - `fileId` string, required: File id reserved for this upload. It becomes readable after completion.
  - `externalId` string, nullable: Developer-provided external file identifier.
  - `externalUserId` string, nullable: Developer-provided end-user identifier.
  - `externalWorkspaceId` string, nullable: Developer-provided workspace/team identifier.
  - `storageMethod` 'single_part' | 'multipart' | 'proxied_relay', required: Upload strategy selected by the API. For single_part and proxied_relay, send one PUT to upload.url. For multipart, send each PUT in parts, then include the returned ETags when completing the upload.
  - `expiresAt` string, date-time, required: Upload session expiration timestamp.
  - `upload` PublicFileUploadInstruction
    - `method` 'PUT', required: HTTP method to use when uploading bytes to this signed URL.
    - `url` string, required: Signed upload URL for the file bytes. Send a separate PUT request to this URL without the API Bearer token; the URL itself is the temporary upload credential.
    - `headers` object: Headers that must be sent with the PUT request, such as Content-Type or storage checksum headers.
  - `partSizeBytes` integer, nullable: Target multipart part size in bytes.
  - `partCount` integer, nullable: Number of multipart parts to upload.
  - `parts` PublicFileUploadPartInstruction[], nullable: Multipart upload instructions. Present when storageMethod is multipart.
    - `partNumber` integer, required: Multipart part number.
    - `method` 'PUT', required: HTTP method to use when uploading this part.
    - `url` string, required: Signed URL for this multipart part. Send this request without the API Bearer token.
    - `headers` object: Headers that must be sent with this part upload.

## Other responses

- `400`: The upload session request is invalid.
- `401`: Missing, malformed, expired, or revoked bearer token.
- `403`: The API key lacks the required scope or account capability.
- `409`: The Idempotency-Key conflicts with a different request.
- `422`: Validation Error
- `429`: The client or API key exceeded the REST API rate limit.
- `503`: The shared REST API rate limiter is temporarily unavailable.
- `507`: The upload would exceed the account storage limit.

---

[API](https://skmtc.dev/kaitoi/apis/kaitoi-rest-api.md) · [All operations](https://skmtc.dev/kaitoi/apis/kaitoi-rest-api/llms.txt) · [OpenAPI document](https://skmtc.dev/kaitoi/apis/kaitoi-rest-api/revisions/239a74aa2c64?raw)
