Custom data collections overview
Define a custom data schema, publish it as a version, and store records against it.
A collection is a custom data schema - the structured-data store behind forms, and usable on its own for anything you would otherwise add a table for.
Three levels, and the middle one is the part worth understanding:
| Level | What it is |
|---|---|
| Collection | The named thing, with a slug. Long-lived |
| Version | One immutable set of field definitions |
| Record | One row, stored against a specific version |
curl https://api.console.buildbase.app/api/collections \
-H "Authorization: $BUILDBASE_TOKEN"Before you start
Build collections in the console: Content in the left rail, then Collections under Data (step by step: create a collection). Every endpoint here is token-authenticated - there is no public read path, so a collection is not a substitute for a public CMS API.
Versions are the schema
Fields do not live on the collection. They live on a version, so changing the schema means publishing a new version rather than editing the old one - and records stay readable against the version they were written under.
A version is created with live: false. Setting live: true publishes it:
it is refused with 400 "Fields must be added first" on a version with no
fields, and it marks every older version of the collection deprecated, so one
version is live at a time.
Warning
A live version cannot be edited. PATCH on one returns 400 with
"Cannot update live version". This is deliberate - records already point at
it, so editing its fields would change the meaning of stored data.
To change a schema, create a new version and publish that.
Field types
Each field on a version has one type: text, rich-text, email,
link, color, number, integer, bool, date, select,
multi-select, money, location and file. Note the name bool - not
boolean.
Field types has what each one stores, its settings (lengths, ranges, patterns, choices, a money field's currency) and the errors a write can get.
Each field carries slug, title, helpText, type, required, and
defaultValue. The slug is the key records are stored under.
File fields
A file field holds an image - JPEG, PNG, GIF, WebP or SVG - as one of your
assets, never the bytes themselves. It has no default value; it has two
settings instead:
| Setting | Meaning | Range | Default |
|---|---|---|---|
maxMb | The largest file it takes, in MB | 0.1 to 100 | 5 |
maxFiles | How many files it takes in one record | 1 to 10 | 1 |
Your plan's own per-file limit still applies below maxMb.
A record stores what the file is:
{
"receipt": {
"assetId": "6ace3b0e898d27ef4b7a6a30",
"name": "receipt.png",
"size": 900000,
"mimeType": "image/png"
}
}A field whose maxFiles is above 1 stores a list of them, even when it
holds one file:
{
"photos": [
{
"assetId": "6ace3b0e898d27ef4b7a6a30",
"name": "front.png",
"size": 412000,
"mimeType": "image/png"
},
{
"assetId": "6ace3b0e898d27ef4b7a6a31",
"name": "back.png",
"size": 398000,
"mimeType": "image/png"
}
]
}When you write a record yourself, send the asset by id - { "assetId": "..." }
or the id alone - after uploading it; for
a field that takes several files, send a list of them. The name, size and type
are read back from the asset, whatever the request says, and the same asset
sent twice is stored once. An empty string clears the field.
The write is refused with 400, naming the field, when an id is not one of
your assets, when a list is sent to a field that takes one file, when there
are more files than maxFiles, or when a file is larger than the field's
maxMb - the same limit a visitor's file on a form is held to. A file over
maxMb is named with its exact size and limit, and the answer carries
maxBytes and tooLarge (records API). Files count
toward your storage like any other upload, and deleting a record leaves its
files in your assets.
Endpoints
| Method | Path | Purpose |
|---|---|---|
GET | /api/collections | List collections |
GET | /api/collections/:id | One collection |
POST | /api/collections | Create |
PATCH | /api/collections/:id | Update name or slug |
DELETE | /api/collections/:id | Delete. Only the person or key that created the collection may: anyone else gets 401, whatever their role, and the console shows Delete to the creator only |
GET | /api/collections/:collectionId/versions | List versions |
GET | /api/collections/:collectionId/versions/:versionId | One version, with its fields |
POST | /api/collections/:collectionId/versions | Create a draft version |
PATCH | /api/collections/:collectionId/versions/:id | Edit a non-live version |
DELETE | /api/collections/:collectionId/versions/:id | Delete a version |
GET | /api/collections/chart | Record counts over time |
Reading, writing and deleting records is covered in the records API.
How forms use this
A form is a collection plus a published version plus a public endpoint. Every
submission becomes a record carrying collectionId, versionId, formId, and
the submitted data.
That is why a form cannot exist without a published version, and why changing a form's fields means publishing a new collection version.
The one difference: form submissions arrive through the public endpoint, which needs no token. Everything on this page does.
Next Steps
- Field types - what each type stores and checks.
- Records API - read and delete stored records.
- Forms - collect records from a public endpoint.