Dazr Files API: developer docs
Read files from Dazr Files in your own software, for example to back them up: a REST API with a changes feed, and WebDAV for backup tools. Read only.
- Quick start
- Organisation access
- A person’s own files
- Reference
- Incremental backups
- Errors and limits
- WebDAV
Quick start
- Register your app and enable the Dazr Files API. Register your app, or use one you already have, in the Dazr Identity console: the same place as for Sign in with Dazr Identity and the Dazr Sign API, with the same client ID and secret. On your app’s page, choose Enable Dazr Files API. For unattended backups the app must be a web server app (with a client secret).
- Get approved. Give the organisation your client ID. An owner or admin opens Dazr Identity → Organisations → the organisation → Connected apps for Files, enters the client ID and chooses what your app may read: all shared files, or chosen folders with everything in them. They can also limit your app to listed networks (IP ranges).
- Get a token. Your server asks for a token with
grant_type=client_credentials, the organisationidasorg, and your client ID and secret (HTTP Basic or the form body). Only apps with a client secret can do this. - Call the API. Send the access token as
Authorization: Bearer. It lasts 10 minutes and there is no refresh token: ask for a new one when it runs out.
curl -u "$DAZR_CLIENT_ID:$DAZR_CLIENT_SECRET" https://identity.dazr.eu/oauth/token \
-d grant_type=client_credentials -d scope=files.read -d org=org_3k9x2m0q8w1v5t7a
{ "access_token": "eyJhbGciOiJFUzI1NiIs...", "token_type": "Bearer", "expires_in": 600, "scope": "files.read" }
curl -H "Authorization: Bearer $TOKEN" https://suite.dazr.eu/api/files/v1/spaces
Organisation access for backups
There are two ways in. An organisation’s owner or admin approves your app for the organisation’s shared files, and your server then gets tokens without a person (best for unattended backups). Or a person allows your app with the files.read scope, and your app reads that person’s own files.
An organisation that did not approve your app, one that revoked it and one that does not exist all answer invalid_grant. The admins see when your app was last used and every file it downloaded, and can change its folders or revoke it at any time. A revoked approval stops on the next request: tokens already issued stop working at once, and so do download links already handed out. Members’ own files are never part of an organisation’s approval.
| Parameter | Meaning |
|---|---|
grant_type | client_credentials |
org | The organisation id, shown to its admins under Connected apps for Files. |
scope | files.read (the default and the only scope). |
| Client authentication | Your client ID and current client secret, with HTTP Basic (client_secret_basic) or in the form body (client_secret_post). A previous secret kept after a transfer is not accepted. |
A person’s own files
Ask for openid files.read (and offline_access for a refresh token) in the usual authorization code flow with PKCE. The person sees on the consent screen that your app may see and download their files. The token reaches their own files, and an organisation’s shared files only when that organisation also approved your app and the person is a member who may open them, with the same folders. When the person removes your app under Connected apps, its tokens stop.
Reference
Base URL https://suite.dazr.eu/api/files/v1. Every endpoint is GET (and HEAD); any other method answers 405. Errors are JSON: { "error": { "code", "message" } }. Lists take limit (1 to 1000, default 200) and return next_cursor while there is more.
| Request | What it returns |
|---|---|
GET /spaces | The spaces your token reaches: me for a person’s own files, and organisations by their id. |
GET /spaces/{space} | One space. |
GET /spaces/{space}/folders/root/children | The folders, then the files, at the top of what your token reaches. Use a folder id instead of root for a folder. |
GET /spaces/{space}/folders/{id} | One folder. |
GET /spaces/{space}/files/{id} | One file: name, path, parent_id, size, mime, version, etag, created_at, modified_at and trashed_at. |
GET /spaces/{space}/files/{id}/versions | The kept versions of a file, newest first. |
GET /spaces/{space}/files/{id}/content | A redirect (302) to a download link at files.dazr.eu that works for 5 minutes and supports byte ranges. Add version= for an earlier version, or redirect=false to get the link as JSON. |
GET /spaces/{space}/trash | Files in the trash, as metadata. They cannot be downloaded until someone restores them. |
GET /spaces/{space}/changes | What changed since a cursor, for incremental backups (below). |
Every request needs the files.read scope. Query parameters:
| Parameter | Meaning |
|---|---|
limit | Items per page for children, trash and changes: 1 to 1000 (default 200, for changes 500). |
cursor | The next_cursor of the previous page, or for changes the cursor it returned. |
version | For content: a version number from versions. Without it, the current version. |
redirect | For content: false returns { "url", "expires_in" } instead of a 302. |
GET /spaces
{ "spaces": [ { "id": "org_3k9x2m0q8w1v5t7a", "type": "organisation", "name": "Bakkerij Jansen", "folders": "chosen" } ] }
GET /spaces/org_3k9x2m0q8w1v5t7a/folders/root/children?limit=2
{ "items": [
{ "id": "Hk2mQ9xP4aL1", "type": "folder", "name": "Finance", "parent_id": null, "path": "/Finance",
"created_at": "2026-09-01T08:12:40.000Z" },
{ "id": "p3RtY7uW0zQe", "type": "file", "name": "Budget 2027.xlsx", "parent_id": "Hk2mQ9xP4aL1",
"path": "/Finance/Budget 2027.xlsx", "size": 48213,
"mime": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "version": 3, "version_count": 3,
"etag": "\"p3RtY7uW0zQe.3.48213\"", "sha256": null, "created_at": "2026-09-02T10:00:00.000Z",
"modified_at": "2026-10-14T16:31:09.000Z", "trashed_at": null } ],
"next_cursor": "o.2" }
GET /spaces/org_3k9x2m0q8w1v5t7a/files/p3RtY7uW0zQe/versions
{ "versions": [ { "version": 3, "size": 48213, "mime": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"created_at": "2026-10-14T16:31:09.000Z", "current": true, "restored_from": null } ] }
GET /spaces/org_3k9x2m0q8w1v5t7a/files/p3RtY7uW0zQe/content
302 Found
Location: https://files.dazr.eu/v1/file?t=g1.…
curl -L -o "Budget 2027.xlsx" -H "Authorization: Bearer $TOKEN" \
https://suite.dazr.eu/api/files/v1/spaces/org_3k9x2m0q8w1v5t7a/files/p3RtY7uW0zQe/content
Follow the redirect (curl -L): the link at files.dazr.eu needs no Authorization header. A file that is not in the Files gateway yet is streamed directly instead of redirected.
Checksums: Dazr Files does not store a hash of each file’s content, so sha256 is always null. The etag changes whenever the content changes (a new version). Compute your own hash while you download if you need one. Files are stored encrypted (AES-256-GCM, with a key for each space that Dazr holds) and Dazr decrypts them when you download them over TLS. This is not end-to-end encryption.
Incremental backups
Call changes without a cursor once: every folder and file comes back as created, with a cursor. Keep the cursor and send it next time as cursor=. You get what changed since: created, updated (new content), moved (renamed or moved to another folder), trashed, restored and deleted (gone for good, or no longer in the folders your app may read). Each change has the id, item_type and the current item (null when deleted). Folders come before files, parents before their children. While has_more is true, call again with the new cursor. When nothing changed you get the same cursor back. A cursor works for 90 days, for your app and that space only; an expired one answers 410, and you start again without a cursor. Only your app’s 5 newest cursors for a space stay valid.
GET /spaces/org_3k9x2m0q8w1v5t7a/changes?cursor=dc1.ds_…
{ "changes": [
{ "type": "updated", "id": "p3RtY7uW0zQe", "item_type": "file",
"item": { "id": "p3RtY7uW0zQe", "type": "file", "name": "Budget 2027.xlsx", "version": 4, … } },
{ "type": "deleted", "id": "Zx81LmQa2bNc", "item_type": "file", "item": null } ],
"cursor": "dc1.ds_…",
"has_more": false }
Errors and limits
Errors have an HTTP status and a body like { "error": { "code": "not_found", "message": "..." } }. Anything your token does not reach answers 404, the same as something that does not exist.
| Status | Codes |
|---|---|
400 | invalid_limit, invalid_cursor (a cursor of another app or space) |
401 | unauthenticated, invalid_token (expired or revoked, the approval or the person’s consent was removed, or the Dazr Files API was turned off for your app) |
403 | insufficient_scope, files_api_disabled, network_not_allowed (the organisation listed networks and this request comes from elsewhere) |
404 | space_not_found, folder_not_found, not_found, version_not_found, unknown_endpoint |
405 | method_not_allowed: any method other than GET, HEAD and OPTIONS |
410 | cursor_expired: start again without a cursor |
429 | rate_limited, with a Retry-After header |
503 | not_available, storage_unavailable: try again later |
The token endpoint answers OAuth errors: invalid_client (wrong client ID or secret, or an app without a client secret), unauthorized_client (the Dazr Files API is not enabled for your app), invalid_scope and invalid_grant (no approval by that organisation, or not from its listed networks).
| What | Limit |
|---|---|
| API requests | 600 a minute per approval (or per person and app), 6,000 a minute per app, 1,200 a minute per IP address |
| Downloads | 300 a minute per approval over the API, 600 a minute over WebDAV |
changes | 120 an hour per space without a page cursor; further pages are not limited separately |
| WebDAV requests | 1,200 a minute per approval |
/oauth/token | 600 requests a minute per IP address, and 300 a minute per app |
Every download is logged for the organisation’s admins with your app’s name, the file, the time and part of the IP address: the latest 5,000, for up to 180 days. The same file downloaded again within 10 minutes counts once. The organisation’s Files activity shows one line a day for your app. Downloads from a person’s own files show in their Connected apps.
WebDAV
For backup tools that speak WebDAV, an organisation’s admin creates a WebDAV sign-in for your app under Connected apps for Files. The password is shown once, is stored only as a hash and is never anyone’s Dazr password. The sign-in follows the approval: the same folders, networks and limits, and it stops when the approval is revoked.
| Setting | Value |
|---|---|
| Server | https://files.dazr.eu/dav/ |
| Sign-in | HTTP Basic with the username (dzw_…) and password from the admin. |
| Methods | OPTIONS, PROPFIND with Depth: 0 or 1, GET and HEAD with byte ranges. Depth: infinity is refused. Every write answers 403 or 405. |
Folder and file names are shown as they are in Dazr Files. When two items in a folder have the same name (ignoring case), the older one keeps it and the others get their id in brackets before the extension, so every item has its own path. A folder with more than 10,000 items cannot be listed over WebDAV; use the API for it. After 10 failed sign-ins from one IP address within 15 minutes, that address waits 15 minutes.
rclone
- Run
rclone config, choosenfor a new remote, name itdazrand choose the storage typewebdav. - URL:
https://files.dazr.eu/dav/. Vendor:other. User: the username (dzw_…). Password: choose to type it yourself and paste the password. - Leave the bearer token empty and save. Check it with
rclone lsd dazr:, then back up.
# ~/.config/rclone/rclone.conf (rclone obscure <password> gives the pass value)
[dazr]
type = webdav
url = https://files.dazr.eu/dav/
vendor = other
user = dzw_0123456789abcdef0123
pass = <obscured password>
rclone lsd dazr:
rclone sync dazr: /backup/dazr --transfers 4
rclone compares size and modification time. Use copy instead of sync to keep files in your backup that were deleted in Dazr Files.
Synology Cloud Sync
- Open Cloud Sync on the NAS, add a cloud provider and choose WebDAV.
- Server address:
https://files.dazr.eu/dav/. Username and password: the WebDAV sign-in from the admin. - Choose a local folder, the remote folder
/(or one folder), and the sync direction Download remote changes only.
Cloud Sync with WebDAV, sync direction “Download remote changes only”. Hyper Backup writes backups to WebDAV but cannot read from it.