Skip to content

Collections & Fields Management

Overview

Collections are database tables (or virtual folder groups). Fields are their columns. Both are managed at runtime — you can create, modify, and delete schema objects without code changes or restarts.

  • CollectionsService (src/services/collections.ts) manages table creation and metadata.
  • FieldsService (src/services/fields.ts) manages column creation and Directus-compatible metadata.

Collections

Data Model

Table: odp_collections (metadata only — the actual table is created in the DB)

ColumnTypeDescription
collectionvarcharCollection name (= table name)
iconvarcharUI icon
notetextDescription shown in app
display_templatevarcharTemplate string for item display
hiddenbooleanHidden from app panel
singletonbooleanOnly one item exists
translationsjsoni18n translations for name/description
archive_fieldvarcharField used for soft delete archiving
archive_app_filterbooleanShow archive filter in app
archive_valuevarcharValue meaning "archived"
unarchive_valuevarcharValue meaning "active"
sort_fieldvarcharField for manual drag-to-sort
accountabilityvarcharAudit log mode: all, activity, null
item_duplication_fieldsjsonFields to copy when duplicating items
groupvarcharParent folder collection name
collapsevarcharUI collapse state
sortintegerSort order in sidebar
versioningbooleanEnable content versioning
versioning_delta_optionsjsonVersioning configuration

Collection Endpoints

POST /collections

Create a new collection. Admin only.

Request Body

json
{
  "collection": "articles",
  "meta": {
    "icon": "article",
    "note": "Blog articles",
    "singleton": false,
    "sort_field": "sort"
  },
  "fields": [
    {
      "field": "id",
      "type": "uuid",
      "meta": { "hidden": true, "readonly": true },
      "schema": { "is_primary_key": true, "has_auto_increment": false }
    },
    {
      "field": "title",
      "type": "string",
      "meta": { "interface": "input", "required": true }
    },
    {
      "field": "status",
      "type": "string",
      "meta": {
        "interface": "select-dropdown",
        "options": { "choices": [
          { "text": "Draft", "value": "draft" },
          { "text": "Published", "value": "published" }
        ]}
      },
      "schema": { "default_value": "draft" }
    }
  ],
  "schema": { "name": "articles" }
}
PropertyDescription
collectionTable name (snake_case, no spaces)
metaVisual/UI configuration
fieldsInitial fields to create (array)
schema.nameDB table name (usually same as collection)
folder: trueCreate a virtual folder (no DB table)

Response 200 — Returns the full collection object.


GET /collections

List all collections.

Auth required: App access

Returns collections the user has at least read permission on (or all for admins). Response uses Directus-compatible format.


GET /collections/:collection

Read a single collection definition.

Auth required: App access

Response 200

json
{
  "data": {
    "collection": "articles",
    "meta": {
      "icon": "article",
      "singleton": false,
      "sort_field": "sort"
    },
    "schema": {
      "name": "articles"
    }
  }
}

PATCH /collections/:collection

Update collection metadata or schema. Admin only.

Request Body

json
{
  "meta": {
    "note": "Updated description",
    "hidden": false
  }
}

DELETE /collections/:collection

Delete the collection and its table. Admin only.

Response 204

This drops the database table and removes all metadata, fields, and permissions for this collection.


Fields

Data Model

Fields have two components:

  • schema — the actual DB column definition (type, nullability, default, etc.)
  • meta — UI/display configuration stored in odp_fields

Table: odp_fields (meta only — schema is read from DB information_schema)

ColumnTypeDescription
idintegerPrimary key
collectionvarcharCollection name
fieldvarcharColumn name
specialjsonSpecial handling (e.g., uuid, cast-boolean)
interfacevarcharUI interface component
optionsjsonInterface-specific options
displayvarcharDisplay component
display_optionsjsonDisplay component options
readonlybooleanRead-only in app
hiddenbooleanHidden in app
sortintegerField order in app
widthvarcharColumn width: half, full, fill
translationsjsoni18n field labels
notetextHelp text
conditionsjsonConditional visibility rules
requiredbooleanRequired validation
groupvarcharField group/panel name
validationjsonCustom validation rules
validation_messagetextError message for validation

Field Endpoints

POST /fields/:collection

Create a new field. Admin only.

Request Body

json
{
  "field": "published_at",
  "type": "timestamp",
  "meta": {
    "interface": "datetime",
    "display": "datetime",
    "readonly": false,
    "hidden": false,
    "note": "When this article was published"
  },
  "schema": {
    "is_nullable": true,
    "default_value": null
  }
}

Field Types

TypeDB ColumnNotes
stringVARCHARConfigurable length
textTEXTLong text
integerINTEGER
bigIntegerBIGINT
floatFLOAT
decimalDECIMAL
booleanBOOLEAN
dateDATE
timeTIME
timestampTIMESTAMPAuto-converts to ISO 8601
dateTimeDATETIME
uuidUUID / CHAR(36)
jsonJSON/TEXTStored as JSON
csvVARCHARComma-separated values
hashVARCHARStored as hash
alias(none)Virtual field (no DB column)

Response 200 — Returns the field in Directus-compatible format.


GET /fields

Read all fields across all collections.

Auth required: App access


GET /fields/:collection

Read all fields for a specific collection.

Auth required: App access

Response 200

json
{
  "data": [
    {
      "collection": "articles",
      "field": "id",
      "type": "uuid",
      "meta": { "hidden": true, "readonly": true },
      "schema": { "is_primary_key": true, "is_nullable": false }
    },
    {
      "collection": "articles",
      "field": "title",
      "type": "string",
      "meta": { "interface": "input", "required": true },
      "schema": { "max_length": 255, "is_nullable": false }
    }
  ]
}

GET /fields/:collection/:field

Read a single field.

Auth required: App access


PATCH /fields/:collection/:field

Update a field's type, schema, or meta. Admin only.

Request Body

json
{
  "type": "text",
  "meta": {
    "interface": "input-rich-text-html",
    "note": "Rich text content"
  },
  "schema": {
    "is_nullable": true
  }
}

All three top-level keys (type, meta, schema) are optional.


DELETE /fields/:collection/:field

Delete a field and its column. Admin only.

Response 204

Drops the database column and removes meta row.


Business Logic Notes

  • System collections (prefixed with odp_) are read-only for non-admin users. Admins can read schema but cannot delete system collections via the API.
  • Schema caching: The SchemaService caches the schema overview. Changes via these endpoints invalidate the cache automatically.
  • Directus compatibility: Field and collection responses are formatted via toDirectusFieldFormat() and toDirectusCollectionFormat() utilities for backward compatibility with Directus SDK clients.
  • Folder collections: Created with folder: true — no database table is created. Used for organizing collections in the sidebar.

ODP Internal API Documentation