A collection is a user-defined datatype. It is stored as a collection record holding a JSON Schema, and once defined it behaves exactly like a built-in datatype — same repository routes, same BaseModel envelope, same lifecycle and permissions.
This is why AppEngine has 261 built-in datatypes and no migration story for adding a 262nd: you add a collection.
Reading collections
/repository/collections/:name?/:subName?JWTWith no name, returns every collection in the tenant. getCollections also filters by subType and by CollectionType, and enriches by default.
Schemas define data and UI
Collection schemas are JSON Schema documents extended with x- keywords that the form renderer consumes. One document validates the record and describes the form.
{
"type": "object",
"properties": {
"summary": {
"type": "string",
"x-control-variant": "textarea"
},
"categories": {
"type": "array",
"items": { "type": "string" },
"x-control": "selectMany",
"x-control-variant": "tree",
"dataSource": {
"source": "collection",
"collection": "category",
"value": "name",
"label": "name",
"children": "children"
}
},
"css": {
"type": "string",
"x-control": "code",
"x-control-variant": "css",
"collapsible": true
}
}
}| Keyword | Effect |
|---|---|
x-control | Control type — selectMany, file, code, … |
x-control-variant | Variant — textarea, chip, combo, tree, css, javascript |
x-render | How to display the stored value |
dataSource | Option source: { source: 'collection', collection, value, label, children } or { source: 'function', value } |
hidden / hideIn | Hide always, or only in a named context such as generator |
readOnly | Display but do not edit |
collapsible | true or "close" — render as a collapsible group |
group, layout, showIndex | Grouping and layout |
styleClass, styling | Class hooks for the container and layout |
labelPostion | Label placement (spelled this way in the schema) |
Studio renders these directly, which is why a new collection gets a working editor with no extra UI work.
Repairing a collection
/repository/collections/fixJWTBody is an array of { action, datatype }. fixCollection reconciles the MongoDB collection with its schema — creating it if missing and adding indexes.
You will meet this indirectly: a full-text search against a collection with no text index fails with text index required for $text query, and search calls fixCollection for that datatype and retries once automatically. The first search on a fresh collection may be slow, but it succeeds.
createTimeSeriesCollection creates a MongoDB time-series collection for metric-shaped datatypes, rather than a standard one.
Search indexes
createSearchIndex(orgid, datatype, page) walks a collection page by page and indexes its records. Use it after a bulk import, when records were written by a path that skipped indexing.
Settings
Org configuration is stored and read through the same layer, keyed by BaseSettingKeys:
/repository/setting/:settingType/:settingName?/:subName?JWT/repository/setting/:settingType/:settingName?/:subName?JWT/repository/setting/:settingType/:settingName?/:subName?JWTsettingType is the top-level key; settingName and subName drill into named and nested values. Admin only.
Settings that change platform behavior include securitySettings (enableTwoFactorForUsers, enableNewDeviceAuthentication, alertOnNewDeviceLogin) and passcodeLoginSettings (whether POS sign-in needs a pin or is instant).
Subschemas
A datatype can carry variants in subschema. In a URL they are written with a hyphen:
GET /repository/search/page-landingThe repository splits on the first hyphen: page is the collection, landing the subschema, and the query filters on subschema. If only a collection name is given, no subschema filter is applied.