Collections
Collections store your data as items with defined properties. Each collection becomes a RESTful endpoint.
Naming
- Unique within the API
- Case-sensitive
- Allowed characters: letters, digits, hyphens, underscores
- The name becomes the endpoint path
/api/products
└── collection name
For external clients, replace /api with https://<region>.restapi.com/<api-name>. See Virtual Paths.
Renaming a collection changes its endpoint path.
Properties
Each collection can have up to 25 properties.
Property Rules
- Unique names within the collection
- Case-sensitive
- Allowed characters: letters, digits, underscores
- Must begin with a letter
Property Configuration
| Setting | Description |
|---|---|
| Name | Unique identifier for the property |
| Type | Data type (string, integer, decimal, etc.) |
| Required | If true, must be provided on create |
| Default | Value used when property is omitted |
| Validation | Min/max length or value constraints |
Data Types
| Type | Description |
|---|---|
string | Text, max 1024 characters |
integer | Whole numbers (-2,147,483,648 to 2,147,483,647) |
decimal | Decimal numbers |
boolean | true or false |
date | Date only (YYYY-MM-DD) |
date-time | Date and time in ISO 8601 format |
guid | Unique identifier (UUID format) |
blob | Binary data (files) |
object | Reference to another model |
System Fields
Every collection you create comes with system fields that the platform manages — you don't declare them, and you can't set their values.
| Field | Type | When it's set |
|---|---|---|
id | guid | On create — primary key, server-generated |
created | date-time | On create — never changes |
createdBy | user reference | On create — the user who created the record¹ |
modified | date-time | On create, then on every update |
modifiedBy | user reference | On create, then on every update¹ |
sequence | integer | On create — insertion order, a stable sort key |
¹ createdBy/modifiedBy are filled only when the write is authenticated with a user token — writes made with an API key or service token leave them empty. On read they expand to a nested { id, name, email } object, so you can select into them:
?select=name,total,createdBy.name,createdBy.email,modified
Because created and modified already exist, there's no need to add your own createdAt/updatedAt property to track when a record was created or changed. You can filter and select system fields, and sort by created, modified, sequence, or id.
user reference in the table above is just how a lookup at the built-in user collection is displayed — you can declare one yourself with typeName: "user".
To scope rows by who created them, you don't need to declare anything:
- Own rows only — grant
_CREATORon the method.GET,PATCHandDELETEagainst the collection, or a view over it, are then filtered to rows whosecreatedByis the caller — no extra property to declare. Queries are not filtered this way, and_CREATORnever grants creation; see Owner-Only Access for the full limits. - Creator as part of a security-policy path —
createdByis a real lookup atuser, so it can carry a direction (TargetFilteredByEntity, ↑) like any other lookup. It is unset by default, and the Developer Portal doesn't offer it on system properties, so set it through the schema API — POST Schema matches properties by name, while PUT Schema matches byid, so sendcreatedBywith itsidor the direction is dropped without an error. Note that giving any lookup a direction makes the whole collection row-filtered, which also means anonymous requests to it are rejected.
Declare your own user lookup when ownership has to be someone other than the creator — an assignee, a transferable owner, an approver. Adding a second person property that only ever holds the creator duplicates createdBy.
Lookup Properties
Create relationships between collections:
{
"name": "customer",
"type": "lookup",
"target": "customers"
}
Access related data in queries or via the select parameter:
?select=orderDate,total,customer.name,customer.email
Self-Referencing Lookups
Collections can reference themselves, which is useful for hierarchical data structures:
{
"name": "categories",
"properties": [
{ "name": "name", "type": "string" },
{ "name": "parent", "type": "lookup", "target": "categories" }
]
}
Use cases:
- Category trees with parent/child relationships
- Organizational hierarchies
- Threaded comments
- File/folder structures
Validation
Required Fields
Required properties must be included in POST/PUT requests:
{ "name": "email", "type": "string", "required": true }
Missing required fields return 400 Bad Request.
String Constraints
Limit string length:
{
"name": "title",
"type": "string",
"minLength": 1,
"maxLength": 100
}
Numeric Constraints
Set value boundaries:
{
"name": "quantity",
"type": "integer",
"min": 0,
"max": 1000
}
Default Values
Provide defaults for optional properties:
{
"name": "status",
"type": "string",
"default": "pending"
}
Defaults apply to POST and PUT operations when the property is omitted.
Expression-Based Defaults
Use expressions for dynamic default values:
| Expression | Description |
|---|---|
now() | Current UTC date-time |
now() + 7D | 7 days from now |
now() - 1H | 1 hour ago |
newId() | Generate unique GUID |
10 + 5 | Numeric calculation |
Date/time tokens: now(), D (days), H (hours), M (minutes), S (seconds). Tokens are case-insensitive.
{
"name": "publishedAt",
"type": "date-time",
"default": "now()"
}
{
"name": "dueDate",
"type": "date-time",
"default": "now() + 7D"
}
See Data Types for complete documentation on default value expressions.
Example Collection
{
"name": "products",
"properties": [
{ "name": "sku", "type": "string", "required": true },
{ "name": "name", "type": "string", "required": true, "maxLength": 200 },
{ "name": "description", "type": "string" },
{ "name": "price", "type": "decimal", "required": true, "min": 0 },
{ "name": "stock", "type": "integer", "default": 0, "min": 0 },
{ "name": "isActive", "type": "boolean", "default": true },
{ "name": "publishedAt", "type": "date-time", "default": "now()" },
{ "name": "category", "type": "lookup", "target": "categories" },
{ "name": "image", "type": "blob" }
]
}