powered by

Model your data: entities, fields, relations

Create entities, add typed fields, set required, unique and indexed, and link records with relationships. Every change updates your REST API at once.

Last updated

Your data model is the set of entities and fields in your project. An entity is a table. A field is a typed column on it. When you create or change either one, Anythink changes the database and your REST API in the same step. There is no migration to write and no deploy to wait for.

Concept What it is Example
Entity A table of records, with its own REST API and permissions customers
Field One typed value on every record of an entity email, signed_up_at
Relationship A link from a field on one entity to records of another orders.customer points at customers

This page walks through the whole life of a data model: creating entities, adding fields, setting constraints, linking entities, changing things later, and the limits to design around.

Create an entity

Create one entity per kind of thing you store: customers, orders, blog_posts.

In the Anythink dashboard

  1. Go to Settings › Data Model.
  2. Select Add Entity. The Create New Entity drawer opens.
  3. Enter an Entity Name, for example customers.
  4. Leave the options at their defaults for now. They're explained below, and you can change them later.
  5. Select Create Entity.

With the CLI

bash
anythink entities create customers
text
Creating entity 'customers'...
✓ Entity customers created (id: 653).

Check what was created:

bash
anythink entities get customers

The output lists the entity's settings and its fields.

With an AI assistant (MCP)

text
Create an entity called customers.

The assistant uses the cli tool to run entities create customers and confirms with entities get customers.

Name rules

Rule Detail
Characters Lower-case letters, numbers and underscores. Start with a letter.
Case Anythink lower-cases the name and replaces any character that isn't a letter or number with an underscore, so Customer Orders becomes customer_orders.
Length 63 characters or fewer.
Reserved Names starting with anythink_, and the names of Anythink's built-in resources, are refused.
Unique Each name can be used once per project.
Permanent An entity can't be renamed. To change a name, create a new entity and move the records across.

Use plural, snake_case names. The name appears in your API paths (/entities/customers/items) and in permission names (customers:read), so it's worth choosing well.

What gets created

Creating an entity sets up three things at once:

  • A database table named after the entity, with an auto-incrementing id and created_at and updated_at timestamps that Anythink manages. These system fields are locked: you can't edit or delete them.
  • A REST API for the entity: list, get, create, update and delete endpoints, available as soon as the entity exists. See Call the instant REST API.
  • Four permissions: customers:read, customers:create, customers:update and customers:delete. Administrator roles get all four automatically. Every other role gets none, so grant them under Roles and permissions before your app's users can call the API.

Entity options

Option (dashboard) CLI What it does
Enable Row-Level Security --rls Records are only visible to users granted access. See Groups and row-level security.
Public --public The entity can be read without signing in. Only fields marked publicly searchable are exposed.
Lock New Records --lock-records Every new record is created locked. A locked record can't be changed or deleted through the API.
Lock Schema Dashboard only Nobody can add, change or delete the entity's fields, and the entity can't be deleted.
Add to Menu Dashboard only Adds the entity to your dashboard menu when you create it.

Add fields

Add one field per piece of information you want on each record. An entity with no fields beyond id and the timestamps can't hold much, so this is where the model takes shape.

In the Anythink dashboard

  1. Go to Settings › Data Model and select the entity.
  2. Select Add Field. The Create New Field drawer opens.
  3. Pick a field type, such as Small text or Integer.
  4. Enter a Name (for example email). Add a Label, Description and Default Value if you want them.
  5. Choose a display type and set any display options (see Display options).
  6. Tick any constraints you need (see Required, unique, indexed and name field).
  7. Select Create Field.

The field shows up on the entity straight away, and in the REST API.

With the CLI

bash
anythink fields add customers email --type varchar --unique --required
anythink fields add customers notes --type text
anythink fields add customers plan --type varchar --display select --options "Free,Pro,Team"
anythink fields add customers signed_up_at --type timestamp
text
✓ Field email (id: 3163) added to customers.

Leave out --display and the CLI picks the usual display type for the field type (the table below shows the default first). List a table's fields with anythink fields list customers, or inspect one with anythink fields get customers email.

With an AI assistant (MCP)

text
Add these fields to customers: email (unique, required), notes (long text), plan (a select with Free, Pro and Team) and signed_up_at (timestamp).

The assistant uses the cli tool to run one fields add per field.

Field names

Field names follow the entity rules, with two extra restrictions: you can't use id, locked, created_at or updated_at (or other names Anythink reserves for itself), and a name can't start with anythink. A name is permanent once the field exists, and so is its type.

A Label is the friendly name shown in the dashboard (up to 100 characters). A Description is a note for your team (up to 500 characters). Neither changes the API.

Field types

Choose the type by what the value is. The type decides how the value is stored, and which display types you can pick.

Type (dashboard) --type / API value Stored as Display types
Small text varchar Text (VARCHAR) input (default), select, entity-select
Large text text Text (TEXT) textarea (default), rich-text
Integer integer Whole number (INTEGER) input (default), select
Big Integer bigint Large whole number (BIGINT) input (default), select
Decimal decimal Exact decimal number (DECIMAL) input (default), select
Boolean boolean True or false (BOOLEAN). Defaults to false checkbox (default), radio
Date date Calendar date, no time (DATE) short-date (default), long-date
Timestamp timestamp Date and time with time zone (TIMESTAMPTZ) timestamp
JSON jsonb JSON document (JSONB) jsonb (JSON editor)
Geo geo Location, stored as JSON (JSONB) geo (map)
Select with Multiple ticked varchar[], integer[], decimal[] Array of values select
File Upload file Link to an uploaded file file
User user Link to a user in your project user
One-to-One, Many-to-One one-to-one, many-to-one Link to one record of another entity relationship
One-to-Many, Many-to-Many one-to-many, many-to-many Links to many records of another entity relationship
Dynamic Reference dynamic-reference Text reference to a record of any entity dynamic-reference

Choosing a type:

  • Money and measurements. Use decimal, not a float: it keeps exact values. For prices you can also store whole pence or cents in an integer or bigint.
  • Counts, ages and IDs. integer. Use bigint for very large numbers such as epoch timestamps.
  • Short strings you filter on. varchar with select for a fixed list of choices, such as a status.
  • Anything longer than a line. text, with rich-text if editors need Markdown.
  • When something happened. timestamp. Use date only when the time of day is meaningless, such as a birthday.
  • Free-form structure. jsonb, when the shape varies between records and you don't need to filter on its contents.

Types that point at other data (file, user, the four relationship types and dynamic-reference) are covered in Link entities with relationships and in Upload and manage files. For a longer description of each type, see Field types reference.

Display options

The display type controls how the field looks in the dashboard's forms and grids. It doesn't change the stored value or the REST API. Each display type has its own options, set in the Create New Field drawer or through the options object of the API.

Display type Options
input Placeholder, Addon before, Addon after (for example a currency symbol), Masked to hide the value as it is typed
select The list of choices (each a label and a value), Multiple, Placeholder, Addon before, Addon after
textarea Rows
rich-text Rows, Enable Markdown Support
file Allowed file types, Number of files allowed for upload, Public

Give a select field its choices in one go from the CLI. A plain list uses each word as both label and value. Use label=value to store something different from what people see:

bash
anythink fields add orders status --type varchar --display select --options "Pending=pending,Shipped=shipped,Delivered=delivered"

Tick Multiple (CLI: --multiple) to let one record hold several choices. Anythink then stores the field as an array (varchar[], integer[] or decimal[], matching the type you picked).

bash
anythink fields add customers interests --type varchar --display select --multiple --options "Running,Cycling,Rugby"

Required, unique, indexed and name field

These switches sit on every field. Some are about data quality, some about speed, and some about how a record is shown.

Switch (dashboard) CLI flag What it does
Required field --required The value can't be empty. The dashboard's record form won't submit without it.
Unique field --unique No two records can share a value. A duplicate write is refused with a 400.
Immutable field Dashboard and API Once a record is saved, updates leave this field's value as it was.
Indexed --indexed Adds a database index, so filtering and sorting on the field stays fast on large tables.
Name field --name-field Marks the field that identifies a record visually in the dashboard. It implies Searchable.
Searchable --searchable Includes the field in the entity's search, and makes it usable in API search queries.
Publicly Searchable --public Lets signed-out visitors search this field on a public entity. It needs Searchable, and the request is refused without it.

Things to know:

  • Choose Unique and Indexed when you create the field. Unique is applied to the database as the column is made, so decide it up front.
  • Unique and nulls. Unique compares values, so any number of records can leave an optional unique field empty.
  • Defaults fill old records. When you add a field with a default value to an entity that already has records, existing records get the default. Without one they get an empty value. Boolean fields default to false.
  • Required relationships. A required relationship field can't use Set null for its on-delete behaviour, since that would empty a required value.
  • Pick one name field per entity. Choose the field that makes a record recognisable at a glance: a title, a name or a reference.

Searchable fields feed Search records across your entities, which also covers public search.

A relationship is a field that points at records of another entity: an order belongs to a customer, a post has many tags. You create one by adding a field of a relationship type.

Type Meaning Example
many-to-one Many records here point at one record there Many orders belong to one customer
one-to-many One record here has many records there One customer has many orders
one-to-one Each record points at exactly one record there, and no two share it One user_profile per customer
many-to-many Records on both sides can have several partners posts and tags

Each relationship field asks for a target entity and an on-delete behaviour: what happens to a record when the record it points at is deleted. The choices are CASCADE (delete it too), SET NULL (clear the link), RESTRICT (refuse the delete) and SET DEFAULT. The CLI defaults to CASCADE.

bash
anythink fields add orders customer --type many-to-one --target customers --on-delete "SET NULL"

The REST API stores the id of the related record in the field, and can expand and filter on related records. The relationships page covers every type in depth, including how to read, write and filter linked records: Connect entities with relationships.

Edit fields and entities

You can change a data model whenever you like. The API updates as soon as you save.

Edit a field

In the Anythink dashboard

  1. Go to Settings › Data Model and select the entity.
  2. Select the field. Fields marked System can't be edited.
  3. Change what you need and select Update Field.

With the CLI

Edit fields in the Anythink dashboard, using the steps above.

With an AI assistant (MCP)

Edit fields in the Anythink dashboard, using the steps above.

What you can and can't change:

You can change You can't change
Label, description, default value Name
Display type (to one compatible with the field's type) and display options Field type
Select choices, Multiple A relationship's target entity
Required, searchable, publicly searchable System fields (id, created_at, updated_at)
Width (see Field order and display) Anything, while the entity's Lock Schema is on

Changing a display type, select choices or other display options never alters stored values. A record that holds a value no longer in the choices keeps it. To change a field's type, add a new field of the type you want and copy the values across (a workflow or a short script works).

Edit an entity

Select the entity in Settings › Data Model, then select Edit to change Enable Row-Level Security, Public, Lock New Records or Lock Schema. The name stays fixed. With the CLI:

bash
anythink entities update customers --rls true --public false --lock-records false

Turning on row-level security hides records that have no grants. Read Groups and row-level security before you switch it on for an entity that already holds data. Lock New Records affects only records created after you turn it on.

Delete an entity

Deleting an entity permanently removes the entity, every record in it, its search index, and its four permissions. Its API endpoints stop working at once and return 404.

In the Anythink dashboard

  1. Go to Settings › Data Model.
  2. Select the entity, then select Delete.
  3. Confirm Delete Entity.

With the CLI

bash
anythink entities delete temp_data --yes

An entity with Lock Schema on can't be deleted. Turn the option off first if you really mean to remove it.

With an AI assistant (MCP)

text
Delete the temp_data entity and everything in it.

Field order and display

Fields appear in the dashboard's record form and grid in the order you set. Drag them into the order you want.

In the Anythink dashboard

  1. Go to Settings › Data Model and select the entity.
  2. Drag a field by its handle to a new position. Locked and system fields have no handle.

The new order saves automatically. Each field also has a Width (from 1 to 1000, default 100) that sets how wide it appears in the dashboard.

With the CLI

There's no dedicated command, but the field-order endpoint is one call. Send each field's id and its new position:

bash
anythink fields list customers
anythink fetch /entities/customers/fields/reorder --method PUT \
  --body '[{"field_id": 3163, "sort_order": 1}, {"field_id": 3164, "sort_order": 2}]'

With an AI assistant (MCP)

text
On customers, put email first, then plan, then notes.

The assistant lists the field ids and calls the reorder endpoint through the cli tool.

Order and width are presentation only. They don't change the API response or the stored data. The REST API returns the same fields whatever order you pick.

Read the model from your app

Your app can read the model it sits on: an entity with its fields, how its fields and relationships are laid out, and the workflows a user can start from its records. All three calls need anythink_entities:read, and they only show fields your role is allowed to see.

Endpoint Returns
GET /entities/id/{id} One entity by its numeric id, with its fields. Same shape as GET /entities/{name}.
GET /entities/{name}/hierarchy A list of the entity's fields and relationships
GET /entities/{name}/workflows The enabled workflows whose Manual trigger includes this entity

In the Anythink dashboard

Settings › Data Model shows the same model. The record page lists the workflows you can run on a record in its Workflows section.

With the CLI

bash
anythink fetch /entities/id/365
anythink fetch /entities/orders/hierarchy
anythink fetch /entities/orders/workflows

The raw request:

http
GET /org/{project_id}/entities/orders/hierarchy

Each item in the hierarchy list has a name, a path, a type, is_system and a definition. The type is field for an ordinary field, or the relationship kind (one-to-many or many-to-one) for a link to another entity, which also carries target_entity. The definition is the field's full definition, including display_type, is_required and, for a relationship, the relationship details.

workflows returns each matching workflow's id, name, description, group, enabled and triggers. Read /workflows/{id} for its steps. See Triggers and scheduling.

An id or name that doesn't exist returns 404.

With an AI assistant (MCP)

text
Show me how the orders entity connects to other entities.

The assistant calls fetch /entities/orders/hierarchy through the cli tool.

Limits

Limit Value
Entity name 63 characters, unique in the project, can't start with anythink_
Field name 63 characters, unique on the entity, can't be id, locked, created_at or updated_at, can't start with anythink
Field label 100 characters
Field description 500 characters
Field width 1 to 1000
Renaming Entities and fields can't be renamed
Changing a field's type Not possible. Add a new field of the type you want and copy the values across
Deleting Permanent. Fields and entities have no undo
Locked entities Under Lock Schema no field can be added, changed or deleted, and the entity can't be deleted
Built-in fields id, created_at and updated_at exist on every entity and can't be edited or deleted

Next steps