Vaze
API Reference

Overview

Authentication, conventions, and the response envelope

Vaze exposes a REST API under /api on your instance. Anything you can do in the dashboard, you can do over HTTP from any language.

https://<your-vaze-instance>/api

Authentication

Create an API key from the API Keys page in the dashboard (or with POST /api/keys from a signed-in session), then send it in the API-Key header on every request:

curl https://files.example.com/api/files \
  -H "API-Key: your-api-key"

Requests without a valid key receive a 401 response:

{ "data": null, "error": { "message": "Unauthorized" } }

A key acts as the user who created it, limited to the scopes picked for the key. A request needs the endpoint's scope on both the key and its owner's current role; otherwise it receives a 403 that names the missing scope:

// the owner's role lacks it
{ "data": null, "error": { "message": "Missing required scope \"files:write\"" } }

// the key lacks it
{ "data": null, "error": { "message": "API key is missing required scope \"files:write\"" } }

The only endpoints that skip authentication are the health check, the setup check and the public file hosting endpoint.

Signed-in sessions

Every endpoint also accepts the session cookie a user gets by signing in, which is how the dashboard and the mobile app call the API. A session acts with the user's own scopes, so it works for every role, including Viewers, who can't create API keys.

Some endpoints accept only a session, since they act on the account rather than its files: account changes, activity, API keys, users and instance settings. A request to them made with an API key gets a 403.

Sign in with POST /api/auth/sign-in/email and send the returned cookie back in the Cookie header. Clients outside a browser that send a cookie to /api/auth/* must also send an expo-origin header with an origin the instance trusts. The instance trusts vaze://, the mobile app's scheme.

Response envelope

Every JSON endpoint responds with the same envelope:

// success
{ "data": { ... }, "error": null }

// failure
{ "data": null, "error": { "message": "File not found" } }

Errors also carry a meaningful HTTP status code:

StatusMeaning
400Invalid input (missing fields, invalid names)
401Missing or invalid API key or session, or the user is disabled
403The key, or its owner, lacks the scope the endpoint needs, or an API key called a session-only endpoint
404File or folder not found
409Name conflict (a name already taken in the same folder, or by another of your API keys), or an email another account uses
413Upload too large, or too many files in one request
429Rate limited — retry after the Retry-After header
500Unexpected server error
507Not enough free space on the volume

Scopes

An admin gives every user a role on the Users page of the dashboard. Each role is a set of scopes, and the Custom role lets the admin pick scopes one by one:

ScopeAdminEditorViewerGrants
files:read✓✓✓List, search, download and sign files; browse and zip folders
files:write✓✓Upload, rename, move and change visibility; create, rename and move folders
files:delete✓✓Delete files and folders
api-keys:manage✓✓Create API keys, and call the API with them
settings:manage✓Instance settings (signed-in sessions only)
users:manage✓Add, edit, disable and remove users (signed-in sessions only; Admin role only)

api-keys:manage is checked on every request made with a key, so taking it away (or disabling the user) stops all of that user's keys at once. Role changes apply to the very next request.

API key scopes

Endpoints only ever ask for files:read, files:write or files:delete, so those are the scopes a key can carry. You tick them when you create the key, and only the ones your own role holds are on offer. Grant a key just what its app needs: an upload script needs files:write, a gallery only files:read.

A key's scopes are a ceiling on its owner's role, not a grant of their own. If the role later loses a scope, the key can't use it either, and it works again once the role gets it back. To change what a key can do, create a new one and delete the old one.

Keys created before key scopes existed carry all three file scopes.

EndpointScope
GET /api/me, GET /api/statsnone
GET /api/files, GET /api/foldersfiles:read
GET /api/files/download/:id, POST /api/files/downloadfiles:read
GET /api/folders/download, POST /api/files/signfiles:read
Private files on GET /api/hosting/... (with a key)files:read
POST /api/files, PUT /api/filesfiles:write
POST /api/folders, PUT /api/foldersfiles:write
DELETE /api/files, DELETE /api/foldersfiles:delete
/api/keys (signed-in sessions only)api-keys:manage
/api/me changes, /api/me/*, /api/activity (signed-in sessions only)none
/api/users (signed-in sessions only)users:manage
/api/settings, /api/settings/* (signed-in sessions only)settings:manage

Rate limits

Requests are limited per client IP: 300/minute across /api, and 600/minute on the public hosting endpoint. Exceeding either responds 429.

List query parameters

Endpoints that return lists of files accept these query parameters:

ParameterDefaultDescription
limitunlimitedMaximum number of files to return
offset0Number of files to skip (for pagination)
orderBycreatedAtOne of createdAt, updatedAt, name, size
orderDirectionDESCASC or DESC

Health check

GET /api/health — no authentication required. Useful for uptime monitoring and container health checks:

{ "data": { "message": "Vaze is running!" }, "error": null }

Setup check

GET /api/setup needs no authentication either. A new instance has no accounts, and the first one to register becomes the admin; after that, registration is closed and the admin adds everyone else. Clients use this to offer the right form:

{ "data": { "needed": true }, "error": null }

Endpoints

On this page