Drive Endpoints
The Preview Drive API works with Google Drive, Microsoft 365, and Dropbox
sources that a team manager has connected to a dashboard project. Every request
needs a team API key, the relevant drive scope, and a current project grant. Read routes use api:drive:read; mutations use api:drive:write. Routes that
target one connection or item also require an active selected source and the
exact capability advertised by that connection; the connection collection
uses the project-scoped connected-data collection decision instead of a
synthetic list capability.
The drive family is controlled by the team's plan and may be disabled until it is enabled for that plan. Write access requires a manager to reauthorize the connection for changes. Write and read scopes are independent; a write-scoped token may perform the minimum target lookup needed for its mutation without receiving general read access.
Public resources
A drive connection exposes its numeric Chab connection_id, customer alias,
provider label, selected source_type, safe state, and sorted public
capabilities. It never exposes account, tenant, site, provider-drive, or
credential identifiers.
A DriveItem has an opaque dri_... item ID that is valid only inside its
project connection. It includes the connection ID, kind, customer-visible
name, nullable parent ID and root-relative path, media metadata, opaque item
and permission revisions, up to 20 owners, and current public actions. Provider
IDs and version tags are never public.
List connections
GET /v1/drive/connections lists active drive connections for one project in
case-insensitive alias order. A traversal uses a stable 15-minute snapshot, so
renames and new connections appear on the next fresh traversal.
curl "https://www.chab.ai/v1/drive/connections?project_id=7&limit=50" \
-H "Authorization: Bearer CHAB_API_KEY"
The response meta contains request_id, next_cursor, has_more, and
limit. Pass an opaque cursor unchanged to fetch the next page.
List items
GET /v1/drive/items lists the selected root, or one folder when parent_id
is supplied, in provider continuation order. limit defaults to 50 and accepts
1–100.
curl "https://www.chab.ai/v1/drive/items?project_id=7&connection_id=12&limit=50" \
-H "Authorization: Bearer CHAB_API_KEY"
Item-list and search metadata adds coverage and structured warnings. Chab
does not promise folders-first, alphabetical, or modified-time ordering.
Search
POST /v1/drive/search performs a case-insensitive literal search against item
names only. query is 1–500 Unicode characters. Provider query syntax and
content, owner, MIME, date, or path filters are not accepted.
curl -X POST https://www.chab.ai/v1/drive/search \
-H "Authorization: Bearer CHAB_API_KEY" \
-H "Content-Type: application/json" \
-d '{"project_id":7,"connection_id":12,"query":"quarterly report","limit":20}'
Search is a direct read and does not use idempotency.
Read item
GET /v1/drive/items/{item_id} refreshes protected item metadata from the
provider and returns one DriveItem.
curl "https://www.chab.ai/v1/drive/items/dri_01JZ7H0A1B2C3D4E5F6G7H8J9K?project_id=7&connection_id=12" \
-H "Authorization: Bearer CHAB_API_KEY"
An ID from another connection, an item outside the selected source, a shortcut
to external content, a trashed item, and an externally deleted item all return
not_found.
Download item
GET /v1/drive/items/{item_id}/download downloads a complete ordinary file.
Ranges are not supported. Chab reauthorizes before delivery and returns either
a safe short-lived redirect or a metered whole-object stream.
curl -L "https://www.chab.ai/v1/drive/items/dri_01JZ7H0A1B2C3D4E5F6G7H8J9K/download?project_id=7&connection_id=12" \
-H "Authorization: Bearer CHAB_API_KEY" \
-o downloaded-file
Chab-streamed downloads are limited to 100 MiB and may incur egress credits
even though the drive operation itself is non-billable. Redirected provider
bytes do not pass through Chab. Do not send Range.
Export item
POST /v1/drive/items/{item_id}/export exports a provider-native document to
pdf, text, html, or markdown when that exact format appears in the
item's available_exports. The asynchronous result contains one protected
artifact with role drive_export.
curl -X POST https://www.chab.ai/v1/drive/items/dri_01JZ7H0A1B2C3D4E5F6G7H8J9K/export \
-H "Authorization: Bearer CHAB_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: export-report-001" \
-d '{"project_id":7,"connection_id":12,"output_format":"pdf"}'
Exports are limited to 100 MiB. Poll the returned operation, then download its artifact through the normal protected artifact endpoint.
Mutations
The following six endpoints return an asynchronous operation with HTTP 202.
They require api:drive:write, the corresponding connection capability, and
an Idempotency-Key for a live request. Poll the returned status_url and
result_url. The operations are non-billable: they reserve no credits and do
not consume a token credit budget. Paid-plan access, operation rate limits,
concurrency limits, current project access, and connection health still apply.
There is no drive operation quota window.
Use the current item available_actions and connection capabilities to
discover support. A connector or item may support only a subset. Dropbox supports file replacement and file trash with revisions; it does not offer move or folder trash through this API. Unsupported
actions return drive_item_action_unavailable or
connection_capability_unavailable; Chab does not substitute another action.
All bodies are closed JSON objects. Upload and replacement accept one
source: {"type":"file_id"|"artifact_id","id":"..."}. Files must have
completed scanning and be available to this token in the target project.
Reusable artifacts must be drive exports from the same project and token.
Other downloadable artifacts are not automatically valid drive inputs. Raw
multipart bodies, URLs, paths, and base64 content are not accepted here; upload
bytes through the Files API first. Inputs may not exceed 100 MiB,
and a lower source or connector limit also applies.
Accepted operations hold their source until they reach a terminal state.
Expiry or requested deletion prevents new acceptance but waits for existing
source holders before deleting bytes. Revoked project/token access and unsafe
scan states still prevent further transfer. Source errors keep their shared
codes: file_expired/artifact_expired (410), source_scan_pending (409),
and source_scan_failed, source_quarantined, or source_too_large (422).
Names are trimmed, 1–255 characters, and cannot contain controls, /, \\,
or be . or ... Microsoft connections also reject reserved system names,
trailing dots/spaces, and "*:<>?|; Dropbox names are limited to 255 UTF-8
bytes. For creation, conflict_mode must be fail or create_copy. The latter
tries the original name, then (copy), then (copy 2) through (copy 100)
before the extension. Exhaustion returns resource_state_conflict. Replacement
never uses a name collision as permission to overwrite a different item.
Add "dry_run":true to any mutation to validate without performing the change.
It returns HTTP 200 with meta.dry_run=true,
meta.live_requires_idempotency=true, and data.preview. No idempotency key is
required, and supplying one does not reserve or replay it. Dry runs can read
current metadata but do not read source bytes, reserve credits, consume a rate
bucket/concurrency slot, create an operation or source hold, or modify the
drive. New IDs, revisions, and mutation timestamps in the preview are null.
Repeat validation at live execution: a preview does not lock the remote item.
Upload item
POST /v1/drive/items creates a file under parent_id, or at the selected
root when it is null. It requires drive.items.upload.
curl -X POST https://www.chab.ai/v1/drive/items \
-H "Authorization: Bearer CHAB_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: upload-report-001" \
-d '{"project_id":7,"connection_id":12,"parent_id":null,"source":{"type":"file_id","id":"fil_01JZ7H0A1B2C3D4E5F6G7H8J9K"},"name":"report.pdf","conflict_mode":"fail"}'
Replace item
PATCH /v1/drive/items/{item_id} replaces the exact file's bytes. It requires
drive.items.update and the latest opaque expected_revision. A stale
revision returns resource_revision_conflict. The Chab item ID stays stable;
there is no public version-history or replacement-mode option.
curl -X PATCH https://www.chab.ai/v1/drive/items/dri_01JZ7H0A1B2C3D4E5F6G7H8J9K \
-H "Authorization: Bearer CHAB_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: replace-report-001" \
-d '{"project_id":7,"connection_id":12,"source":{"type":"artifact_id","id":"art_01JZ7H0A1B2C3D4E5F6G7H8J9K"},"expected_revision":"opaque_revision"}'
Create folder
POST /v1/drive/folders requires drive.folders.create. Null parent_id
selects the connection root. Creation conflict modes match file uploads.
curl -X POST https://www.chab.ai/v1/drive/folders \
-H "Authorization: Bearer CHAB_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: create-reports-001" \
-d '{"project_id":7,"connection_id":12,"parent_id":null,"name":"Reports","conflict_mode":"fail"}'
Move item
POST /v1/drive/items/{item_id}/move requires drive.items.move, the latest
expected_revision, and a target_parent_id in the same connection. Optional
name renames the item during the move. The item ID stays stable. Destination
collisions fail; moving into itself, a descendant, another root, or a shortcut
is rejected. There is no copy-on-conflict mode.
curl -X POST https://www.chab.ai/v1/drive/items/dri_01JZ7H0A1B2C3D4E5F6G7H8J9K/move \
-H "Authorization: Bearer CHAB_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: move-report-001" \
-d '{"project_id":7,"connection_id":12,"target_parent_id":"dri_01JZ7H0A1B2C3D4E5F6G7H8J9M","expected_revision":"opaque_revision"}'
Trash item
POST /v1/drive/items/{item_id}/trash requires drive.items.trash and the
current expected_revision. It uses the connected drive's trash/recycle bin.
It never falls back to permanent deletion. An already-trashed or externally
deleted item returns not_found; Chab has no restore endpoint.
curl -X POST https://www.chab.ai/v1/drive/items/dri_01JZ7H0A1B2C3D4E5F6G7H8J9K/trash \
-H "Authorization: Bearer CHAB_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: trash-report-001" \
-d '{"project_id":7,"connection_id":12,"expected_revision":"opaque_revision"}'
Permissions
POST /v1/drive/items/{item_id}/permissions requires
drive.permissions.update and the latest expected_permission_revision.
action is grant, update, or revoke; principal contains exactly type
(user or group) and email. role is viewer, commenter, or editor
for grant/update and must be omitted for revoke. Support depends on the
connection and item. The current Microsoft connector supports update/revoke of
existing direct permissions with a current item revision. New grants are
unavailable. Google Drive and Dropbox permission mutations are unavailable;
unsupported actions return drive_item_action_unavailable before a change.
Grant requires no existing direct match; update/revoke require exactly one
direct match of normalized type and email. Missing, existing, or ambiguous
matches return resource_state_conflict. Public links, domain sharing,
ownership transfer, inherited permission changes, and notifications are not
supported. A connector unable to perform the exact request without those
effects rejects it.
curl -X POST https://www.chab.ai/v1/drive/items/dri_01JZ7H0A1B2C3D4E5F6G7H8J9K/permissions \
-H "Authorization: Bearer CHAB_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: update-report-permission-001" \
-d '{"project_id":7,"connection_id":12,"action":"update","principal":{"type":"user","email":"[email protected]"},"role":"viewer","expected_permission_revision":"opaque_permission_revision"}'
Mutation results and recovery
Successful results contain action, changed, item_id, nullable item,
previous_revision, current_revision, trashed, and nullable permission.
Permission outcomes contain the action, principal type/address, role, and new
opaque permission revision. Item metadata uses the same DriveItem schema as
reads. Provider IDs and session handles are never returned.
Use a fresh idempotency key for each intended change. Repeating a key, method, target, and identical body replays the accepted operation. A changed body in that slot conflicts; a different target has a separate slot. Retrying an ambiguous remote effect does not blindly repeat it. The operation waits for reconciliation and may time out if its outcome cannot be established. Removing access prevents subsequent protected effects; cancellation does not undo a change already applied. Each confirmed effect creates one content-free audit event; dry runs and replays do not duplicate it.
Errors
Drive endpoints use the shared error envelope. Important drive codes include:
| Code | Meaning |
|---|---|
drive_item_action_unavailable |
The current provider item does not support the requested action. |
drive_export_format_unavailable |
The format is not currently advertised for this item. |
drive_item_too_large |
A Chab-served download exceeds 100 MiB. |
drive_export_too_large |
Exported bytes exceed 100 MiB. |
connection_access_removed |
Current project, connection, capability, or source access was removed. |
Direct reads have a dedicated team/key/family/profile rate bucket and return RFC rate headers. Export uses operation rate and concurrency controls. See Errors, Rate Limits, and Pagination, Operations, and Operation Lifecycle.