Databases
Data lives in documents inside collections inside a database. Documents are JSON. Schema (collections, attributes, indexes) is managed with an API key; document reads and writes go through the permission matrix.
Collections
Create a collection with a permission list and optional per-document security:
curl -X POST "https://base.finiteskills.com/v1/databases/main/collections" \
-H "X-Appwrite-Project: <YOUR_PROJECT_ID>" -H "X-Appwrite-Key: <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"collectionId":"notes","name":"Notes","documentSecurity":true,
"permissions":["read(\"any\")","create(\"users\")"]}'
With documentSecurity on, each document can carry its own permissions in addition to the
collection's.
Attributes (typed schema)
Attributes are optional — undeclared keys are stored as-is — but declaring them enables validation and
defaults. Create them with POST .../attributes/{type}:
string { key, size, required, default } // + formats: email, url, ip, enum
integer { key, min, max, required, default }
float { key, min, max, required, default }
boolean { key, required, default }
datetime { key, required, default }
email | url | ip | enum(elements) // string sub-formats
vector { key, dimensions } // for similarity search
relationship { key, relatedCollection, type } // see Relationships
Add "array": true to store a list of that type. Validation runs on create and update;
violations return 400 general_argument_invalid.
Documents
POST /databases/main/collections/notes/documents { documentId, data, permissions }
GET /databases/main/collections/notes/documents (list; supports queries[]=…)
GET /databases/main/collections/notes/documents/{id}
PATCH /databases/main/collections/notes/documents/{id} { data } (partial merge)
DELETE /databases/main/collections/notes/documents/{id}
Every document carries metadata: $id, $collectionId, $databaseId,
$createdAt, $updatedAt, $permissions, $sequence.
Indexes
Create key, unique or fulltext indexes with
POST .../indexes. Unique indexes are enforced on every write; fulltext indexes power the
search operator.
Auto-expiring documents (TTL)
Set $expiresAt to an ISO-8601 datetime on create or update and the document is removed once that
time passes. Pass null to clear an expiry; omit the field to leave it unchanged.
POST /databases/main/collections/sessions/documents
{ "documentId":"unique()", "data":{...}, "$expiresAt":"2026-08-01T00:00:00.000Z" }
PATCH /databases/main/collections/sessions/documents/{id}
{ "$expiresAt": null } # never expire
Cross-collection transactions
Where the atomic batch is scoped to one collection, a transaction applies a list of operations spanning any collections and databases in the project — all-or-nothing. If any operation fails (validation, a permission denial, a unique-index clash), the whole set rolls back and nothing is written.
curl -X POST "https://base.finiteskills.com/v1/databases/transactions" \
-H "X-Appwrite-Project: <YOUR_PROJECT_ID>" -H "X-Appwrite-Key: <API_KEY>" \
-H "Content-Type: application/json" -d '{
"operations": [
{ "databaseId":"main","collectionId":"accounts","op":"update",
"documentId":"a1","data":{"balance":40} },
{ "databaseId":"main","collectionId":"accounts","op":"update",
"documentId":"a2","data":{"balance":60} },
{ "databaseId":"main","collectionId":"ledger","op":"create",
"data":{"from":"a1","to":"a2","amount":20} }
]
}'
Each operation is { databaseId, collectionId, op, documentId?, data?, permissions? } where
op is create, update or delete. Needs a server key.
Evolving & removing schema
Collections, attributes and databases can be edited and dropped (server key). Dropping a collection or database removes its documents:
PATCH /databases/{db}/collections/{coll} # rename / change permissions & security
DELETE /databases/{db}/collections/{coll} # drop the collection
PATCH /databases/{db}/collections/{coll}/attributes/{key} # change an attribute (e.g. required/default)
DELETE /databases/{db}/collections/{coll}/attributes/{key} # drop an attribute
DELETE /databases/{db} # drop the database