Developers and AI agents
The Endorr Cloud API
Put Endorr Cloud inside your own apps, shops, scripts and AI agents. One API key, plain HTTP, and paths you already know: upload a file in one request.
Everything is JSON over HTTPS at https://auth.endorr.com/v1/cloud. There is no SDK to install, no OAuth dance, and no separate upload host to learn. AI agents can use the same key through the MCP server or the OpenAPI document.
Quickstart
- In Endorr Studio, open Settings, API keys and create a key. Give it Read files and Add and change files.
- Copy the key. It starts with
endorr_sk_and is shown once. - Upload your first file:
export ENDORR_KEY=endorr_sk_...
curl -T invoice.pdf \
-H "Authorization: Bearer $ENDORR_KEY" \
"https://auth.endorr.com/v1/cloud/files?path=/Invoices/2026/invoice.pdf"That is the whole flow. The Invoices and 2026 folders are created for you, and the answer tells you the file's id and where it landed:
{
"file": {
"type": "file",
"id": "file_01JB8Q...",
"name": "invoice.pdf",
"path": "/Invoices/2026/invoice.pdf",
"folder_id": "fld_01JB8Q...",
"size_bytes": 48213,
"content_type": "application/pdf",
"sha256": "9f2c...",
"status": "ready",
"created_via": "api",
"created_at": "2026-10-21T09:30:00.000Z",
"updated_at": "2026-10-21T09:30:00.000Z"
},
"replaced": false
}AI agents and MCP
The API is built to be used by agents as much as by people. Point an agent at any of these and it can work out the rest:
| What | Where |
|---|---|
| MCP server (Streamable HTTP) | https://auth.endorr.com/v1/cloud/mcp |
| OpenAPI 3.1 document | https://auth.endorr.com/v1/cloud/openapi.json |
| These docs as one Markdown file | https://endorr.com/developers.md |
| Index for LLMs | https://endorr.com/llms.txt and https://endorr.com/llms-full.txt |
| Discovery (no key needed) | GET https://auth.endorr.com/v1/cloud |
Connect an agent over MCP. Create a key with only the permissions the agent needs, ideally limited to one folder, and add the server with the key as a bearer token. In Claude Code:
claude mcp add --transport http endorr-cloud https://auth.endorr.com/v1/cloud/mcp \
--header "Authorization: Bearer endorr_sk_..."Clients configured with JSON (Claude Desktop, Cursor, VS Code and others) take an entry like this:
{
"mcpServers": {
"endorr-cloud": {
"type": "http",
"url": "https://auth.endorr.com/v1/cloud/mcp",
"headers": { "Authorization": "Bearer endorr_sk_..." }
}
}
}The agent sees only the tools its key allows:
| Tool | Does | Needs |
|---|---|---|
whoami | Who the key acts for, its permissions and folder, storage | files.read |
list_folder | List a folder by path or id | files.read |
search | Find files and folders by name | files.read |
get_file_info | A file's details | files.read |
read_file | Text and images inline (up to 1 MB), else a download link | files.read |
get_download_link | A short-lived link to the bytes | files.read |
write_file | Create or overwrite a file from text or base64 | files.write |
create_folder | Create a folder and missing parents | files.write |
move_or_rename | Rename or move a file or folder | files.write |
move_to_trash | Trash a file or folder (restorable for 28 days) | files.delete |
create_share_link | A public view-only link | shares.create |
Teach a coding agent the API. Paste this into your project's AGENTS.md or CLAUDE.md:
## Endorr Cloud
Files live in Endorr Cloud. API docs: https://endorr.com/developers.md
- Base URL: https://auth.endorr.com/v1/cloud
- Auth: `Authorization: Bearer $ENDORR_KEY` (never commit the key)
- Upload: `PUT /v1/cloud/files?path=/folder/name.ext` with the file as the body
- List: `GET /v1/cloud/folders?path=/folder`; download: `GET /v1/cloud/files/download?path=…` (follow the redirect)
- Errors are `{ "error": { "code", "message", "docs_url" } }`; branch on `code`files.read cannot see or change anything else. Agents may not trash files or create public links unless you give the key files.delete or shares.create.API keys
Send your key on every request as Authorization: Bearer endorr_sk_…. Check a key with GET /v1/cloud/me: it answers who the key acts for, what it may do and how much storage is used.
A key acts as you, inside the workspace you made it in. It can never do more than you can, and only what you allowed when you made it:
| Permission | Allows |
|---|---|
files.read | List, search and download files and folders |
files.write | Upload files, create folders, rename and move |
files.delete | Move files and folders to the trash (restorable for 28 days) |
shares.create | Create view-only share links |
Limit a key to one folder and it sees that folder as /, and nothing outside it. That is the safest choice for an app or agent that only needs a place of its own. You can change a key's permissions later without changing the key, set an expiry date, and revoke it at any time; it stops working at once.
Paths and ids
Use whichever is easier. Every file and folder can be reached by its path, like /Clients/Acme/logo.png, or by its id, like file_01JB8Q… or fld_01JB8Q…. Ids never change when you rename or move something, so store ids if you keep references.
Paths start at /, are case-sensitive, and never contain . or ... Encode them in a query string as usual (?path=/My%20files/a.pdf). The folder id root also means /.
Upload a file
PUT /v1/cloud/files?path=… with the file as the request body, up to 100 MB. POST works too. The content type comes from the file extension, or from your Content-Type header for extensions we do not know.
When a file with the same name is already there, on_conflict decides:
rename(default): keep both. The new one becomesinvoice (2).pdf. Nothing is ever lost.overwrite: replace the old file's contents. It keeps its id and share links. The answer has"replaced": true.fail: answer409 already_existswith the existing file's id indetails.file_id.
curl -T report.pdf -H "Authorization: Bearer $ENDORR_KEY" \
"https://auth.endorr.com/v1/cloud/files?path=/Reports/weekly.pdf&on_conflict=overwrite"Download a file
GET /v1/cloud/files/{id}/download, or by path with GET /v1/cloud/files/download?path=…. The answer is a redirect to a short-lived link to the bytes, so tell your client to follow redirects. Add redirect=false to get { "url", "expires_at" } instead.
curl -L -o invoice.pdf -H "Authorization: Bearer $ENDORR_KEY" \
"https://auth.endorr.com/v1/cloud/files/download?path=/Invoices/2026/invoice.pdf"File details without the bytes: GET /v1/cloud/files/{id} or GET /v1/cloud/files?path=….
List a folder
GET /v1/cloud/folders?path=/Invoices or GET /v1/cloud/folders/{id}. One list of items, folders first, then files, by name. Each item has a type of folder or file.
curl -H "Authorization: Bearer $ENDORR_KEY" "https://auth.endorr.com/v1/cloud/folders?path=/Invoices"Up to 100 items per page (limit up to 500). When next_cursor is not null, pass it as cursor for the next page.
Create folders
POST /v1/cloud/folders with { "path": "/Clients/Acme/2026" } makes every missing folder on the way. Calling it again is safe: it answers 200 with the existing folder and "created": false instead of an error.
Rename, move, delete
PATCH /v1/cloud/files/{id} or PATCH /v1/cloud/folders/{id} with a new name, a move_to path, or both. The destination folder is created when missing.
curl -X PATCH -H "Authorization: Bearer $ENDORR_KEY" -H "Content-Type: application/json" \
-d '{"name": "invoice-paid.pdf", "move_to": "/Invoices/Paid"}' \
"https://auth.endorr.com/v1/cloud/files/file_01JB8Q..."DELETE /v1/cloud/files/{id} and DELETE /v1/cloud/folders/{id} move things to the trash. You can restore them in Endorr Studio for 28 days.
Share links
POST /v1/cloud/files/{id}/share (or /folders/{id}/share) makes a view-only link anyone can open, for 7 days unless you pass expires_in_days (1 to 365). Add max_downloads to cap downloads.
curl -X POST -H "Authorization: Bearer $ENDORR_KEY" -H "Content-Type: application/json" \
-d '{"expires_in_days": 30}' "https://auth.endorr.com/v1/cloud/files/file_01JB8Q.../share"
# { "share": { "id": "shr_…", "url": "https://…/s/…", "expires_at": "…" } }Search
GET /v1/cloud/search?q=invoice finds files and folders whose name contains the text, newest first, with their paths.
Large files
For files over 100 MB (up to 50 GB), upload in three steps so the bytes go straight to storage:
POST /v1/cloud/uploadswith{ "path", "size_bytes", "content_type" }.PUTthe bytes toupload.urlwith the headers inupload.headers. No API key on this request.POSTthecomplete_urlfrom step 1. The file then appears in its folder.
START=$(curl -s -X POST -H "Authorization: Bearer $ENDORR_KEY" -H "Content-Type: application/json" \
-d "{\"path\": \"/Videos/launch.mp4\", \"size_bytes\": $(stat -f%z launch.mp4)}" "https://auth.endorr.com/v1/cloud/uploads")
curl -T launch.mp4 "$(echo "$START" | jq -r .upload.url)"
curl -X POST -H "Authorization: Bearer $ENDORR_KEY" "https://auth.endorr.com$(echo "$START" | jq -r .complete_url)"Large uploads support on_conflict=rename and fail. To replace a large file, delete the old one first.
Errors
Every error has the same shape, with a stable code to branch on, a message written for people, and a docs_url pointing here:
{
"error": {
"code": "forbidden",
"message": "This API key lacks the \"files.write\" permission. Add it in Endorr Studio under Settings, API keys.",
"request_id": "6f1c…",
"docs_url": "https://endorr.com/developers#errors"
}
}| Status | code | What to do |
|---|---|---|
| 401 | unauthorized | The key is missing, wrong, expired or revoked. |
| 402 | storage_quota_exceeded | The workspace is out of storage. details says how much is used and free. |
| 403 | forbidden | The key lacks a permission, or you cannot edit that folder. |
| 404 | not_found | Nothing at that path or id that this key can see. |
| 409 | already_exists | A file with that name is there and you passed on_conflict=fail. |
| 413 | payload_too_large | Over 100 MB: use a large upload. |
| 422 | validation_failed | A parameter is missing or wrong; details says which. |
| 429 | rate_limited | Too many requests. Wait a few seconds and retry. |
Mention the request_id when you contact support.
Limits
- 600 requests per minute per key (an MCP call counts as one).
- 100 MB per one-request upload; 50 GB per large upload.
- 25 active keys per person.
- Storage counts against your plan, the same as files you add in Studio.
- End-to-end encrypted vault folders from the desktop app cannot be read or written through the API.
Endpoint reference
All paths are relative to https://auth.endorr.com. The same list, with request and response schemas, is in the OpenAPI document.
| Endpoint | Does | Needs |
|---|---|---|
GET /v1/cloud | Discovery: docs, OpenAPI and MCP links | nothing |
GET /v1/cloud/openapi.json | OpenAPI 3.1 document | nothing |
POST /v1/cloud/mcp | MCP server for AI agents | per tool |
GET /v1/cloud/me | Who the key acts for, its permissions, storage | files.read |
GET /v1/cloud/folders?path= | List a folder by path | files.read |
GET /v1/cloud/folders/{id} | List a folder by id (root = /) | files.read |
POST /v1/cloud/folders | Create a folder and missing parents | files.write |
PATCH /v1/cloud/folders/{id} | Rename or move a folder | files.write |
DELETE /v1/cloud/folders/{id} | Move a folder to the trash | files.delete |
POST /v1/cloud/folders/{id}/share | Share link to a folder | shares.create |
PUT /v1/cloud/files?path= | Upload in one request | files.write |
GET /v1/cloud/files?path= | File details by path | files.read |
GET /v1/cloud/files/{id} | File details by id | files.read |
GET /v1/cloud/files/download?path= | Download by path (302) | files.read |
GET /v1/cloud/files/{id}/download | Download by id (302) | files.read |
PATCH /v1/cloud/files/{id} | Rename or move a file | files.write |
DELETE /v1/cloud/files/{id} | Move a file to the trash | files.delete |
POST /v1/cloud/files/{id}/share | Share link to a file | shares.create |
POST /v1/cloud/uploads | Start a large upload | files.write |
POST /v1/cloud/uploads/{id}/complete | Finish a large upload | files.write |
GET /v1/cloud/search?q= | Search by name | files.read |
Questions or something missing? Ask us through the Help center.
