> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ndi.nace.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# create_upload_session

> 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.



## OpenAPI

````yaml /openapi.json post /v1/workspaces/{workspace_id}/upload-sessions
openapi: 3.1.0
info:
  description: >-
    Document intelligence: parse, split, classify, extract, and ground files, or
    build a searchable workspace. Authenticate with ``X-API-Key``.
  title: NDI Platform API
  version: 0.1.0
servers:
  - url: https://ndi-api.nace.ai
security: []
tags: []
paths:
  /v1/workspaces/{workspace_id}/upload-sessions:
    post:
      tags:
        - files
      summary: create_upload_session
      description: >-
        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.
      operationId: create_upload_session_v1_workspaces__workspace_id__upload_sessions_post
      parameters:
        - description: Workspace identifier.
          in: path
          name: workspace_id
          required: true
          schema:
            description: Workspace identifier.
            format: uuid
            title: Workspace Id
            type: string
        - description: >-
            Replaying a request with the same key returns the original job with
            200, never a second job.
          in: header
          name: Idempotency-Key
          required: false
          schema:
            anyOf:
              - maxLength: 200
                type: string
              - type: 'null'
            description: >-
              Replaying a request with the same key returns the original job
              with 200, never a second job.
            title: Idempotency-Key
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateUploadSessionRequest'
        required: true
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateUploadSessionResponse'
          description: Successful Response
        '504':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
          description: Gateway Timeout
        default:
          content:
            application/json:
              example:
                error:
                  code: invalid_request
                  detail: null
                  message: >-
                    Request body has extra fields that this operation does not
                    accept.
                  request_id: req-01j9k2n3p4q5r6s7t8v9
                  retryable: false
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
          description: >-
            Typed error envelope used by every 4xx and 5xx. ``error.code``
            distinguishes the failure; HTTP status is a consequence of the code.
      security:
        - APIKeyHeader: []
        - UploadGrantHeader: []
components:
  schemas:
    CreateUploadSessionRequest:
      additionalProperties: false
      description: |-
        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.
      properties:
        graph_inclusion:
          default: auto
          description: >-
            Whether this file joins the knowledge-graph corpus. 'auto' follows
            the workspace's KG exclusion rules; 'include'/'exclude' override
            them for this file.
          enum:
            - auto
            - include
            - exclude
          title: Graph Inclusion
          type: string
        labels:
          additionalProperties:
            type: string
          description: Caller-supplied metadata, stored verbatim.
          title: Labels
          type: object
        on_conflict:
          default: reject
          description: >-
            '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.
          enum:
            - reject
            - new_version
          title: On Conflict
          type: string
        path:
          description: >-
            Destination path inside the workspace. Relative — must not start
            with '/'.
          maxLength: 1024
          minLength: 1
          pattern: ^[^/]
          title: Path
          type: string
        total_size_bytes:
          description: Exact total size of the file, across every part.
          exclusiveMinimum: 0
          title: Total Size Bytes
          type: integer
        ttl_seconds:
          default: 5400
          description: How long the session accepts parts before it expires unfinished.
          maximum: 5400
          minimum: 1
          title: Ttl Seconds
          type: integer
      required:
        - path
        - total_size_bytes
      title: CreateUploadSessionRequest
      type: object
    CreateUploadSessionResponse:
      additionalProperties: false
      description: |-
        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.
      properties:
        chunk_size:
          description: Upload every part at exactly this size, except a shorter final part.
          title: Chunk Size
          type: integer
        expires_at:
          description: When the session stops accepting parts.
          format: date-time
          title: Expires At
          type: string
        session_id:
          format: uuid
          title: Session Id
          type: string
        session_token:
          description: Send in the X-Upload-Token header of every subsequent request.
          title: Session Token
          type: string
        total_parts:
          description: ceil(total_size_bytes / chunk_size) — the parts complete() expects.
          title: Total Parts
          type: integer
      required:
        - session_id
        - session_token
        - chunk_size
        - total_parts
        - expires_at
      title: CreateUploadSessionResponse
      type: object
    ErrorEnvelope:
      description: Every non-2xx body on ``/v1``.
      example:
        error:
          code: invalid_request
          detail: null
          message: Request body has extra fields that this operation does not accept.
          request_id: req-01j9k2n3p4q5r6s7t8v9
          retryable: false
      properties:
        error:
          $ref: '#/components/schemas/Error'
      required:
        - error
      title: ErrorEnvelope
      type: object
    Error:
      description: The error object, per spec 12 §1.8.
      properties:
        code:
          $ref: '#/components/schemas/ErrorCode'
        detail:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          description: Structured payload, when the code carries one.
          title: Detail
        message:
          description: Human- and model-readable; says what to do differently.
          title: Message
          type: string
        request_id:
          description: Per-request correlation id; matches the ``X-Request-Id`` header.
          title: Request Id
          type: string
        retryable:
          description: Whether retrying the identical request could succeed.
          title: Retryable
          type: boolean
      required:
        - code
        - message
        - retryable
        - request_id
      title: Error
      type: object
    ErrorCode:
      description: |-
        Every error the ``/v1`` surface can return.

        Clients must treat this as an **open** enum: a new member is an additive
        change (spec 12 §9), and a client that crashes on an unknown code makes
        every future error a breaking change.
      enum:
        - invalid_request
        - unsupported_file_type
        - file_too_large
        - invalid_schema
        - invalid_sql
        - invalid_path_prefix
        - command_not_permitted
        - batch_too_large
        - domain_validation_failed
        - default_label_required
        - wait_required_for_zero_retention
        - workspace_not_found
        - file_not_found
        - job_not_found
        - upload_not_found
        - node_not_found
        - schema_not_found
        - domain_not_found
        - session_not_found
        - access_label_not_found
        - path_conflict
        - schema_version_conflict
        - access_label_name_taken
        - workspace_name_taken
        - access_label_in_use
        - upload_expired
        - file_not_ingested
        - workspace_deleting
        - workspace_not_deletable
        - ingestion_in_progress
        - job_not_cancellable
        - confirmation_required
        - domain_not_published
        - domain_in_use
        - reserved_domain_slug
        - kg_not_built
        - kg_build_in_progress
        - session_busy
        - range_not_satisfiable
        - result_expired
        - access_denied
        - access_backstop_violation
        - access_mode_not_implemented
        - rate_limited
        - concurrency_limit_reached
        - quota_exceeded
        - corrupt_file
        - zero_byte_file
        - encrypted_file
        - parse_failed
        - ocr_failed
        - conversion_failed
        - sheetless_workbook
        - unplayable_media
        - unclassified_pages
        - job_cancelled
        - job_timeout
        - upstream_unavailable
        - internal_error
        - unauthorized
        - not_implemented
      title: ErrorCode
      type: string
  securitySchemes:
    APIKeyHeader:
      in: header
      name: X-API-Key
      type: apiKey
    UploadGrantHeader:
      description: >-
        Short-lived upload grant from POST
        /v1/workspaces/{workspace_id}/upload-grants.
      in: header
      name: X-Upload-Token
      type: apiKey

````