---
title: "Upload files"
method: POST
path: "/org/kb/upload"
tags: ["Knowledge Base"]
---

# Upload files

`POST /org/kb/upload`

## Request

- Base URL: `https://apiv2.senso.ai/api/v1`
- URL: `https://apiv2.senso.ai/api/v1/org/kb/upload`
- Auth: API key in header `X-API-Key`

Registers up to 10 files for ingestion and returns a presigned upload URL per accepted file (`status: upload_pending`) — PUT the file bytes to that URL to start ingestion. Files that conflict, duplicate, or fail validation come back with a per-file status instead. Omit `kb_folder_node_id` to create under the root. When no file is accepted the whole response is returned with `422`.

## Request body

- IngestionUploadRequest
  - `kb_folder_node_id` string, uuid, nullable: The folder to create the documents in. Omit or null for the root.
  - `files` IngestionUploadFileItem[], required: 1–10 files to register for ingestion.
    - `filename` string, required
    - `file_size_bytes` integer, required
    - `content_type` string, required: The file's MIME type (e.g. `application/pdf`).
    - `content_hash_md5` string, required: The file's MD5 hash, 32 hex characters.

## Response `200`

Per-file ingestion registration results (at least one file accepted).

- IngestionUploadResponse
  - `summary` IngestionUploadSummary, required
    - `total` integer, required
    - `success` integer, required: Files accepted for ingestion.
    - `skipped` integer, required: Files not accepted (any status other than `upload_pending`).
  - `results` IngestionUploadResultItem[], required
    - `filename` string, required
    - `status` string, required: `upload_pending` (accepted — PUT the bytes to `upload_url`), `conflict` (an active run is already processing this content), `duplicate` (the same file appears twice in the request), `invalid` (failed metadata validation), or `markdown_requires_raw_ingestion` (a `.md`/`.markdown` file was supplied — create markdown documents via the raw-text endpoint instead).
    - `ingestion_run_id` string, uuid
    - `content_id` string, uuid
    - `kb_node_id` string, uuid: The created/replaced document node. Absent on skipped items (any status other than `upload_pending`).
    - `upload_url` string: Presigned URL to PUT the file bytes to (accepted items only).
    - `expires_in` integer: Seconds until `upload_url` expires.
    - `error` string: Why the file was skipped (skipped items only).
    - `existing_content_id` string, uuid: The already-processing content's id (`conflict` items only).

## Other responses

- `400`: The request body was invalid — either it failed field validation (`ValidationErrorResponse`) or was otherwise malformed (`ErrorResponse`).
- `401`: Missing or invalid credentials — supply a valid org API key in the `X-API-Key` header.
- `402`: The organization is out of credits or has reached its spending limit.
- `403`: The API key is authenticated but not permitted to access this resource.
- `404`: The requested resource does not exist or is not visible to this key.
- `409`: The request conflicts with the current state (e.g. a duplicate).
- `422`: No file was accepted; the same result body reports why per file.

---

[API](https://skmtc.dev/senso/apis/senso-org-api.md) - [All operations](https://skmtc.dev/senso/apis/senso-org-api/llms.txt) - [OpenAPI document](https://skmtc.dev/senso/apis/senso-org-api/revisions/d789b4fcbe84?raw)
