---
title: "Create subfolder"
method: POST
path: "/knowledgeBase/{kbId}/folder/{folderId}/subfolder"
tags: ["Knowledge Base"]
---

# Create subfolder

`POST /knowledgeBase/{kbId}/folder/{folderId}/subfolder`

## Request

- Base URL: `https://app.pipeshub.com/api/v1`
- URL: `https://app.pipeshub.com/api/v1/knowledgeBase/{kbId}/folder/{folderId}/subfolder`
- Auth: one of:
  - HTTP bearer
  - OAuth 2
    - Authorization code: `/api/v1/oauth2/authorize`
    - Client credentials
    - Token URL: `/api/v1/oauth2/token` scopes: `kb:write`

Create a nested subfolder inside an existing parent folder, named by the `folderId`
path parameter. It runs the same validator and handler as
`POST /knowledgeBase/{kbId}/folder`. A `folderId` query parameter is still read: one
that names a different folder than the path is refused with `400`.

**Required permission:** WRITER or higher

**Folder features:**

- Organize records hierarchically
- Support nested subfolders, up to 20 levels deep
- Inherit parent KB permissions

**Naming rules:**

- Whitespace around the name is removed first; then 1–255 characters
- A name holding an HTML tag, a `javascript:` URL or an inline event handler is
  refused with `400` before authentication; one holding a printf-style format
  specifier (`%s`, `%x`, `%n`, `%p`) is refused with `400` by the gateway controller
- Spaces and special characters allowed
- A name already used by a folder in the same parent is refused with `409`, ignoring
  case (`Reports` and `rEPORTS` clash). A file of the same name, or a folder of the
  same name under another parent, does not clash.

**Request:** only `folderName` and the `folderId` query parameter are read; other body
fields and query parameters are ignored, except a `folderId`, `parentId` or
`parent_id` in the body and a `parentId` or `parent_id` query parameter, which are
refused with `400`.

**Access:** a caller with no role on the knowledge base gets `404`
(`Knowledge base <kbId> not found`), a `READER` gets `403`.

**Response:** Returns `id` and `name` for the created folder.

## Path parameters

- `kbId` string, uuid, required
- `folderId` string, uuid, required

## Query parameters

- `folderId` string

## Request body

- object
  - `folderName` string, required: Name of the folder. Whitespace around it is removed first, so a name made only of whitespace is refused as empty. It cannot contain `/` or `\`, which folder paths use as separators.

## Response `200`

Folder created successfully

- FolderCreateResponseSchema: Response returned when a folder is created (root or nested subfolder)
  - `id` string, required: Unique folder identifier
  - `name` string, required: Name of the folder

## Other responses

- `400`: Invalid request. Possible reasons: - `folderName` missing, `null`, not a string, empty or only whitespace, or longer than 255 characters; `kbId` or the path `folderId` not a UUID; the query `folderId` empty (`VALIDATION_ERROR`) - The query `folderId` names a different folder than the path (`HTTP_BAD_REQUEST`, `Conflicting folderId in path and query parameters`) - A `folderId`, `parentId` or `parent_id` in the body, or a `parentId` or `parent_id` query parameter (`VALIDATION_ERROR`, `To create a subfolder, use the subfolder route.`): name the parent in the path only - `folderName` contains an HTML tag, a `javascript:` URL or an inline event handler (`HTTP_BAD_REQUEST`). This check runs before authentication. - `folderName` contains a format specifier (`HTTP_BAD_REQUEST`) - `folderName` contains `/` or `\` (`VALIDATION_ERROR`, `Folder names cannot contain "/" or "\".`) - The parent is already 20 levels deep (`Folders can be nested at most 20 levels deep. ...`) - `kbId` or `folderId` holds a character that cannot stand in a URL path segment (`/`, `\`, `?`, `#`, `%`, a control character) or is `.` or `..` (`HTTP_BAD_REQUEST`) Also returned, before authentication, when a query value, or any string in a JSON or form-encoded body, looks like markup to the app-wide XSS filter: an HTML tag, a script tag, `<iframe`, `<object`, `<embed` or `<svg` tag, a word starting with `on` followed by `=` (meant for inline event handlers such as `onerror=`, it also catches plain text such as `one=1`), a `javascript:` or `data:text/html` URL, an encoded script tag (`&lt;script`, `%3cscript`), or any string longer than 100,000 characters (`HTTP_BAD_REQUEST`, "HTML tags, scripts, and XSS content are not allowed in ...", naming the field or query parameter; a string over 100,000 characters is refused as too long instead). A JSON body that does not parse is refused the same way, also before authentication (`HTTP_BAD_REQUEST`, "The request body is not valid JSON.").
- `401`: Unauthorized - Valid bearer token required
- `403`: Forbidden. Possible reasons: - OAuth token lacks the `kb:write` scope - User is `READER` (`... OWNER or WRITER role required, but your role is: READER.`)
- `404`: - `Knowledge base <kbId> not found`: unknown knowledge base, or the caller holds no role on it - `Parent folder <folderId> not found in KB <kbId>`: `folderId` is not a folder of this knowledge base (unknown id, or a file)
- `409`: Conflict. Possible reasons: - A folder with this name already exists at the knowledge base root or within the parent folder - The parent folder is in Recently deleted; restore it first, or choose another folder The knowledge base is being deleted (`error.code` is `HTTP_KB_BEING_DELETED`): it can no longer be changed. Reads still work and show `status: DELETING`; retry the delete instead.
- `500`: Internal server error while creating folder. A JSON body larger than 10 MB, or a form-encoded body larger than 100 KB or with more than 1000 fields, is answered `413` by the app-wide body parsers instead, also before authentication.
- `503`: Connector service unavailable or connection refused

## Changes

- **2026-10-28** `dbb5e203b445`: 3 breaking, 1 info
  - added the new required `query` request parameter `folderId`
  - for the `path` request parameter `kbId`, the format changed from no format to `uuid`
  - added the pattern `^(?![\s\S]*?(?:(?<!\w)%(?:\d{1,10}\$)?[#0\-+ ]{0,10}(?:\d{1,10})?(?:\.\d{1,10})?(?:h{1,2}|l{1,2}|L|z|j|t)?[nsxXp]))[\s\S]*?\S` to the request property `folderName`
  - added the media type `application/x-www-form-urlencoded` to the request body
- **2026-10-26** `fc76aa045994`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/pipeshub-ai/apis/pipeshub-api/changes/knowledgeBase/:kbId/folder/:folderId/subfolder/post.md)

---

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