Authentication

Every API request is authenticated with an API key. There are no other authentication methods on /api/v1 routes — session cookies from the web app are never accepted.

Creating a key

Open Settings → API keys in the app and create a key. Pick a name and the scopes the key should have. The secret starts with na_ and is displayed once at creation — store it somewhere safe. Only a hash is kept on the server, so a lost secret can't be recovered; revoke the key and create a new one instead.

Using a key

Send the secret as a Bearer token on every request:

curl https://your-host/api/v1/files/0198c9a0-… \
  -H "Authorization: Bearer na_your_key"

A missing or invalid key returns 401 unauthorized. A valid key that lacks the required scope returns 403 forbidden.

Scopes

Scopes are chosen when the key is created and can't be changed afterwards — create a new key to change access.

ScopeGrants
uploadPOST /api/v1/files, resumable tus uploads, GET /api/v1/files/:id
searchPOST /api/v1/search, GET /api/v1/files/:id

Keys act as their creator

A key performs actions as the member who created it, inside that member's team. Uploads are attributed to the key's creator, and the creator's team role must additionally grant the file-upload permission — a key with the upload scope still gets 403 forbidden if its owner's role can't upload. Revoking a key takes effect immediately.

Rate limiting

Each key may make 120 requests per 60-second window. Above that, requests fail with 429 rate_limited and a Retry-After header telling you how many seconds to wait:

HTTP/2 429
retry-after: 42

{ "error": { "code": "rate_limited", "message": "Rate limit exceeded" } }

Note that a resumable tus upload counts as two requests against the window (one when the upload is created, one when it finishes).