---
title: "create_upload_session"
method: POST
path: "/v1/workspaces/{workspace_id}/upload-sessions"
tags: ["files"]
---

# create_upload_session

`POST /v1/workspaces/{workspace_id}/upload-sessions`

## Request

- Base URL: `https://ndi-api.nace.ai`
- URL: `https://ndi-api.nace.ai/v1/workspaces/{workspace_id}/upload-sessions`
- Auth: one of:
  - API key in header `X-API-Key`
  - API key in header `X-Upload-Token`
- TypeScript: <https://skmtc.dev/nace/apis/ndi-platform-api/docs/v1/workspaces/:workspace_id/upload-sessions/post.ts> (a function with typed inputs; its response is checked against the schema)

Open a chunked upload for a large file. Cost class: **fast**.

Same auth as ``upload_file`` — an ``X-API-Key`` or a short-lived
``X-Upload-Token`` grant — but redeemed exactly once, here. Every later
request against the session (parts, status, complete, abort) presents
the ``session_token`` this returns instead, in the same ``X-Upload-Token``
header.

Upload every part with ``PUT .../upload-sessions/{session_id}/parts/{n}``
at exactly ``chunk_size`` bytes (the final part may be shorter), then
call ``POST .../complete``. ``GET`` the session at any point to see which
parts have already landed, e.g. after a dropped connection.

## Path parameters

- `workspace_id` string, uuid, required: Workspace identifier.

## Headers

- `Idempotency-Key` string, nullable: Use the same key to recover an earlier request. A replay returned as a Job carries Idempotent-Replayed: true and replayed: true without a new charge; Job credits keeps the original cost. Re-serving a settled inline tool answer reports zero credits for that call and also carries Idempotent-Replayed: true; a fresh re-execution after a transient failure carries no header. The key is kept with the job for replay and never cleared, so it must not contain personal data.

## Request body

- CreateUploadSessionRequest: Body for ``POST /workspaces/{workspace_id}/upload-sessions``. Same destination/conflict/labelling contract as ``UploadFileRequest`` — this is the chunked entry point to the exact same ledger write, for a file large enough (or a link flaky enough) that one unretried multipart POST is the wrong shape. ``total_size_bytes`` is required and checked byte-for-byte at ``complete``: nothing here is trusted on faith.
  - `graph_inclusion` 'auto' | 'include' | 'exclude': Whether this file joins the knowledge-graph corpus. 'auto' follows the workspace's KG exclusion rules; 'include'/'exclude' override them for this file.
  - `labels` object: Caller-supplied metadata, stored verbatim.
  - `on_conflict` 'reject' | 'new_version': 'reject' raises path_conflict at complete-time when a file already exists at this path. 'new_version' increments the version and stamps replaced_at on the previous one.
  - `path` string, required: Destination path inside the workspace. Relative, must not start with '/', and must not use the platform-reserved '.workspace' subtree.
  - `source_modified_at` string, date-time, nullable: Filesystem modification time reported by the uploading client. Informational only: callers control this value, so it is not audit evidence.
  - `total_size_bytes` integer, required: Exact total size of the file, across every part.
  - `ttl_seconds` integer: How long the session accepts parts before it expires unfinished.

## Response `201`

Successful Response

- CreateUploadSessionResponse: A newly created upload session, ready to accept parts. ``session_token`` is sent as ``X-Upload-Token`` on every subsequent request against this session (parts, status, complete, abort) — the upload grant or API key used to create the session is not sent again.
  - `chunk_size` integer, required: Upload every part at exactly this size, except a shorter final part.
  - `expires_at` string, date-time, required: When the session stops accepting parts.
  - `session_id` string, uuid, required
  - `session_token` string, required: Send in the X-Upload-Token header of every subsequent request.
  - `total_parts` integer, required: ceil(total_size_bytes / chunk_size) — the parts complete() expects.

## Other responses

- `504`: Gateway Timeout
- `default`: Typed error envelope used by every 4xx and 5xx. ``error.code`` distinguishes the failure; HTTP status is a consequence of the code.

---

[API](https://skmtc.dev/nace/apis/ndi-platform-api.md) - [All operations](https://skmtc.dev/nace/apis/ndi-platform-api/llms.txt) - [OpenAPI document](https://skmtc.dev/nace/apis/ndi-platform-api/revisions/d002a3589a67?raw)
