Every Space automatically sees 3 built-in kits, visible to every Space and immutable via this API: todo-list (Users who own Lists of Tasks), blog (Authors writing Posts that readers Comment on), and ecommerce (Customers placing Orders of Products, tracked via Order Items). A Space can also author its own custom kits, visible only to that Space. A local operator can add further global kits (see "Create a global starter kit" below).
definition shapeA kit's definition cross-references its own Types and Relationships by a local string key (typeKey/relationshipKey) instead of a real id, since none exist until the kit is applied to a Project. It follows the exact same field shapes as the manual Data Types, Relationships, and Mock Routes create requests.
Example definition
{
"types": [
{
"typeKey": "user",
"name": "User",
"routeName": "users",
"schema": {
"id": {
"type": "number"
},
"email": {
"type": "string",
"format": "email"
}
},
"identifierField": "id",
"uniqueFields": [
"email"
],
"generation": {
"recordCount": 5
}
},
{
"typeKey": "list",
"name": "List",
"routeName": "lists",
"schema": {
"id": {
"type": "number"
},
"userId": {
"type": "number"
}
},
"generation": {
"recordCount": 8
}
}
],
"relationships": [
{
"relationshipKey": "list-user",
"sourceTypeKey": "list",
"sourceField": "userId",
"targetTypeKey": "user",
"targetField": "id"
}
],
"routes": [
{
"method": "GET",
"path": "/lists",
"typeKey": "list"
},
{
"method": "GET",
"path": "/users/{id}/lists",
"typeKey": "list",
"relationshipKey": "list-user"
}
]
}
Saving a kit (create/update) runs a structural, database-free validation pass over this shape - the same rules a manual Type/Relationship/Route create request is checked against, just resolved against the definition's own arrays instead of live database rows. Applying a kit always re-runs the real, database-aware validation regardless, so correctness never depends on this pass alone.
Returns the 3 built-in kits plus any custom kits this Space has authored. Requires any resolvable Space role (viewer included).
Requires Space owner or admin. key must be lowercase letters/numbers/hyphens and unique within the Space. Returns 422 for a structurally invalid definition, 409 if key is already used in this Space.
Request
{
"key": "notes",
"name": "Notes",
"description": "A single flat Note type",
"definition": {
"types": [
{
"typeKey": "note",
"name": "Note",
"routeName": "notes",
"schema": {
"id": {
"type": "number"
}
},
"generation": {
"recordCount": 10
}
}
]
}
}
Response (201)
{
"id": 4,
"key": "notes",
"name": "Notes",
"description": "A single flat Note type",
"isSystem": false
}
Requires Space owner or admin. Returns 403 against any of the 3 built-in kits - they're immutable via this API. Deleting a kit is safe at any time: applying a kit only ever copies its definition into a Project once, so no durable link back to the kit exists afterward.
A global kit (space_id NULL) belongs to no Space, is visible to every Space immediately, and is always is_system (immutable, same as the 3 built-in kits) - so it needs a different authorization check than the Space-scoped create endpoint above, which checks a caller's role within a specific Space. This service has no separate "platform admin" identity concept, so this endpoint reuses the one bypass that already exists for exactly this kind of local-operator action: it only succeeds when AUTH_MODE=mock, and returns 403 otherwise. Never enable AUTH_MODE=mock in a shared/deployed environment - doing so also opens this endpoint there. Same request/response shape as Create a custom starter kit above, minus spaceId. There is no corresponding update/delete endpoint - removing a global kit created this way requires direct database access.
Requires effective Project editor or admin. starterKitId must be a built-in kit or belong to the Project's own Space. The target Project must have no existing Data Types - returns 409 otherwise, since applying a kit is all-or-nothing (no merging into an existing data model). Creates every Type, then every Relationship, then every Route from the kit's definition in one transaction; any failure rolls back the entire kit. Only scaffolds structure - it does not generate mock data (see Master Template docs) or create an API key (see API Keys docs), both of which remain separate follow-up steps.
Request
{
"starterKitId": 1
}
Response (201)
{
"starterKitId": 1,
"projectId": 42,
"typesCreated": [
{
"id": 101,
"typeKey": "user",
"name": "User",
"routeName": "users"
}
],
"relationshipsCreated": [
{
"id": 12,
"relationshipKey": "list-user"
}
],
"routesCreated": [
{
"id": 55,
"method": "GET",
"path": "/lists"
}
]
}