API Reference
API Reference
Section titled “API Reference”This document is the authoritative V1 API contract. The mobile client is the source of truth: the Go server must match it exactly (method + path + response envelope).
Reference file:
docs/api-v1.mdin the repository.
- Base URL:
http://<host>:8080/api/v1 - Format: JSON everywhere, except
POST /files/upload(multipart). - Success envelope:
{ "data": T, "meta"?: { "page", "pageSize", "total" } }(metais present on paginated lists). - Error envelope:
{ "error": { "code", "message" } }+ proper HTTP status.
Authentication
Section titled “Authentication”- The device registers first:
POST /deviceswith a client-generated identifier (32-hex). The response contains{ "deviceId" }only — no token. - Then
POST /auth/login(username,password,device_id) returns a PASETO v4-local token. - Subsequent requests use
Authorization: Bearer <token>. - Token TTL is 7 days, no refresh. Signing secret:
AUTH_SECRET. - Identifiers are opaque 32-hex lowercase strings (
^[0-9a-f]{32}$).
Endpoints
Section titled “Endpoints”| Method | Path | Auth | Description |
|---|---|---|---|
GET | /health | — | Status probe, { "status": "healthy" }. |
POST | /devices | — | Register a device (client-generated deviceId). |
POST | /auth/login | — | Login, returns { token, expires_at, user }. |
GET | /shares/links/:token | — | Public share-link resolution. |
GET | /users/resolve?username= | ✓ | Resolve a username (exact match only). |
PATCH | /users/me/password | ✓ | Change own password. |
GET | /files | ✓ | List files (folderId?, page?, pageSize?, sort?). |
GET | /files/:id | ✓ | Get one file. |
DELETE | /files/:id | ✓ | Delete a file (owner-only for shared resources). |
GET | /files/search?q= | ✓ | Search files. |
GET | /files/folders | ✓ | List root folders. |
POST | /files/upload | ✓ | Upload (multipart file, optional folderId). |
POST | /ocr/jobs | ✓ | Create an OCR job ({ "fileId" }). |
GET | /ocr/jobs/:id | ✓ | Poll an OCR job. |
POST | /sync/ops | ✓ | Apply client outbox operations (sequential). |
GET | /sync/permissions?after= | ✓ | Permission snapshot / delta. |
Sync protocol
Section titled “Sync protocol”Outbox — POST /sync/ops
Section titled “Outbox — POST /sync/ops”The client sends a batch of operations. Each operation:
{ "operations": [ { "operation_id": "…32-hex", "ref_type": "resource", "ref_id": null, "resource_id": "…32-hex", "resource_type": "folder", "operation": "create_resource", "payload": {} } ]}Supported operations: create_resource, update_metadata,
delete_resource, move_resource, share, revoke_share,
update_share, create_link, revoke_link.
Key rules:
- Operations are applied sequentially; the server stops at the first non-idempotent error and returns the index reached.
- Idempotence is scoped per device:
UNIQUE(device_id, operation_id). Replayed operations are no-ops. delete_resourceis idempotent (deleting a missing resource succeeds).- Sharing requires the resource to be owned by the caller.
Response:
{ "applied": 3, "failed": { "operation_id": "…", "code": "NAME_CONFLICT", "message": "…" } }Snapshot — GET /sync/permissions?after=<cached_at_ms>
Section titled “Snapshot — GET /sync/permissions?after=<cached_at_ms>”Returns the effective permissions for the current user. The server is the
source of truth for effective_access resolution (viewer < commenter < editor < owner). Ancestors propagate only when inherit = true; expired
relations are ignored. A after delta filters on resource.updated_at and the
winning relation’s updated_at. After 24h without reseed, the client
downgrades its cache to read-only (viewer).
Common error codes
Section titled “Common error codes”| Code | HTTP | Meaning |
|---|---|---|
UNAUTHORIZED | 401 | Missing/invalid/expired token, or bad login credentials (indistinguishable by design). |
INVALID_DEVICE_ID | 400 | Device not registered. |
NOT_FOUND | 404 | Resource, user or link not found. |
NAME_CONFLICT | 409 | Same name in the same parent (or root). |
FILE_TOO_LARGE | 413 | Upload exceeds MAX_FILE_SIZE_MB. |
GRANTEE_NOT_FOUND | 404 | Share target user does not exist. |
INVALID_PASSWORD | 403 | Wrong current password on password change. |
NETWORK_ERROR / INVALID_RESPONSE / HTTP_<status> | — | Client-only errors. |
POST /ocr/jobs { "fileId" }→{ "id", "status": "queued" }, processed asynchronously in a goroutine.- Poll
GET /ocr/jobs/:idevery 3s untildone/failed(queued → processing → done | failed). - Engine: Tesseract system call (
OCR_LANG). PDFs get their text layer extracted; scanned PDFs yield empty text (out of V1 scope).