---
title: "Model and records"
url: /model
---

# Model and records

> Each Customer's Things, with their Relationships, state, history, files and content, and the search, views and metrics rebuilt from them.

Model and records keeps each Customer's Things: their fields, [Relationships](/patterns/headless-saas.md), state, full history, files and content. Search, views and metrics are projections, rebuilt from the record and never written.

## Capability families
| Family | What it does |
| --- | --- |
| Things and fields | Each [Noun](/reference/platform.md#noun) as typed fields with keys, so a record answers at its id and at its `!#` key |
| Relationships | Links read from either side, with how many each side holds and what a delete does to the other side |
| State | Each [Thing](/reference/platform.md#thing)'s place in its lifecycle, kept on the record and moved only by its Verbs |
| [Provenance](/patterns/dataset-api.md#how-a-field-is-filled) | Who wrote each value and on what basis: Stated, Inferred or Observed; Observed wins for facts |
| History | Every change as an [Event](/reference/platform.md#event), a read of any record as it stood at any moment, and soft delete with restore |
| Customer fields and Nouns | Fields and Nouns a Customer adds in its own [Namespace](/reference/platform.md#namespace), inside the limits your file sets |
| Import, export and bulk | Records in and out in bulk, each row checked; a whole Namespace out in an open format |
| Files and documents | Files and media kept with their record; documents generated from records and a template |
| Authored content | Drafts, versions, review and publishing; editions and access tiers, the core of the Content pattern |
| Working together | Comments, mentions, assignment and presence on any record |
| Projections | Search by words and by meaning that respects permissions, views as data, metrics and roll-ups |

Each Customer's records live in its own Namespace: the unit of residency, backup, export and deletion.

## Lifecycles and states
| Thing | States | What moves it |
| --- | --- | --- |
| A record | `live`, `deleted`, `restored` | `DELETE` keeps it; `POST /{nouns}/{id}/restore` brings it back; only an erase, under its legal rule, removes it |
| A Thing's lifecycle | As the file declares it: `opened`, `qualified`, `won`, `lost` | Its moves, each guarded by its state and its Role |
| A content item | `drafted`, `reviewed`, `published`, `withdrawn` | Its author, its reviewer, its schedule; each published version is kept |
| An edition | `scheduled`, `sending`, `sent` | Its schedule; it reaches entitled members only, with a delivery state per member |
| A file | `uploading`, `stored`, `attached` | The upload, a scan, the record it attaches to |
| An import | `uploaded`, `checked`, then `committed` or `rejected` | Each row is checked first, and a rejected row carries its [Problem](/reference.md#errors) |
| An export | `requested`, `building`, `ready`, `expired` | The Customer, or its agent; the link expires, the export is kept |
| A projection | `building`, `current`, `behind` | The Events it reads; a reply says how far behind it is |

Every record move writes its Event: `created`, `updated`, `deleted` and `restored`, and each lifecycle move its own past form.

## What you declare, what the platform does
| You declare | The platform does |
| --- | --- |
| Nouns, fields, types and keys | Create, get, list, update, delete and restore on each Noun, in each Customer's Namespace, typed on every [Interface](/every-product.md) |
| Relationships, with `->` and `<-` | The read from either side: `GET /companies/{id}/deals` |
| A lifecycle, as moves | The state on the record, 409 `wrong_state` with `allowed` on a wrong move |
| A field with a `from` | The value from its [Source](/patterns/dataset-api.md#how-a-field-is-filled) or Verb, stamped with its Provenance |
| A `file` field | Upload, storage, a scan, renditions, and a link that respects permissions |
| Views and metrics | Each kept as data, rebuilt from the record, answered over every Interface |
| Nothing else | History, as-of reads, import, export, bulk, search, comments, mentions, assignment and presence |

### Example
A proposal kept with each Deal, a view of open Deals, and a metric of won value by month.

```ts title="definition.ts"
import { define } from 'apis.dev'

/** Deals for each Customer, kicked off when won. */
export default define({
  name: 'pipeline', domain: 'pipeline.apis.dev',
  …
  Company: { name: 'string', domain: 'url!#', deals: '<-Deal.company' },
  Deal: {
    title: 'string', amount: 'decimal(12,2)', company: '->Company.deals',
    proposal: 'file?',                                    // kept with the record
    stage: { open: [], qualify: 'opened', win: 'qualified', lose: ['opened', 'qualified'] },
  },
  views: { open: { Deal: { stage: ['opened', 'qualified'] }, sort: '-amount' } },
  metrics: { won: { sum: 'Deal.amount', where: { stage: 'won' }, by: 'month' } },
  offer: { Team: { month: 49, seats: 5, seat: 9 }, 'Deal.open': 0.001 },
})
```

The record as it stood at any moment is one read, at no charge.

```http title="Response"
HTTP/1.1 200 OK
X-Cost: price=0, currency="USD"
X-Request-Id: req_4b8e2a71c90d3f56e1a7

{
  "id": "deal_1",
  "title": "Pilot",
  "amount": "5000.00",
  "company": "company_1",
  "stage": "opened",
  "createdAt": "2026-10-24T09:10:00Z",
  "updatedAt": "2026-10-24T09:10:00Z",
  "asOf": "2026-10-24T09:15:00Z"
}
```

That is `GET /deals/deal_1?at=2026-10-24T09:15:00Z`, as `getDeal` over MCP with `at` and `pipeline deals get deal_1 --at` in the CLI.

## Contracts with the other subsystems
| Subsystem | What it gives this one | What this one gives back |
| --- | --- | --- |
| Definition and compile | The shape: Nouns, fields, keys, Relationships, lifecycles, renames | The live record each migration is checked against |
| Identity, access and policy | A mask per principal on every field and record | Records, state and Relationships, which the one decision reads |
| Data and Sources | Values from [Mappings](/patterns/dataset-api.md#how-a-field-is-filled) and [Integrations](/patterns/headless-saas.md#integrations), with their Provenance and licence terms | Fields to write back to a Customer's system; licence terms kept on each value, honoured on export |
| Runtime | The only writes, through one commit gate: the fact, its Event, its meter line and its audit entry together | The record a Verb reads, and the Events every projection and Watch is built on |
| Work | Case files, privilege classes, retention and legal hold | A hold that stops a delete and an erase; a class an ethical wall hides |
| Commerce | Access tiers as [Entitlements](/reference/platform.md#entitlement); a price per read | The read a [Meter](/reference/platform.md#meter) counts once |
| Interfaces and distribution | Every call that reads or writes | Schemas for OpenAPI, MCP and the SDK; a docs page per Noun; views and forms for the UI contracts |
| Trust and operations | Residency, backups, encryption | Each Namespace to export, restore or erase as one |

## What Customers and their agents meet
- **A member's day.** Create a record, relate it to another, search, move it on, delete one by mistake and restore it, over any Interface.
- **Nothing is lost.** Every record keeps its history. A read with `at` answers it as it stood, and the change feed reads every change in order.
- **Their own shape.** A Customer's admin adds a field or a Noun in their own Namespace, and it appears on their own Interfaces only.
- **Search that respects Roles.** A search, a view or a metric never shows what the member may not see. An empty result says why.
- **An agent at work.** An agent drafts a post, sends it for review, publishes it on approval, and reads each version back.
- **Nothing locked in.** Export answers the whole Namespace in an open format, files included, at any time.

---

Every read is rebuilt from one record that only Verbs write, so a search, a view and a reply always agree.