# The ontology model

> Objects, links, and actions — the three primitives every Aerandil surface is built from.

Everything in Aerandil is expressed with three primitives. Learn these and the REST API, the MCP tools, and the SDKs all read the same way.

## Objects

An **object** is a typed, versioned record — a `booking`, a `folio`, a `rate_plan`, a `guest_profile`. Every object has:

- a **type** drawn from the ontology (the hospitality domain lives in `aerandil-schema`);
- a stable **id**;
- a monotonic **`version`** that increments on every change;
- a **tenant** it belongs to (Aerandil is multi-tenant end to end).

Objects are never hard-deleted — they are **soft-deleted** (marked, not removed) so history stays intact.

## Links

A **link** is a typed, directional relationship between two objects — a `booking` _stays in_ a `room`, a `payment` _settles_ a `folio`. Links are first-class and typed by the ontology, not foreign keys you assemble by hand.

## Actions

An **action** is the _only_ way state changes. Rather than `PUT`-ing arbitrary fields, you **apply** a named, validated action — `apply_payment`, `assemble_package_sale`, `assign_operator_to_venue` — and Aerandil validates it, mutates the affected objects and links atomically, and appends an immutable **event** describing what happened.

This is the core idea: **reads are open, writes are actions.** Every mutation is a named verb with a schema, an authorization scope, and an audit trail.

## The ontology, live

This is not an illustration — the graph below is generated from the kernel’s schema registry at build time, so it is exactly the ontology the API, the MCP tools, and the SDKs speak. Pick a domain, then click any object type to see its properties and the actions that can change it, or any arrow to see the link’s cardinality.

## Concurrency and idempotency

Because objects are versioned, writes are safe under contention:

- **Versions** — every read returns the object’s `version` as a strong `ETag`. An action reads its target’s current state when it runs, and a change that no longer fits is refused with `409` rather than silently clobbering a concurrent one.
- **Idempotency** — send an `Idempotency-Key` on a create/apply and a retry returns the original result instead of duplicating the effect.

## Where to go next

- [Quickstart](/guides/quickstart/) — apply your first action end to end.
- [Authentication](/guides/authentication/) — OAuth 2.1 and action scopes.
- [API reference](/api/) — every object type, link, and action in full.

---

Source: https://developers.aerandil.com/guides/ontology-model/
