Drive
Upload a file into a workspace's Drive and read back signed URLs for it.
Workspace-wide file storage, brokered so your application never holds the bytes.
Three scopes, deliberately split so a key gets only what it needs: drive:write uploads, drive:read returns a signed URL for the original, drive:preview returns one for a thumbnail only.
const file = await connect.drive.upload({ workspaceId, file, parentId });
// Later - URLs are short-lived, so fetch one when you render, not at upload.
const url = await connect.drive.getFileUrl(file.id, { workspaceId });Signed URLs expire. Store the fileId, never the URL. Caching a URL is how an <img> starts 403ing a few minutes after the page was built.
Drive is the workspace's storage, not your application's - the customer sees these files in their own Drive, and they are covered by the deletion policy you declared. A key scoped to drive:preview alone can render thumbnails without ever being able to fetch an original.
Endpoints
POST /api/v1/application/drive/files
Upload a file into a workspace's Drive
Scope drive:write · Rate limit 20 requests / min per key
Uploads a file into the target workspace's Drive and hands back a signed URL for it in the same response - no separate call needed right after upload.
Implementation
1. Prerequisite - an API key scoped to drive:write.
2. Send a multipart/form-data request - file is the binary, workspaceId is required, parentId is an optional Drive folder id (omit, or send empty, to upload into the workspace's Drive root):
curl -X POST https://connect.cosmoops.com/api/v1/application/drive/files \
-H "Authorization: Bearer YOUR_API_KEY_PLAINTEXT" \
-F "workspaceId=WORKSPACE_ID" \
-F "file=@invoice.pdf"3. Read url in the response - a short-lived signed URL for the original file. Store id if you'll need the file again later; re-fetch a fresh URL anytime with GET /drive/files/{id}/url below rather than caching this one past its expiry.
Errors
validation_error (400 - missing file/workspaceId, or the file exceeds the per-file size cap), forbidden (403 - key missing drive:write), not_found (404 - unknown workspaceId), quota_exceeded (409 - the workspace's Drive storage is full), rate_limited (429).
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
workspaceId | string | yes | |
file | string | yes | Binary file content |
parentId | uuid | no | Destination Drive folder id - omitted uploads into the workspace's Drive root |
Responses
| Status | Meaning |
|---|---|
201 | File uploaded |
400 | validation_error - missing file/workspaceId, or file too large |
403 | forbidden - key missing drive:write |
404 | not_found - unknown workspaceId |
409 | quota_exceeded - workspace's Drive storage is full |
429 | rate_limited |
Response body
| Field | Type | Required | Notes |
|---|---|---|---|
id | uuid | yes | |
fileName | string | yes | |
mimeType | string | yes | |
size | number | yes | Bytes |
url | uri | yes |
GET /api/v1/application/drive/files/{fileId}/url
Get a signed URL for a Drive file's original bytes
Scope drive:read · Rate limit 60 requests / min per key
Re-fetches a signed URL for a file already uploaded (via POST /drive/files above, or already present in the workspace's Drive) - use this once the URL you were handed earlier has expired.
Implementation
1. Prerequisite - an API key scoped to drive:read.
2. Send the request:
curl "https://connect.cosmoops.com/api/v1/application/drive/files/FILE_ID/url?workspaceId=WORKSPACE_ID" \
-H "Authorization: Bearer YOUR_API_KEY_PLAINTEXT"3. Read url - short-lived, don't persist it; call this again next time you need it.
Errors
validation_error (400 - missing workspaceId), forbidden (403 - key missing drive:read), not_found (404 - unknown fileId for this workspace, or it's been deleted), rate_limited (429).
Parameters
| Name | In | Required | Notes |
|---|---|---|---|
fileId | path | yes | |
workspaceId | query | yes |
Responses
| Status | Meaning |
|---|---|
200 | Signed URL |
400 | validation_error - missing workspaceId |
403 | forbidden - key missing drive:read |
404 | not_found - unknown fileId for this workspace |
429 | rate_limited |
Response body
| Field | Type | Required | Notes |
|---|---|---|---|
url | uri | yes |
GET /api/v1/application/drive/usage
Get how much of a workspace's Drive storage is used
Scope drive:read · Rate limit 60 requests / min per key
Returns the bytes the workspace's Drive holds and its limit - the same limit an upload is refused against with quota_exceeded, so a meter built on this agrees with the refusal. The limit is the workspace's baseline plus the storage every active plan includes; limitBytes: null means unlimited.
Implementation
1. Prerequisite - an API key scoped to drive:read, and the workspace must hold an active subscription to your application.
2. Send the request:
curl "https://connect.cosmoops.com/api/v1/application/drive/usage?workspaceId=WORKSPACE_ID" \
-H "Authorization: Bearer YOUR_API_KEY_PLAINTEXT"Errors
validation_error (400 - missing workspaceId), forbidden (403 - key missing drive:read, or the workspace does not subscribe to your application), not_found (404 - unknown workspaceId), rate_limited (429).
Parameters
| Name | In | Required | Notes |
|---|---|---|---|
workspaceId | query | yes |
Responses
| Status | Meaning |
|---|---|
200 | Storage usage |
400 | validation_error - missing workspaceId |
403 | forbidden - key missing drive:read, or no subscription |
404 | not_found - unknown workspaceId |
429 | rate_limited |
Response body
| Field | Type | Required | Notes |
|---|---|---|---|
usedBytes | number | yes | Bytes |
limitBytes | any | yes | Bytes; null means unlimited |
GET /api/v1/application/drive/files
List the files your application uploaded to a workspace's Drive
Scope drive:read · Rate limit 60 requests / min per key
The files your application uploaded through POST /drive/files, newest first. A workspace's Drive also holds its members' own files and other applications' files; none of those are listed here, and none can be read or deleted through your key.
limit defaults to 50 and is capped at 100. There is no cursor: truncated: true says more exist. An application that keeps more than a hundred files in one workspace should keep its own index of the ids POST /drive/files returned.
Errors
validation_error (400 - missing workspaceId, or a limit that is not a positive integer), forbidden (403 - key missing drive:read), rate_limited (429).
Parameters
| Name | In | Required | Notes |
|---|---|---|---|
workspaceId | query | yes | |
limit | query | no | 1-100, default 50. |
Responses
| Status | Meaning |
|---|---|
200 | Your application's files |
400 | validation_error |
403 | forbidden - key missing drive:read |
429 | rate_limited |
Response body
| Field | Type | Required | Notes |
|---|---|---|---|
files | array | yes | |
truncated | boolean | yes | More files exist than limit returned; there is no cursor |
DELETE /api/v1/application/drive/files/{fileId}
Delete a file your application uploaded
Scope drive:write · Rate limit 20 requests / min per key
Removes the file's bytes and thumbnails and gives the space back to the workspace's Drive quota. Only a file your application uploaded can be deleted: a member's file, another application's file, an unknown id and an already-deleted file all answer the same not_found, so a retry after a timeout can treat 404 as done.
Errors
validation_error (400 - missing workspaceId), forbidden (403 - key missing drive:write), not_found (404), rate_limited (429).
Parameters
| Name | In | Required | Notes |
|---|---|---|---|
fileId | path | yes | |
workspaceId | query | yes |
Responses
| Status | Meaning |
|---|---|
204 | Deleted |
400 | validation_error - missing workspaceId |
403 | forbidden - key missing drive:write |
404 | not_found - not a file your application uploaded |
429 | rate_limited |
GET /api/v1/application/drive/files/{fileId}/preview-url
Get a signed URL for a Drive file's thumbnail
Scope drive:preview · Rate limit 60 requests / min per key
Same as GET /drive/files/{fileId}/url above, but for the file's thumbnail instead of its original bytes - useful for rendering a preview without downloading a large original.
Implementation
1. Prerequisite - an API key scoped to drive:preview.
2. Send the request - size defaults to medium:
curl "https://connect.cosmoops.com/api/v1/application/drive/files/FILE_ID/preview-url?workspaceId=WORKSPACE_ID&size=medium" \
-H "Authorization: Bearer YOUR_API_KEY_PLAINTEXT"3. Read url - short-lived, same as the original-file endpoint.
Errors
validation_error (400 - missing workspaceId, or an invalid size), forbidden (403 - key missing drive:preview), not_found (404 - unknown fileId, or it has no thumbnail), rate_limited (429).
Parameters
| Name | In | Required | Notes |
|---|---|---|---|
fileId | path | yes | |
workspaceId | query | yes | |
size | query | no | Defaults to "medium" |
Responses
| Status | Meaning |
|---|---|
200 | Signed thumbnail URL |
400 | validation_error - missing workspaceId, or invalid size |
403 | forbidden - key missing drive:preview |
404 | not_found - unknown fileId, or it has no thumbnail |
429 | rate_limited |
Response body
| Field | Type | Required | Notes |
|---|---|---|---|
url | uri | yes |