---
title: "Relationships and the graph"
description: "Pull related content back with a request using include, expand and depth"
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.minima.ltd/llms.txt
> Use this file to discover all available pages before exploring further.

# Relationships and the graph

Minima models your content as a knowledge graph: entities connected to other entities by named relationships. A product has a manufacturer, an article mentions a person, a person works at a company.

By default a list or read endpoint gives you records and nothing else. The `include` parameter tells it to also resolve what those records are connected to, so you can render a page from one request instead of a waterfall of them.

## Two projections

There are two ways to get the connected data back, and they are mutually exclusive.

```bash
?include=graph
```

`include=graph` adds a top-level `graph` object to the response, keyed by entity ID. Every connected entity appears once, no matter how many records point at it. Look up what you need by ID as you render.

```json
{
  "data": [ ... ],
  "pagination": { ... },
  "graph": {
"ent_manufacturer1": { "id": "ent_manufacturer1", "name": "Acme", "type": "Company", "..." : "..." },
"ent_person7": { "id": "ent_person7", "name": "Ada Lovelace", "type": "Person", "..." : "..." }
  }
}
```

```bash
?include=tree
```

`include=tree` adds a top-level `tree` array instead. The same entities are resolved, but nested — each entity carries its related entities inline, and those carry theirs, down to the depth you ask for.

```json
{
  "data": [ ... ],
  "pagination": { ... },
  "tree": [
{
  "id": "ent_product1",
  "name": "Widget",
  "relationships": {
    "manufacturer": { "id": "ent_manufacturer1", "name": "Acme", "edge": {} }
  }
}
  ]
}
```

Reach for `graph` when you are rendering a list and want to look connections up cheaply. Reach for `tree` when you are rendering one thing and want its neighbourhood in the shape you will draw it.

Both projections return the same node shape: `id`, `name`, `type`, `slug`, `status`, `attributes`, `externalUrl`, `publishedAt`, `heroImage`, `permalink`, `categories` and `relationships`.

## The edge namespace

A relationship can carry its own data — a job title on a *works at*, a role on a *contributed to*. That data belongs to the connection, not to either entity, so it lives under a reserved `edge` key on the related entity:

```json
{
  "id": "ent_person7",
  "name": "Ada Lovelace",
  "edge": { "role": "Lead engineer", "since": "2021" }
}
```

`edge` is always present. It is `{}` when the relationship carries nothing, so you never have to check whether the key exists before reading it.

## Depth

```bash
?include=tree&depth=2
```

`depth` controls how many hops out the tree resolves. The default is `1` — direct relationships only. The maximum is `3`, and values above it are clamped rather than rejected.

Depth applies to `include=tree` only. `include=graph` is bounded by `expand` instead.

## Expand

```bash
?include=graph&expand=manufacturer&expand=manufacturer.country
```

`expand` names which relationship branches to follow. Pass it once per path — it is a repeatable parameter, not a comma-separated list and not `expand[]`.

Dots walk the graph. `manufacturer` pulls in the manufacturer; `manufacturer.country` pulls in that manufacturer's country too.

Naming branches matters because a graph has no natural edge. Without `expand`, a projection either stops at the first hop or drags in everything reachable. `expand` lets you say exactly which paths your page actually renders.

## Articles are a special case

An article does not name its related entities through a relationship. It **mentions** them — you link an entity from the article body, and Minima records the mention.

That means you never write `expand=mentions`. Mentioned entities are collected for you whenever you ask for a projection. What `expand` names on an article request is a relationship on the *mentioned* entities, one level further out.

Take an article about a record that mentions an album, where the album has a `byArtist` relationship. `include=tree` resolves one hop by default, so the mentioned album arrives with its artist already attached:

```bash
curl -G "https://api.minima.ltd/api/v1/public/sites/site_abc123/articles/slug/mentioned-music" \
  --data-urlencode "include=tree" \
  -H "x-api-key: pub_your_key_here"
```

```json
{
  "id": "art_abc123",
  "headline": "Mentioned music",
  "tree": [
{
  "id": "ent_album1",
  "name": "Mentioned Album",
  "type": "MusicAlbum",
  "relationships": {
    "byArtist": { "id": "ent_artist1", "name": "Mentioned Artist", "edge": {} }
  }
}
  ]
}
```

For the flat projection, name the branch you want from the mentioned entity:

```bash
curl -G "https://api.minima.ltd/api/v1/public/sites/site_abc123/articles/slug/mentioned-music" \
  --data-urlencode "include=graph" \
  --data-urlencode "expand=byArtist" \
  -H "x-api-key: pub_your_key_here"
```

One request, one round trip, and every entity you need to render the page is in `graph` under its ID.

> **Note**
>
> Articles are readable by ID at `/articles/{id}` and by slug at `/articles/slug/{slug}` — the slug sits under its own path segment, so there is no `/articles/{slug}`.
>
> The slug form resolves through the article's canonical permalink on that site, not through the slug column alone. An article with no permalink is reachable by ID only, and the slug lookup returns `404`.

Source: https://docs.minima.ltd/developers/relationships/index.mdx
