This page is generated from /llms.txt, the same guide agents read. Point your agent at that URL and it can do everything described here.
DriveBot API guide
DriveBot is file storage for AI agents and the people they work with. This
page is the complete reference. Everything in the web app can also be done
over HTTPS + JSON with curl.
Base URL: https://drivebot.in/api/v1
Auth header: Authorization: Bearer <token> (or X-API-Key: <token>)
Two kinds of credential:
| Token | Looks like | Who | Reach |
|---|---|---|---|
| API key | adk_\x{2026} |
an agent | the workspaces it was granted (see Agent keys) |
| Session | ads_\x{2026} |
a human (or an agent acting fully as one) | everything that person can do |
Prefer API keys for day-to-day work. Use a session only for account and organization administration.
Every response explains itself. Successful calls return
{"ok": true, "message": "\x{2026}", \x{2026}data} where message says in plain words
what happened and what to do next (e.g. that an invite was created and
when it activates). Failures return {"ok": false, "error": code, "message": why, "hint": what to do, "docs": url} with the matching HTTP
status. Read message before deciding your next step.
1. Opening an account (phone + one-time code)
Sign-in is phone based and an agent can drive it. Ask your human for their
mobile number in E.164 form (e.g. +919876543210).
# 1. Send a code by SMS
curl -s -X POST https://drivebot.in/api/v1/auth/otp/send \
-H 'content-type: application/json' -d '{"phone":"+919876543210"}'
# 2. Ask the human: "What 6-digit code did you just receive?"
# 3. Verify. Optionally mint yourself an API key in the same call.
curl -s -X POST https://drivebot.in/api/v1/auth/otp/verify \
-H 'content-type: application/json' \
-d '{"phone":"+919876543210","code":"123456","name":"Priya",
"agent":{"name":"claude","type":"claude","permission":"write"}}'
Response:
{"token":"ads_\x{2026}","new_user":true,
"user":{"id":1,"phone":"+919876543210","name":"Priya"},
"workspace":{"id":1,"name":"My Drive"},
"api_base":"https://drivebot.in/api/v1/workspaces/1",
"api_key":"adk_\x{2026}","agent":{"name":"claude","grants":[\x{2026}]}}
The response also lists every workspaces entry the account can reach.
By default the key is minted for the user's first workspace; pass
"agent": {\x{2026}, "workspace_id": 7} (or "workspace": "Acme specs") to
target another, or "all": true to get one key that reaches every
workspace in that workspace's organization.
First-time numbers get an account, a personal organization, and a
workspace called My Drive. Returning numbers get the same account back.
Any pending invites for that number activate automatically. Store
api_key durably; it is shown once. Codes expire in 10 minutes, work once,
and lock after 5 wrong tries.
GET /me tells you who you are. With a session it lists your orgs; with
an API key it lists the workspaces the key can reach and the permission
on each. PATCH /me {"name": "Priya S"} changes the display name
(session only). POST /auth/logout ends a session.
2. Organizations, members, teams and roles
Workspaces live in organizations. Everyone has a personal org; companies create shared orgs and invite people by phone.
Org roles \x{2014} owner (everything, including deleting the org and
managing other owners) � admin (members, teams, workspaces, keys, audit;
automatically an admin of every workspace) � member (only workspaces
they are granted) � billing (settings and audit log only).
Workspace roles \x{2014} admin (members, keys, rename) � editor
(read/write/share) � viewer (read). A person's effective role is the
highest of their direct membership, any team grant, and their org role.
Session token required for all of these (ORG = org id):
| Call | Body / notes |
|---|---|
GET /orgs |
Your orgs with your role in each; personal: true marks the personal one |
POST /orgs |
{"name": "Acme Inc"} \x{2192} you become owner |
GET /orgs/ORG |
Org, your role and your permissions list |
PATCH /orgs/ORG |
{"name"} (needs org.settings) |
DELETE /orgs/ORG |
owners only; personal orgs cannot be deleted |
GET /orgs/ORG/members |
members + pending invites |
POST /orgs/ORG/members |
{"phone": "+91\x{2026}", "role": "member"}. Known number \x{2192} added now (status: added); unknown \x{2192} invite (status: invited) that activates when they first sign in |
PATCH /orgs/ORG/members/USER_ID |
{"role"}; only owners can create or change owners; the last owner can't be demoted |
DELETE /orgs/ORG/members/USER_ID |
removes them from the org and all its workspaces and teams |
DELETE /orgs/ORG/invites/ID |
cancel a pending invite |
GET /orgs/ORG/teams � POST /orgs/ORG/teams |
{"name", "description"?} |
GET /orgs/ORG/teams/ID |
team + members |
PATCH / DELETE /orgs/ORG/teams/ID |
rename / delete |
POST /orgs/ORG/teams/ID/members |
{"phone"} \x{2014} must already be an org member, or an invite is created |
DELETE /orgs/ORG/teams/ID/members/USER_ID |
|
GET /orgs/ORG/workspaces |
workspaces you can reach in the org (admins see all) |
POST /orgs/ORG/workspaces |
{"name"} (needs org.workspaces); you become its admin |
GET /orgs/ORG/audit |
see Audit log |
Typical onboarding of a company, as an agent with a session token:
S="Authorization: Bearer $SESSION"; J='content-type: application/json'
ORG=$(curl -s -X POST https://drivebot.in/api/v1/orgs -H "$S" -H "$J" -d '{"name":"Acme Inc"}' | jq .id)
curl -s -X POST https://drivebot.in/api/v1/orgs/$ORG/members -H "$S" -H "$J" -d '{"phone":"+14155550123","role":"admin"}'
TEAM=$(curl -s -X POST https://drivebot.in/api/v1/orgs/$ORG/teams -H "$S" -H "$J" -d '{"name":"Engineering"}' | jq .id)
curl -s -X POST https://drivebot.in/api/v1/orgs/$ORG/teams/$TEAM/members -H "$S" -H "$J" -d '{"phone":"+14155550123"}'
WS=$(curl -s -X POST https://drivebot.in/api/v1/orgs/$ORG/workspaces -H "$S" -H "$J" -d '{"name":"Product specs"}' | jq .id)
curl -s -X POST https://drivebot.in/api/v1/workspaces/$WS/teams -H "$S" -H "$J" -d '{"team_id":'$TEAM',"role":"editor"}'
3. Agent keys (adk_\x{2026})
A key belongs to an org and carries grants: which workspaces it may
reach, with read or write, and a root_path folder it is confined to.
"workspace_id": "*" (or null) means every workspace in the org,
including ones created later. Keys can also carry policies.
| Call | Body / notes |
|---|---|
GET /orgs/ORG/keys |
all active keys with grants and policies (needs org.keys) |
POST /orgs/ORG/keys |
see example; returns key once |
PATCH /orgs/ORG/keys/ID |
any of name, grants (replaces all), expires_in_days, expires_at, ip_allowlist, rate_limit_per_min |
DELETE /orgs/ORG/keys/ID |
revoke immediately |
GET/POST /workspaces/WS/keys |
shortcut for single-workspace keys (needs ws.keys); {"name","type"?,"permission","root_path"?,"expires_in_days"?} |
DELETE /workspaces/WS/keys/ID |
only if the key reaches nothing else |
curl -s -X POST https://drivebot.in/api/v1/orgs/$ORG/keys -H "$S" -H "$J" -d '{
"name": "research-bot", "agent_type": "claude",
"grants": [
{"workspace_id": 12, "permission": "write", "root_path": "/reports"},
{"workspace_id": "*", "permission": "read"}
],
"expires_in_days": 90,
"ip_allowlist": ["203.0.113.0/24"],
"rate_limit_per_min": 600
}'
Policy failures: 401 key_expired, 403 ip_not_allowed, 429 rate_limited (with Retry-After). Every action a key takes is recorded
as agent:<name> in file history and the audit log.
4. Workspaces and files
All file calls live under /workspaces/WS. GET /workspaces lists the
ones you can reach. GET /workspaces/WS shows your effective role,
permissions and root_path; PATCH /workspaces/WS {"name"} renames.
Paths are absolute and /-separated: /, /reports,
/reports/q3.md. No . or ... Parent folders are created automatically
on write, move and copy.
Reading
| Call | Purpose |
|---|---|
GET /ls?path=/dir[&recursive=true] |
List a folder (recursive = whole subtree) |
GET /stat?path=/f |
Metadata: kind, size, version, sha256, updated_by |
GET /read?path=/f[&offset=0&limit=200000][&version=N] |
Extracted text of text, code, Markdown, JSON, CSV, PDF and DOCX files, paginated by characters. Follow next_offset while truncated is true |
GET /download?path=/f[&version=N] |
Raw bytes (images, binaries). Supports If-None-Match with the returned ETag |
GET /versions?path=/f |
Version history, newest first |
GET /search?q=\x{2026}[&mode=hybrid|text|semantic][&path=/dir][&limit=20] |
Search names and contents; best snippet per file |
GET /events[?since=EVENT_ID&limit=100] |
Activity in this workspace. Poll with since to watch for changes |
Writing (needs write)
| Call | Body |
|---|---|
POST /write |
JSON {"path", "content", "message"?, "if_version"?, "encoding"?: "utf8"|"base64", "content_type"?} |
PUT /upload?path=/f[&message=..][&if_version=N] |
Raw bytes as the request body (any size/type) |
POST /upload |
multipart: file + path, or files[] + dir |
POST /mkdir |
{"path"} |
POST /move |
{"from", "to"} (also renames) |
POST /copy |
{"from", "to"} |
POST /delete |
{"path"} \x{2192} trash |
POST /versions/restore |
{"path", "version"} \x{2192} new version with the old content |
Every write creates a new version and records message (like a commit
message). Say what you changed and why. Writing identical content returns
"status": "unchanged" and creates no version.
Avoid clobbering others: read the file, note its version, then write
with "if_version": <that version>. If it changed in between you get
409 conflict; re-read and merge. "if_version": 0 creates only if the
file doesn't exist yet.
Trash
GET /trash � POST /trash/ID/restore � DELETE /trash/ID (purge
forever). Restored items get a (2) suffix if the name is taken.
Members and teams of a workspace (needs ws.members)
| Call | Body |
|---|---|
GET /members |
members, teams (team grants) and, for admins, org_teams available to grant |
POST /members |
{"phone", "role": "admin"|"editor"|"viewer"} \x{2014} unknown numbers get an invite |
DELETE /members/USER_ID |
|
DELETE /invites/ID |
cancel a pending invite listed by GET /members |
POST /teams |
{"team_id", "role"} grant a whole team |
DELETE /teams/TEAM_ID |
Share links (needs write)
POST /shares {"path", "permission": "view"|"edit", "expires_in_hours"?}
returns a public url (for people) and api_url (for agents, no key
needed). GET /shares lists, DELETE /shares/ID revokes. Under
https://drivebot.in/api/v1/s/TOKEN the calls /ls, /stat, /read, /download
work with paths relative to the shared item (plus /write, /upload,
/mkdir for edit shares).
5. Audit log
GET /orgs/ORG/audit (needs org.audit; billing and above) returns
every administrative action and file event across the org, newest first.
Filters: actor=agent:codex, action=file. (prefix), workspace_id=,
since=EVENT_ID, limit= (max 5000). Add format=csv for a CSV export.
Action names: file.create/update, folder.create, node.move/trash/ restore/purge, share.create, member.add/invite/remove/role,
invite.accept/revoke, team.create/update/delete, team.member.add/ remove, team.grant/revoke, key.create/update/revoke,
workspace.create/rename, org.create/update.
6. MCP server (for Muse, Claude, Codex and other MCP clients)
DriveBot is also a Model Context Protocol server at https://drivebot.in/mcp
(Streamable HTTP transport, JSON responses). Authenticate with the same
bearer token as the REST API: Authorization: Bearer <DriveBot API key>.
Tools: list_workspaces, list_files, read_file, search,
write_file, create_folder, move, delete, file_versions,
create_share_link, recent_activity. Call list_workspaces first;
every tool result begins with a plain-language message.
Example client config (Claude Code / Codex style):
{"mcpServers": {"drivebot": {"type": "http", "url": "https://drivebot.in/mcp",
"headers": {"Authorization": "Bearer adk_\x{2026}"}}}}
7. Quick examples
H="Authorization: Bearer $DRIVEBOT_KEY"
API=https://drivebot.in/api/v1/workspaces/$WS
curl -s "$API/ls?path=/" -H "$H"
curl -s "$API/read?path=/specs/api.md" -H "$H"
curl -s "$API/search?q=refund+policy" -H "$H"
curl -s -X POST "$API/write" -H "$H" -H 'content-type: application/json' \
-d '{"path":"/notes/summary.md","content":"# Summary\n...","message":"Summarised Q3 docs"}'
curl -s -X PUT "$API/upload?path=/data/report.pdf" -H "$H" --data-binary @report.pdf
curl -s "$API/download?path=/data/report.pdf" -H "$H" -o report.pdf
8. Getting help
Humans: https://drivebot.in/support (FAQ + contact form) or support@drivebot.in.
Agents can file a support request directly, no key needed:
POST /support {"name"?, "contact": "email or phone", "subject", "message"}
\x{2192} returns a ticket id. Include what you were trying to do and the exact
error message you received.
9. Errors
JSON {"error": code, "message": text}. Common codes: 400 bad
path/params (invalid_path, invalid_phone, no_grants, last_owner\x{2026}),
401 bad/expired token or otp_rejected, 403 forbidden (role, read-only
key, outside root_path, ip_not_allowed), 404 not_found, 409
exists/conflict, 413 too large, 415 not_text (use /download),
422 validation details, 429 rate_limited.