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.
| Scope | Grants |
|---|---|
upload | POST /api/v1/files, resumable tus uploads, GET /api/v1/files/:id |
search | POST /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).