Silo organises content in a deliberate hierarchy. Understanding the names and how they nest makes every API route, every claim, and every export command immediately readable. This page defines each term, explains how the pieces fit together, and covers the details you will reach for when building real applications.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/org-quicko/silo/llms.txt
Use this file to discover all available pages before exploring further.
Glossary
| Term | What it is |
|---|---|
| Instance | One data directory with one instance_id. Everything below is inside it. |
| Project | A named container — for example a tenant or an application. |
| Environment | A named container inside a project — for example prod or staging. |
| Collection | A name and a JSON Schema document, identified by (project, environment, name). |
| Entry | A JSON document in a Silo envelope: a ULID id, a rev, a seq, and UTC timestamps. |
| Variable | A name declared once in a project, valued per environment, substituted into each {{NAME}} an entry holds on the way out. |
| API key | A key with explicit claims. Silo has no users and no sessions. |
Scope hierarchy
The hierarchy flows from broadest to narrowest: Instance → Project → Environment → Collection → Entry. Every API route reflects this nesting directly in its URL path.Entries and the envelope
An entry is a JSON document wrapped in a Silo envelope. When you read an entry, Silo returns it flattened — the envelope fields come first, followed by your own fields:| Field | Type | Description |
|---|---|---|
id | ULID string | Unique, sortable identifier. ULIDs are lexicographically ordered by creation time. |
rev | integer | Revision counter. Incremented on every update. Used for optimistic concurrency. |
seq | integer | Instance-wide write cursor. Monotonically increasing across all collections. |
created_at | RFC 3339 UTC | When the entry was first created. |
updated_at | RFC 3339 UTC | When the entry was last updated. |
$.data in JSONPath filter expressions, so a field you name id can never shadow the envelope’s id.
Optimistic concurrency
PUT and DELETE on an entry require the revision you expect, sent as If-Match: "3" or ?rev=3. Every entry response carries the current rev, so send back the one you read. A mismatch returns 409 Conflict. This is what prevents two admin tabs from overwriting each other silently.
A read is never refused because of a schema mismatch. Silo validates only writes, so a schema change can never make stored data unreadable.
Collections and JSON Schema
A collection is defined by a name and a JSON Schema document (draft 2020-12, validated in full by Ajv). The schema describes exactly what documents the collection accepts.- Every write is validated. There is no way to bypass schema validation on create or update.
- Reads are never validated. A schema change cannot make existing entries unreadable.
- The schema is frozen while entries exist. To change the fields that determine validity, you must delete the entries first — or export them, create a new collection, and import them back.
- Some schema fields stay editable at any time.
x-silo-auth,x-silo-search,title,description,$comment, and$schemado not change which entries are valid, so they can always be edited even when the collection holds entries.
x-silo-* schema keywords
Silo extends JSON Schema with a small set of x-silo-* keywords that control rendering and protection in the admin UI — for example, marking a field as private or declaring which fields contribute to the full-text search index. These keywords are always editable regardless of entry count.
System collections
Names that start with_ belong to Silo. You cannot create a collection whose name begins with _.
The most important system collection is _keys, which lives at the reserved scope _system/_system. Silo stores API keys there exactly like any other content — which is why every storage driver and the export engine handle keys with no special code.
_system/_system is not a project and environment you created. It is a reserved scope managed by Silo itself.Variables
Variables let one value differ between environments without duplicating entries. You declare a variable name once in a project, then set its value separately in each environment. When Silo returns an entry, it substitutes each{{NAME}} placeholder in the document with the current environment’s value for that variable. A name that has no declaration and a name with no value for this environment are left as-is rather than blanked.
prod as:
staging as:
API Keys and claims
Silo has no user accounts and no sessions. Every request is authenticated with an API key. A key carries a set of explicit claims that enumerate exactly what it may do. Access is deny by default — a key with no claims can do nothing. A key can only mint keys whose claims are a subset of its own. The root key (printed once on first start) holds all claims and can delegate any of them. Claims are scoped to the hierarchy. For example, a claim might allow reading entries in all collections insidedefault/prod, or only in a specific collection. Wildcards are available per segment.