DriveBot

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.