Files, projects and knowledge

Upload files, organise work in projects, build and share knowledge bases, and manage teams through the REST API.

17 min read · Updated 28 September 2026

These are the resources that give a model something to work with. Files are uploads you attach to a message or run. Projects group chats, prompts and files with shared instructions and a default model. Knowledge bases are folder trees of documents that are indexed for retrieval and cited in answers. Teams are groups inside your workspace that you share projects, knowledge bases and conversations with.

All paths are relative to https://api.stickyprompts.com/api/v1. Every request runs as the user who owns the API key, so every ownership, sharing and workspace-role check applies to that user.

Conventions

  • Objects carry capitalised base fields ID, CreatedAt, UpdatedAt and DeletedAt (null on live records) next to snake_case fields.
  • Paginated endpoints read page (default 1) and size (default 10) and set the X-Total-Count, X-Page and X-Page-Size response headers. See Errors, pagination and quotas.
  • Errors are {"error": "message"}. Quota errors are 429 {"error": "Quota exceeded", "reason": "<reason>"}.

Files

The File object

Every upload endpoint returns the same File object.

{
  "ID": 4812,
  "CreatedAt": "2026-09-28T09:14:03.512Z",
  "UpdatedAt": "2026-09-28T09:14:03.512Z",
  "DeletedAt": null,
  "name": "northwind-q3-report.pdf",
  "path": "https://<storage-host>/<bucket>/231/k9Tq2vX8bLmN3pRs7wYz4cDf6gHj1kLm.pdf",
  "preview_path": "",
  "public_path": "",
  "user_id": 231,
  "workspace_id": 17,
  "project_id": null,
  "fileType": "file_search",
  "partial": false
}
FieldTypeMeaning
IDintegerThe file ID you pass as an attachment in conversations and runs.
namestringOriginal filename.
pathstringDirect URL of the stored object: <storage URI>/<bucket>/<user id>/<32 random chars><extension>. Whether it can be read without credentials depends on storage configuration outside the API.
preview_pathstringSet only for .docx (converted to a PDF preview) and .jfif (re-served as .jpg). Otherwise empty.
public_pathstringPublic share slug, empty when not shared. See POST /file/:id/public.
user_id, workspace_id, project_idinteger or nullUploader, their workspace at upload time, and the project if uploaded to one.
fileTypestringcamelCase key. image, file_search, spreadsheet, code_interpreter or code_interpreter_output, derived from the extension.
partialbooleantrue only while generated content is still being written. Always false for uploads.

How fileType is derived. The extension match is case-sensitive, so REPORT.PDF falls through to code_interpreter.

  • image: .png .jpg .jpeg .gif .webp .bmp .tiff .tif .ico .heic .heif .jfif .avif .svg
  • file_search: .c .cc .cpp .h .hpp .cs .css .scss .less .doc .docx .go .html .java .js .jsx .ts .tsx .vue .json .md .pdf .php .pptx .py .rb .sh .bat .ps1 .tex .txt .xml .yaml .yml .toml .ini .log .rtf .odt .rst .sql .kt .swift .rs .r .m .lua .pl
  • spreadsheet: .xlsx .xlsm .xlam .xltm .xltx .xls .csv .tsv .ods .ots .numbers
  • code_interpreter: anything else

POST /file

POST /api/v1/file
Permission files_manage

Uploads one or more files to your personal file library. The upload is synchronous: when the response arrives, each file is stored and has an ID. There is no MCP equivalent for uploading.

Body (multipart/form-data)
upload[] file form required
One part per file; repeat the field to upload several. The name is literally upload[]: parts under any other name are ignored and the request succeeds with [].

The API code enforces no file size limit and no extension allow-list here; any limit you hit comes from infrastructure in front of the API.

curl -X POST https://api.stickyprompts.com/api/v1/file \
  -H "Authorization: Bearer $STICKY_API_KEY" \
  -F "upload[]=@northwind-q3-report.pdf" \
  -F "upload[]=@pricing.xlsx"
import os, requests

with open("northwind-q3-report.pdf", "rb") as a, open("pricing.xlsx", "rb") as b:
    r = requests.post(
        "https://api.stickyprompts.com/api/v1/file",
        headers={"Authorization": f"Bearer {os.environ['STICKY_API_KEY']}"},
        files=[("upload[]", a), ("upload[]", b)],
    )
r.raise_for_status()
for f in r.json():
    print(f["ID"], f["name"], f["fileType"])
import { readFile } from "node:fs/promises";

const form = new FormData();
form.append("upload[]", new Blob([await readFile("northwind-q3-report.pdf")]), "northwind-q3-report.pdf");
form.append("upload[]", new Blob([await readFile("pricing.xlsx")]), "pricing.xlsx");

const files = await fetch("https://api.stickyprompts.com/api/v1/file", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.STICKY_API_KEY}` },
  body: form,
}).then((r) => r.json());
console.log(files.map((f) => [f.ID, f.fileType]));

Response. 200 with an array of File objects, in upload order.

Errors. 500 {"error": "could not upload files"} when the body is not valid multipart or storage fails.

Using an uploaded file

  • In a conversation message or run: "attachments": [{"id": 4812, "type": "file"}]. Add "temp": true to attach it for that call only. See Conversations.
  • On a prompt: POST /prompt/:id/file with {"file_ids": [4812]}. See Prompts and runs.
  • For spreadsheet processing: pass it as file_id to POST /xlsx/start-process. See Models and media.

GET /file

GET /api/v1/file
Permission files_get MCP tool list_files

Lists every file you uploaded, including files uploaded to projects and knowledge bases and generated spreadsheet outputs. No explicit sort order.

Query parameters
page integer query optional default 1
Page number.
size integer query optional default 10
Items per page.

Response. 200 with an array of File objects.

DELETE /file/:id

DELETE /api/v1/file/:id
Permission files_delete

Deletes a file you uploaded: removes it (and any preview) from storage and soft-deletes the record.

Path parameters
id integer path required
File ID.

Response. 204, no body.

Errors. 400 {"error": "Invalid file ID"}, 404 {"error": "File not found"}, 403 {"error": "You do not have permission to delete this file"} (you are not the uploader), 502 {"error": "Failed to delete file"}.

POST /file/:id/public

POST /api/v1/file/:id/public
Permission files_manage

Creates or replaces a public share slug for a file you uploaded. Calling it again generates a new slug and invalidates the old one. Anyone holding the slug can call GET /public/file/:slug without authentication; it returns the File object, including path (and 404 {"error": "File not found"} once revoked). The API does not define a share URL format on top of the slug.

Path parameters
id integer path required
File ID.

Response. 200 with the File object, public_path set to a new 32-character slug such as "Qx7_mB2kLr9-TtZwP4nV8cHd3JfG6sYq".

Errors. 400 Invalid file ID, 404 File not found, 403 {"error": "You do not have permission to share this file"}.

DELETE /file/:id/public

DELETE /api/v1/file/:id/public
Permission files_delete

Revokes the public link by clearing public_path.

Path parameters
id integer path required
File ID.

Response. 204. Errors. 400 Invalid file ID, 404 File not found, 403 {"error": "You do not have permission to modify this file"}.

Projects

A project groups conversations, prompts and files, and carries default instructions and a default model: the API side of Projects. Every :id accepts the numeric ID or the slug. Files uploaded to a project are automatically attached, for that call only, to conversations started in the project (use the X-Project-ID header on the conversation endpoints).

Access model

  • The owner can do everything. Only the owner can delete the project or change its sharing.
  • Others get access through shares to the whole workspace, individual users or teams; the effective flags are the union. Being shared grants view access (see the project and its files, pin it). Extra flags: prompt_management (manage its prompts), file_management (upload and delete files) and project_management (edit it with PATCH).

The Project object

{
  "ID": 305,
  "CreatedAt": "2026-09-01T12:00:00Z",
  "UpdatedAt": "2026-09-27T16:40:00Z",
  "DeletedAt": null,
  "slug": "k7Tq2vX",
  "name": "Northwind Launch",
  "description": "Everything for the Q4 launch",
  "instructions": "Answer in British English. Keep it short.",
  "color": "#3B82F6",
  "icon": "rocket",
  "ai_model_id": null,
  "auto_model_type": "best",
  "user_id": 231,
  "is_pinned": false,
  "has_files": true,
  "current_user_permission": { "prompt_management": false, "file_management": false, "project_management": false },
  "workspace_share": true,
  "workspace_share_flags": { "prompt_management": true, "file_management": false, "project_management": false },
  "user_shares": [
    { "user_id": 240, "user": { "ID": 240, "first_name": "Dora", "...": "..." },
      "flags": { "prompt_management": true, "file_management": true, "project_management": false } }
  ],
  "team_shares": [
    { "team_id": 12, "team": { "ID": 12, "name": "Marketing", "...": "..." },
      "flags": { "prompt_management": false, "file_management": true, "project_management": false } }
  ]
}
  • icon must be empty or one of folder rocket hat-glasses box flask-conical book-open briefcase circle-dollar-sign puzzle cpu plane cross database paw-print headset. color is a hex string and is not validated.
  • Normally exactly one of ai_model_id (a fixed model) or auto_model_type (best, balanced, fastest) is set.
  • ai_model, pin, files, conversations, prompts and has_files are omitted when not loaded.
  • current_user_permission reflects only flags granted through shares; the owner has full rights but usually sees all false.
  • has_files, current_user_permission, user_shares and team_shares are filled only by GET /project/:id. Elsewhere has_files is omitted, the permission flags are all false and the share lists are null.

POST /project

POST /api/v1/project

Creates a project. The default model comes from your preferences (preferred model or auto mode), falling back to the platform default. instructions cannot be set here: use PATCH.

Body
name string required
Project name.
description string optional
Free text.
color string optional
Hex color.
icon string optional
One of the icon names above.
curl -X POST https://api.stickyprompts.com/api/v1/project \
  -H "Authorization: Bearer $STICKY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Northwind Launch", "description": "Everything for the Q4 launch", "icon": "rocket" }'

Response. 201 with the Project object.

Errors. 400 ("Project name is required" or a binding error, "Invalid project icon"), 500 {"error": "Failed to create project"}.

GET /project

GET /api/v1/project

Lists projects you own plus projects shared with you, newest first.

Query parameters
page integer query optional default 1
Page number.
size integer query optional default 10
Items per page.
search string query optional
Case-insensitive match on name or description.
is_shared boolean query optional
true: only projects shared with you. false: only projects you own. Omit for both.

Response. 200 with an array of Project objects.

Access filtering is applied after pagination, so a page can hold fewer than size items and X-Total-Count can be higher than what you can see. is_pinned is always false in this list: use GET /project/pinned. Errors. 400 {"error": "Invalid is_shared parameter"}.

GET /project/pinned

GET /api/v1/project/pinned
Permission projects_get

Your pinned projects, oldest pin first, with is_pinned: true and pin populated. Not paginated.

GET /project/:id

GET /api/v1/project/:id
Permission projects_get MCP tool get_project

Returns the full Project object.

Path parameters
id string path required
Project ID or slug.
Query parameters
include_files string query optional
true includes the project’s files as files (File objects).

Errors. 404 {"error": "Project not found"}, 403 {"error": "You don't have access to this project"}.

PATCH /project/:id

PATCH /api/v1/project/:id

Updates a project. You must be the owner or hold project_management. Every field is optional, but send at least one.

Path parameters
id string path required
Project ID or slug.
Body
name string optional
Cannot be empty.
description string optional
Free text.
color string optional
Hex color.
icon string optional
Icon name, or "" to clear.
instructions string optional
Project-level instructions for the model. Your workspace’s sensitive-data rules apply: matching content is redacted or the request is rejected.
ai_model_id integer optional
Sets a fixed model and clears auto_model_type.
auto_model_type string optional
best, balanced or fastest. Clears ai_model_id.

Response. 200 with the Project object.

Errors. 400 for Project name cannot be empty, only one of ai_model_id or auto_model_type may be set, invalid auto_model_type, Invalid project icon, No fields provided for update, or a sensitive-data block ({"error": "...", "code": "..."}); 404 Project not found; 403 You don't have access to this project.

DELETE /project/:id

DELETE /api/v1/project/:id

Deletes the project together with its conversations, project files, pins, prompts and share records. Owner only.

Path parameters
id string path required
Project ID or slug.

Response. 204. Errors. 404 Project not found, 403 You don't have access to this project.

POST /project/:id/pin

POST /api/v1/project/:id/pin

Toggles your pin on a project you can view. At most 5 pinned projects per user.

Path parameters
id string path required
Project ID or slug.

Response. 200 {"message": "Project pinned", "pinned": true} or 200 {"message": "Project unpinned", "pinned": false}.

Errors. 400 {"error": "Maximum 5 projects can be pinned"}, 404, 403.

PATCH /project/:id/share_with_workspace

PATCH /api/v1/project/:id/share_with_workspace

Shares the project with your whole workspace, or removes that share. Owner only; you must belong to a workspace. Flags you omit keep their current value.

Path parameters
id string path required
Project ID or slug.
Body
share boolean optional
true shares with the workspace, false removes the share. Omitted: nothing changes.
prompt_management boolean optional
Applied only together with share: true.
file_management boolean optional
Applied only together with share: true.
project_management boolean optional
Applied only together with share: true.

Response. 200 {"message": "Project shared with workspace"}, also when unsharing.

Errors. 403 {"error": "You don't have access to this project's share settings"}, 400 {"error": "User is not in a workspace"}, 404.

PATCH /project/:id/share_with_user

PATCH /api/v1/project/:id/share_with_user

Shares the project with individual users in your workspace. Owner only.

Path parameters
id string path required
Project ID or slug.
Body
shares array required
Entries { "user_id", "share", "prompt_management", "file_management", "project_management" }. share: true grants view access; share: false removes the user’s share entirely; omitted share only patches the flags given.
{
  "shares": [
    { "user_id": 240, "share": true, "prompt_management": true, "file_management": true },
    { "user_id": 251, "share": false }
  ]
}

Entries are applied in order and the request stops at the first failing entry; earlier entries stay applied.

Response. 200 {"message": "Project sharing with users updated"}.

Errors. 404 {"error": "User not found"}, 400 {"error": "Target user is not in the same workspace"}, plus the owner and workspace errors above.

PATCH /project/:id/share_with_team

PATCH /api/v1/project/:id/share_with_team

The same as share_with_user, but entries use team_id. The team must belong to your workspace.

Path parameters
id string path required
Project ID or slug.
Body
shares array required
Entries { "team_id", "share", "prompt_management", "file_management", "project_management" }.

Response. 200 {"message": "Project sharing with teams updated"}.

Errors. 404 {"error": "Team not found"}, 400 {"error": "Target team is not in the same workspace"}.

POST /project/:id/file

POST /api/v1/project/:id/file

Uploads files into a project. You must be the owner or hold file_management. Same mechanics as POST /file: synchronous, multipart/form-data, no size limit or extension allow-list in the API code. Each resulting File has project_id set.

Path parameters
id string path required
Project ID or slug.
Body (multipart/form-data)
upload[] file form required
One part per file; repeat for several.

Response. 200 with an array of File objects.

Errors. 404 Project not found, 403 {"error": "You don't have access to this project"}, 500 {"error": "could not upload files"}.

GET /project/:id/file

GET /api/v1/project/:id/file
Permission projects_get

Lists a project’s files. Each is a File object plus can_delete (true if you can manage project files or uploaded the file). preview_path falls back to path when there is no preview.

Path parameters
id string path required
Project ID or slug.
[
  {
    "ID": 4820,
    "name": "brand-guidelines.pdf",
    "path": "https://<storage-host>/<bucket>/231/Hq3...pdf",
    "preview_path": "https://<storage-host>/<bucket>/231/Hq3...pdf",
    "project_id": 305,
    "fileType": "file_search",
    "partial": false,
    "can_delete": true
  }
]

DELETE /project/:id/file/:fileId

DELETE /api/v1/project/:id/file/:fileId

Removes a file record from the project. You need view access, and either file_management (or ownership of the project) or to be the file’s uploader.

Path parameters
id string path required
Project ID or slug.
fileId integer path required
File ID.

Response. 200 {"message": "File deleted successfully"}.

Errors. 400 Invalid file ID, 404 Project not found, 404 {"error": "File not found in project"}, 403 {"error": "You don't have access to delete this file"}.

Knowledge bases

A knowledge base is a folder tree of documents that are chunked and indexed for retrieval: the API side of Knowledge bases. Use one in a conversation or run by passing knowledge_base_ids, optionally with knowledge_base_limit_node_ids to restrict retrieval to specific folders or files, and world_knowledge. Knowledge base IDs are numeric only (no slugs).

Access levels (current_user_permission and share access_type):

ValueCan do
kb_accessRead the knowledge base and use it in chats.
kb_uploadThe above, plus upload files.
kb_editThe above, plus rename it, manage folders and delete any file.
noneNo access.

The owner always has kb_edit. Only the owner can delete the knowledge base or change its sharing. Uploaders can always delete their own files.

The Knowledge base object

{
  "ID": 44,
  "CreatedAt": "2026-09-10T08:30:00Z",
  "UpdatedAt": "2026-09-10T08:30:00Z",
  "DeletedAt": null,
  "user_id": 231,
  "user": { "ID": 0, "email": "", "first_name": "", "...": "zero values" },
  "name": "Northwind Help Center",
  "description": "Policies, onboarding and FAQs",
  "color": "#10B981",
  "icon": "book-open",
  "document_count": 18,
  "member_count": 6,
  "current_user_permission": "kb_edit",
  "user_shares": [
    { "user_id": 240, "user": { "ID": 240, "first_name": "Dora", "...": "..." }, "access_type": "kb_upload", "added_at": "2026-09-11T09:00:00Z" }
  ],
  "team_shares": [
    { "team_id": 12, "team": { "ID": 12, "name": "Customer Support", "...": "..." }, "access_type": "kb_access", "added_at": "2026-09-11T09:05:00Z" }
  ]
}

The owner object user is never loaded and always has zero values: use user_id. document_count counts files, not folders. member_count is returned only by GET and PUT on a single knowledge base.

POST /knowledge-bases

POST /api/v1/knowledge-bases

Creates a knowledge base.

Body
name string required
Knowledge base name.
icon string required
One of the icon names listed under Projects.
description string optional
Free text.
color string optional
Hex color (not validated).

Response. 201 with the knowledge base, document_count: 0, member_count: 0 and empty share lists.

Errors. 400 {"error": "Knowledge base name is required"}, 400 {"error": "Invalid knowledge base icon"}.

GET /knowledge-bases

GET /api/v1/knowledge-bases

Lists every knowledge base you own or can access through a share. Not paginated. Each item has the knowledge base fields plus document_count and current_user_permission (no member_count or share lists).

GET /knowledge-bases/:id

GET /api/v1/knowledge-bases/:id

Returns the full knowledge base. Requires at least kb_access.

Path parameters
id integer path required
Knowledge base ID.

Errors. 400 Invalid knowledge base ID, 404 Knowledge base not found, 403 {"error": "You don't have access to this knowledge base"}.

PUT /knowledge-bases/:id

PUT /api/v1/knowledge-bases/:id

Replaces name, description, color and icon, with the same body and validation as POST. An omitted description is cleared. Requires kb_edit.

Path parameters
id integer path required
Knowledge base ID.
Body
name string required
Knowledge base name.
icon string required
Icon name.
description string optional
Cleared when omitted.
color string optional
Hex color.

Response. 200 with the full knowledge base.

Errors. As for POST, plus 403 {"error": "You are not authorized to update this knowledge base"} and 404.

DELETE /knowledge-bases/:id

DELETE /api/v1/knowledge-bases/:id

Deletes the knowledge base with all its folders, files, stored objects and index data. Owner only.

Path parameters
id integer path required
Knowledge base ID.

Response. 204. Errors. 404 Knowledge base not found, 403 {"error": "You are not authorized to delete this knowledge base"}.

PATCH /knowledge-bases/:id/share_with_user

PATCH /api/v1/knowledge-bases/:id/share_with_user

Shares a knowledge base with users in your workspace. Owner only; you must be in a workspace. Removing a share triggers a re-check of agents that use this knowledge base.

Path parameters
id integer path required
Knowledge base ID.
Body
shares array required
Entries { "user_id", "access_type" }. access_type is kb_access, kb_upload or kb_edit to set (replacing the previous level), or null, "" or none to remove the share.
{
  "shares": [
    { "user_id": 240, "access_type": "kb_upload" },
    { "user_id": 251, "access_type": null }
  ]
}

Entries are applied in order and processing stops at the first failing entry.

Response. 200 {"message": "Knowledge base sharing with users updated"}.

Errors. 400 {"error": "User is not in a workspace"}, 403 {"error": "You don't have access to this knowledge base's share settings"}, 404 User not found, 400 Target user is not in the same workspace, 400 {"error": "Invalid access_type"}.

PATCH /knowledge-bases/:id/share_with_team

PATCH /api/v1/knowledge-bases/:id/share_with_team

The same as share_with_user, with team_id instead of user_id.

Path parameters
id integer path required
Knowledge base ID.
Body
shares array required
Entries { "team_id", "access_type" }.

Response. 200 {"message": "Knowledge base sharing with teams updated"}.

GET /knowledge-bases/:id/folders

GET /api/v1/knowledge-bases/:id/folders

Lists the direct children, folders and files, of one level of the tree. This is also the endpoint to poll for a file’s indexing status.

Path parameters
id integer path required
Knowledge base ID.
Query parameters
parent_id integer query optional
Folder node ID to list. Omit (or pass a non-numeric value) for the root.
{
  "folders": [
    { "ID": 501, "name": "Policies", "parent_id": null, "size": 2483112,
      "CreatedAt": "2026-09-10T08:31:00Z", "UpdatedAt": "2026-09-10T08:31:00Z" }
  ],
  "files": [
    {
      "ID": 502,
      "name": "Northwind Refund Policy.md",
      "parent_id": null,
      "file_data_id": 4830,
      "file_data": { "ID": 4830, "name": "Northwind Refund Policy.md", "fileType": "file_search", "...": "..." },
      "size": 912334,
      "download_url": "https://<storage-host>/<bucket>/231/Zp8...md",
      "preview_url": "https://<storage-host>/<bucket>/231/Zp8...md",
      "status": "done",
      "status_progress": 100,
      "can_delete": true,
      "CreatedAt": "2026-09-10T08:32:00Z",
      "UpdatedAt": "2026-09-10T08:33:10Z"
    }
  ]
}

POST /knowledge-bases/:id/folders

POST /api/v1/knowledge-bases/:id/folders

Creates a folder. Requires kb_edit. Names must be unique among siblings; folders and files share the namespace.

Path parameters
id integer path required
Knowledge base ID.
Body
name string required
Folder name.
parent_id integer optional
A folder in the same knowledge base. Omit or null for the root.

Response. 201. The current implementation returns the folder with zero values ("ID": 0, empty name) even though it was created: re-list with GET /knowledge-bases/:id/folders to get the new folder’s ID.

Errors. 403 {"error": "You don't have access to create folders in this knowledge base"}, 400 {"error": "Folder name is required"}, 404 {"error": "Parent folder not found"}, 400 {"error": "Folder or document with this name already exists"}.

GET /knowledge-bases/:id/folders/:folderId

GET /api/v1/knowledge-bases/:id/folders/:folderId

Returns one folder: ID, name, parent_id, size, CreatedAt, UpdatedAt. Requires kb_access.

Path parameters
id integer path required
Knowledge base ID.
folderId integer path required
Folder node ID.

Errors. 404 {"error": "Folder not found"}, 403.

PATCH /knowledge-bases/:id/folders/:folderId

PATCH /api/v1/knowledge-bases/:id/folders/:folderId

Renames a folder. Folders cannot be moved. Requires kb_edit.

Path parameters
id integer path required
Knowledge base ID.
folderId integer path required
Folder node ID.
Body
name string required
New name. A blank name gives 400 {"error": "No fields provided for update"}.

Response. 200 with the updated folder. Errors. 400 {"error": "Folder or document with this name already exists"}.

DELETE /knowledge-bases/:id/folders/:folderId

DELETE /api/v1/knowledge-bases/:id/folders/:folderId

Deletes the folder and everything under it, including stored files and index data. Requires kb_edit.

Path parameters
id integer path required
Knowledge base ID.
folderId integer path required
Folder node ID.

Response. 204.

POST /knowledge-bases/:id/files

POST /api/v1/knowledge-bases/:id/files

Uploads one document per request. Requires kb_upload or higher; quota is checked first. The file must have a unique name within the target folder. No file size limit is enforced in the API code.

Path parameters
id integer path required
Knowledge base ID.
Body (multipart/form-data)
file file form required
The document. The field name is file, not upload[]. Allowed extensions (case-insensitive): .txt .md .markdown .pdf .docx .xlsx .csv .png .jpg .jpeg.
folder_id string form optional
Target folder node ID. Omit for the root.
curl -X POST https://api.stickyprompts.com/api/v1/knowledge-bases/44/files \
  -H "Authorization: Bearer $STICKY_API_KEY" \
  -F "file=@Northwind Refund Policy.md" \
  -F "folder_id=501"
import os, time, requests

BASE = "https://api.stickyprompts.com/api/v1"
H = {"Authorization": f"Bearer {os.environ['STICKY_API_KEY']}"}

with open("Northwind Refund Policy.md", "rb") as f:
    node = requests.post(f"{BASE}/knowledge-bases/44/files", headers=H,
                         files={"file": f}, data={"folder_id": "501"}).json()

# Wait until the document is indexed before relying on it
while True:
    listing = requests.get(f"{BASE}/knowledge-bases/44/folders", headers=H,
                           params={"parent_id": 501}).json()
    status = next(x["status"] for x in listing["files"] if x["ID"] == node["ID"])
    if status in ("done", "error"):
        print(status)
        break
    time.sleep(3)
import { readFile } from "node:fs/promises";

const BASE = "https://api.stickyprompts.com/api/v1";
const headers = { Authorization: `Bearer ${process.env.STICKY_API_KEY}` };

const form = new FormData();
form.append("file", new Blob([await readFile("Northwind Refund Policy.md")]), "Northwind Refund Policy.md");
form.append("folder_id", "501");
const node = await fetch(`${BASE}/knowledge-bases/44/files`, { method: "POST", headers, body: form }).then((r) => r.json());

for (;;) {
  const { files } = await fetch(`${BASE}/knowledge-bases/44/folders?parent_id=501`, { headers }).then((r) => r.json());
  const { status } = files.find((x) => x.ID === node.ID);
  if (status === "done" || status === "error") { console.log(status); break; }
  await new Promise((r) => setTimeout(r, 3000));
}

Response. 201 with a file node (the same shape as the files items above) in status: "uploading", status_progress: 0. Upload, text extraction and indexing then run in the background:

statusstatus_progress
uploadingUpload percentage
processing0
indexingIndexing percentage
done100
errorProcessing failed

Poll GET /knowledge-bases/:id/folders?parent_id=<folder_id> until the file is done before relying on it in retrieval.

Errors. 403 {"error": "You don't have access to upload files to this knowledge base"}, 429 quota exceeded, 400 {"error": "File is required"}, 400 {"error": "Invalid folder ID"}, 404 {"error": "Parent folder not found"}, 400 {"error": "File extension not allowed. Allowed extensions: .txt, .md, ..."}, 400 {"error": "Folder or document with this name already exists"}.

DELETE /knowledge-bases/:id/files/:fileId

DELETE /api/v1/knowledge-bases/:id/files/:fileId

Deletes a document node, its stored file and its index data. Requires kb_edit, or being the file’s uploader.

Path parameters
id integer path required
Knowledge base ID.
fileId integer path required
The node ID from the folder listing, not the File ID.

Response. 204. Errors. 404 {"error": "File not found"}, 403 {"error": "You don't have access to delete this file"}.

Teams

Teams live inside a workspace and are share targets for projects, knowledge bases and conversations. Team roles are owner and member; in workspace-wide listings, none means you are not in the team. See Users and teams for the admin view.

ActionAllowed for
Create a teamWorkspace owner or admin
List all teams in the workspaceWorkspace owner or admin
See a team’s membersTeam members, workspace owner or admin
Rename or delete a team, add or remove membersTeam owner, workspace owner or admin
Change a member’s role, add a member as owner, remove an ownerWorkspace owner or admin

The Team object

{
  "ID": 12,
  "CreatedAt": "2026-09-05T10:00:00Z",
  "UpdatedAt": "2026-09-05T10:00:00Z",
  "DeletedAt": null,
  "workspace_id": 17,
  "workspace": { "ID": 0, "name": "", "...": "zero values" },
  "name": "Marketing",
  "description": "Campaigns and content",
  "color": "#F472B6",
  "member_count": 0
}

workspace is never loaded and is always a zero-valued object. member_count is meaningful only in the list endpoints.

A team member is a User object (ID, email, first_name, last_name, status, workspace_id and more) with the member’s role added at the top level.

POST /teams

POST /api/v1/teams
Permission teams_manage

Creates a team and adds you as its owner. Workspace owner or admin only.

Body
name string required
Team name.
description string optional
Free text.
color string optional
Hex color (not validated).

Response. 201 with the Team object.

Errors. 403 {"error": "You are not authorized to create a team"}, 400 {"error": "Team name is required"}.

GET /teams

GET /api/v1/teams
Permission teams_get MCP tool list_teams

Teams you belong to, each with member_count and current_user_role. Not paginated. Returns null, not [], when you are in no team.

GET /teams/all

GET /api/v1/teams/all
Permission teams_get

Every team in your workspace, with member_count and current_user_role (none if you are not a member). Workspace owner or admin only. Returns null when the workspace has no teams.

Errors. 404 {"error": "User is not a member of a workspace"}, 403 {"error": "You are not authorized to view all teams in this workspace"}.

GET /teams/:id/members

GET /api/v1/teams/:id/members

Lists a team’s members. Team members and workspace owners or admins only.

Path parameters
id integer path required
Team ID.

Response. 200 with an array of team members.

Errors. 400 Invalid team ID, 404 {"error": "Team not found"}, 403 {"error": "You are not authorized to view the members of this team"}.

PUT /teams/:id

PUT /api/v1/teams/:id
Permission teams_manage

Replaces a team’s name, description and color; omitted description and color are cleared. Team owner or workspace owner or admin.

Path parameters
id integer path required
Team ID.
Body
name string required
Team name.
description string optional
Cleared when omitted.
color string optional
Cleared when omitted.

Response. 200 with the updated Team.

Errors. 403 {"error": "You are not authorized to update this team"}, 400 Team name is required, 404 Team not found.

DELETE /teams/:id

DELETE /api/v1/teams/:id
Permission teams_delete

Deletes a team that has at most one member. Team owner or workspace owner or admin.

Path parameters
id integer path required
Team ID.

Response. 204. Errors. 409 {"error": "Cannot delete a team with other members"}, 403 {"error": "You are not authorized to delete this team"}.

POST /teams/:id/members

POST /api/v1/teams/:id/members
Permission teams_manage

Adds a workspace member to a team. Team owner or workspace owner or admin; adding someone as owner needs workspace owner or admin.

Path parameters
id integer path required
Team ID.
Body
user_id integer required
A user in your workspace.
role string required
Always send member or owner; the value is not validated beyond the owner check.

Response. 201. The body currently contains only role, with every user field at zero values: call GET /teams/:id/members to read the member back.

Errors. 403 {"error": "You are not authorized to add a team member"}, 403 when adding an owner without workspace admin rights, 409 {"error": "User is already a member of this team"}, 404 {"error": "User not found"}, 403 {"error": "User is not a member of this workspace"}.

PATCH /teams/:id/members/:memberUserId

PATCH /api/v1/teams/:id/members/:memberUserId
Permission teams_manage

Changes a member’s role. Changing role needs workspace owner or admin.

Path parameters
id integer path required
Team ID.
memberUserId integer path required
The member’s user ID.
Body
role string required
owner or member.

Response. 200 with the team member and the new role.

Errors. 404 {"error": "Team member not found"}, 403 {"error": "You are not authorized to update this team member"}, 403 {"error": "Updating the role of this team member requires workspace admin permissions"}.

DELETE /teams/:id/members/:memberUserId

DELETE /api/v1/teams/:id/members/:memberUserId
Permission teams_manage

Removes a member. Team owner or workspace owner or admin; removing an owner needs workspace owner or admin. You cannot remove yourself.

Path parameters
id integer path required
Team ID.
memberUserId integer path required
The member’s user ID.

Response. 204.

Errors. 403 {"error": "You cannot remove yourself from a team"}, 403 {"error": "You are not authorized to remove this team member"}, 404 Team member not found, 403 {"error": "Removing an owner requires workspace admin permissions"}.