Skip to content

Relations

Relations define how resources reference each other. A relation field creates a foreign key link from one resource to another, enabling you to model associations like "a post belongs to a user" or "a student enrolls in many courses."

Defining a Relation

Add a field with type: "relation" and include a relations object specifying the target resource, the target field, and the relation type:

{
  "name": "author_id",
  "type": "relation",
  "relations": {
    "resource": "users",
    "field": "id",
    "type": "many-to-one"
  }
}

Relations Object

Property Type Description
resource string Name of the related resource (required)
field string Field on the related resource to join on
type string One of the four relation types listed below

Relation Types

One-to-One

Each record in the source resource maps to exactly one record in the target resource, and vice versa.

{
  "name": "profile_id",
  "type": "relation",
  "relations": { "resource": "profiles", "field": "id", "type": "one-to-one" }
}

Use case: a users resource has one profiles record.

One-to-Many

A single record in the source resource can be referenced by many records in the target resource. This is defined on the "one" side.

{
  "name": "category_id",
  "type": "relation",
  "relations": {
    "resource": "categories",
    "field": "id",
    "type": "one-to-many"
  }
}

Use case: a categories resource has many products.

Many-to-One

Many records in the source resource point to a single record in the target resource. This is the inverse of one-to-many and is the most common relation type.

{
  "name": "author_id",
  "type": "relation",
  "relations": { "resource": "users", "field": "id", "type": "many-to-one" }
}

Use case: many posts belong to one users record.

Many-to-Many

Records on both sides can reference multiple records on the other side. Snaapi manages the join internally.

{
  "name": "tag_ids",
  "type": "relation",
  "relations": { "resource": "tags", "field": "id", "type": "many-to-many" }
}

Use case: posts can have many tags, and each tags record can appear on many posts.

Query Behavior

When you read a resource that contains relation fields, Snaapi resolves the relations automatically. The query response includes the related data based on the relation type and the permissions of the requesting role.

  • Filtering — You can filter by relation fields using the standard filter operators (e.g., author_id eq <uuid>).
  • Sorting — If the relation field is marked sortable, results can be ordered by the foreign key value.
  • Permissions — Relation fields are subject to the same field-level permission rules as any other field. A role must have access to the relation field to see or filter by it.
  • Existence checks — Use the exists / not_exists filter operators to query based on whether a related record is present.