Documents
The document library stores all scheme files — by-laws, financial reports, meeting notices, minutes, insurance certificates, and more. Documents are organised into categories, controlled by access levels, and support versioning via supersession.
Categories
Every document belongs to a category. Categories are scheme-specific, but a set of system categories is seeded for every new scheme and cannot be deleted:
| System category | Typical contents |
|---|---|
| By-laws | Registered by-law documents |
| Financial Reports | Audited accounts, levy notices, budgets |
| Meeting Notices | Auto-generated when a notice is issued from a meeting |
| Meeting Minutes | Drafted and approved minutes for all meeting types |
| Insurance | Current and historical policy documents |
| Contracts | Contractor agreements, strata management agreements |
| Correspondence | Letters, NCAT applications, legal correspondence |
| Other | Catch-all for documents that don't fit above |
Committees can add custom categories. All categories have a is_system flag.
Access levels
Each document has an access_level that controls who can view it. Access is additive — a higher-privilege role sees all levels below its own:
| Level | Who can see it |
|---|---|
all | All authenticated users (including tenants) |
owners | Owners, committee, strata managers, admins |
committee | Committee members and above |
strata_manager | Strata managers and platform admins |
platform_admin | Platform staff only |
The API enforces access level filtering on every list and detail request. The computedaccessible_levels for the caller's role is used to filter the query server-side.
Versioning
When a document is superseded, the new version sets supersedes_document_id to the previous document's ID. The old document has is_current_version set to false.
- The document list endpoint returns only current versions by default (
?current_only=true). - The version history for a document is retrievable via
GET .../documents/:id/versions. - The
versionfield is an integer, incrementing from 1. - Superseding a document does not delete the old version — it remains accessible to users with the appropriate access level.
Publish workflow
Documents have an is_published flag. Unpublished documents are visible only to committee members and above. Publishing makes the document visible to all members at or above its access level.
- Meeting notices are auto-published when issued (
is_published: true). - Minutes are typically uploaded as draft, reviewed, then published after confirmation at the next meeting.
- Any committee member can publish or unpublish a document.
File uploads
Documents are stored in Supabase Storage. The upload flow:
- Client requests a signed upload URL via
POST /api/schemes/:id/documents/upload-url. - Client uploads the file directly to Supabase Storage using the signed URL.
- Client confirms the upload via
POST /api/schemes/:id/documentswith metadata.
Download links are short-lived signed URLs (1-hour expiry) generated on each detail or list request.
Allowed file types:
application/pdf.doc / .docx.xls / .xlsx.ppt / .pptximage/jpegimage/pngimage/webpimage/giftext/plaintext/csvOther MIME types return HTTP 422.
Meeting-linked documents
A document can be linked to a meeting via the optional meeting_id field. Meeting notices created automatically by the issue-notice endpoint are linked in this way. The meeting detail endpoint does not inline documents — query the document list with?meeting_id= to retrieve all documents attached to a meeting.
Plan access
- Full document history is available on every plan — there is no free tier or history cap.
- Document writes (upload, edit, publish) are blocked only when a scheme is past its trial without payment (status
expired), returning HTTP 402 until billing is set up. Storage is subject to Supabase project limits.
Fields
| Field | Type | Notes |
|---|---|---|
document_id | UUID | Primary key. |
title | string | Display name. Required. |
description | string | Optional longer description. |
category_id | UUID | Required. Links to document_categories. |
category_name | string | Denormalised for convenience on list responses. |
access_level | string | One of the five levels. Default: owners. |
is_published | bool | Controls visibility to non-committee members. |
version | int | Version number, starting at 1. |
is_current_version | bool | False for superseded documents. |
supersedes_document_id | UUID | Previous version's ID, if this is a replacement. |
file_name | string | Original filename. |
mime_type | string | MIME type of the uploaded file. |
file_size_bytes | int | Size of the uploaded file in bytes. |
meeting_id | UUID | Optional link to a meeting. |
signed_url | string | 1-hour download URL. Regenerated on each fetch. |