Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Drive

Preview Base URL: https://tj7hnhcvwir4n6rl5itdqut3mq0wdpke.lambda-url.us-east-1.on.aws

Overview

Drive keeps a person’s files and folders. The person works with them in the Drive app at https://drive.stackwell.tech, signing in with ChirpAuth. Apps reach them through Drive’s API, and only with a grant: a permission the person approves in Granite that names your app, the files it covers, and whether it may read, write, or both.

It is for developers of apps that keep a signed-in person’s files in that person’s own Drive rather than in their own database. The person can see everything your app writes, in the Drive app, next to their other files.

With a grant, an app can, within the files the grant covers:

  • create text files, list them, and read them;
  • update them, with a version check so two writers can’t overwrite each other;
  • list a file’s earlier versions and restore one;
  • move files to the trash and restore them.

An app cannot permanently delete a file (only the person can, in the Drive app), and cannot reach anything its grant doesn’t cover.

The person can export their Drive from the Drive app: one ZIP of every file outside the trash, in every app’s area, with each file’s earlier versions, their tables, the shared records they hold, the grants they gave apps, and their activity log, with a manifest.json listing them.

What preview means here: Drive runs in production, and Stackwell’s own apps store people’s files in it. Its API is not declared stable: routes and fields can change without notice. Drive is not open to new apps yet; each app is enabled by hand, and there is no self-serve sign-up.

These pages cover the file routes an app uses with a grant. The generated reference also lists routes that Stackwell’s own services use (tables, records, calendars and others); they are not documented for outside apps.

Not yet:

  • Sharing a file or folder with another person.
  • Search.
  • Writing files larger than 300,000 bytes from an app.
  • Self-serve access for new apps.

Quickstart

This walks through the path an app takes: check Drive is up, get the person’s approval, then write and read a file in their Drive.

1. Check that Drive is reachable

No credentials needed:

curl -fsS https://tj7hnhcvwir4n6rl5itdqut3mq0wdpke.lambda-url.us-east-1.on.aws/health
{"service":"drive","status":"ok"}

Every other route needs credentials:

curl -sS https://tj7hnhcvwir4n6rl5itdqut3mq0wdpke.lambda-url.us-east-1.on.aws/v1/files | grep -Fx '{"error":"unauthorized"}'

2. What your app needs

  • A ChirpAuth confidential client, so your server can get a ChirpAuth machine token.
  • Stackwell’s go-ahead for that client to request the drive.grant scope from ChirpAuth. Developers can’t turn this on themselves.
  • A way to file requests with Granite (an app credential or the same machine token); see Granite’s developer docs.

3. Ask the person for a folder

Pick a folder id for your app (any UUID), and file a Granite storage_grant request for it, naming your machine token’s sub as requester_chirp_sub:

{
  "request_type": "storage_grant",
  "title": "Acme notes",
  "summary": "Acme wants to keep your notes in a folder in your Drive.",
  "requested_action": "read and write files",
  "requested_resource": "storage:drive:drive:files:in:6f1c2a9e-4b7d-5e3a-9c8f-0d2e4a6b8c1f",
  "requested_scopes": ["drive.read", "drive.write"],
  "requester_chirp_sub": "<your machine token's sub>"
}

Send the person to Granite to approve it. Once they have, reading the request from Granite gives you its grant_id. The person may approve fewer scopes than you asked for.

4. Get the person’s Drive context

When the person signs in to your app with ChirpAuth, ask for the scope openid drive.grant. The token response then carries an access_token with audience drive. This is the user context: it tells Drive which person is using your app right now.

5. Write a file

Send your machine token, the grant id and the user context together.

curl https://tj7hnhcvwir4n6rl5itdqut3mq0wdpke.lambda-url.us-east-1.on.aws/v1/files \
  -H "Authorization: Bearer $MACHINE_TOKEN" \
  -H "x-granite-grant: $GRANT_ID" \
  -H "x-drive-user-context: $USER_CONTEXT" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "shopping.md",
    "content": "Apples\n",
    "mime_type": "text/markdown",
    "directory_id": "6f1c2a9e-4b7d-5e3a-9c8f-0d2e4a6b8c1f"
  }'

201 Created:

{
  "content": "Apples\n",
  "content_hash": "sha256:d14cbe5383b698ced713c1325292e005a85a051cb10d969893d60fde2ec32c53",
  "created_at": "2026-11-05T20:40:14.87202439Z",
  "directory_id": "6f1c2a9e-4b7d-5e3a-9c8f-0d2e4a6b8c1f",
  "id": "9327802d-b5d8-42e7-a6d5-61d31ffaf600",
  "mime_type": "text/markdown",
  "name": "shopping.md",
  "owner_uid": "usr_7Hq2mV9cXk4tR1pB",
  "size_bytes": 7,
  "tags": [],
  "updated_at": "2026-11-05T20:40:14.87202439Z",
  "version": 1
}

If the person has no folder with that id yet, Drive creates it on your app’s first write and records that it belongs to your app.

6. Read it back

curl https://tj7hnhcvwir4n6rl5itdqut3mq0wdpke.lambda-url.us-east-1.on.aws/v1/files/9327802d-b5d8-42e7-a6d5-61d31ffaf600 \
  -H "Authorization: Bearer $MACHINE_TOKEN" \
  -H "x-granite-grant: $GRANT_ID" \
  -H "x-drive-user-context: $USER_CONTEXT"

The response is the file as above. API examples covers listing, updating, versions and the trash.

Authentication

An app sends three things on every request: a ChirpAuth machine token as Authorization: Bearer, the id of a Granite grant the person approved as x-granite-grant, and the person’s user context (a ChirpAuth access token with audience drive and scope drive.grant) as x-drive-user-context. Drive checks all three, and asks Granite about the grant, on every request, so a grant the person revokes stops working at once. People use the Drive app; its sign-in is for that app only. Authentication has the checks and what each grant covers.

API reference

The full endpoint list is in the generated API reference. API examples walks through the routes an app uses, with requests and responses.

Conventions shared by the routes these pages cover:

  • Every path starts with /v1/.
  • Request and response bodies are JSON; send Content-Type: application/json. Unknown fields in a file body are refused.
  • Times are RFC 3339 in UTC. Ids are UUIDs.
  • Every change to a file increases its version by one. Updates must name the version they expect.
  • Lists are not paged.
  • There are no idempotency keys. Two creates with the same name in the same folder can’t both succeed: the second gets 409.

Errors and limits

Errors are JSON, {"error": "<message>"}, except parsing errors (bad path, bad JSON, unknown field, body too large), which are plain text and come before authentication. Each person has a file count, folder count and storage limit, shared by every app they use, and file content is capped at 300,000 bytes. Errors and limits lists the status codes and the numbers.

Data and privacy

Drive keeps a person’s files, their earlier versions, and a record of who changed what, until the person deletes them. Your app sees only what its grant covers, while the grant is active; the person sees everything. Revoking a grant leaves the files in the person’s Drive. Drive can read file contents: it is not end-to-end encrypted. Data and privacy says what is stored, who sees it, and what deleting does.