Appearance
Relations (Eager Loading)
Load related entities alongside the main resource using the with query parameter.
Syntax
?with=relation1,relation2Nested Relations
Use dot notation to load nested relations:
?with=categories.translations
?with=categories.articles.translationsSelf-Relations (Recursive)
For tree structures (e.g., categories with children), use the * wildcard to load all levels:
?with=children* # Load all descendant levels
?with=children*.translations # Load all levels with their translationsMultiple Relations
Combine relations with commas:
?with=translations,categories.translations,vendor,imagesAvailable Relations
Each endpoint's tag description lists its supported relations. Requesting an unsupported relation is silently ignored.
Scope-Based Filtering
Scope-based relation filtering is opt-in per controller — it only applies where rest_policies.php declares a relations allow-list for that controller. Today that's Customer and Line only. For every other endpoint, no allow-list is defined, so RelationFilterMiddleware does not filter at all: any relation the endpoint supports (per its tag description / x-relations) is available regardless of scope.
Where a controller does declare an allow-list, the available set depends on your authentication scope:
| Scope | Behavior |
|---|---|
| Public | Only public-safe relations are available |
| Customer | Public relations + customer-specific relations |
| Backend | All relations available |
If you request a relation that isn't allowed for your scope, it is silently stripped from the response (no error returned). See the REST Middleware & RBAC guide for the full mechanism and the current allow-lists.
This enforcement is per endpoint, not per entity. Relation loading recurses across entity boundaries, so denying a relation on one controller does not deny that data platform-wide. If the related entity is itself exposed by another guest-readable endpoint — or reachable through a relation declared on one — and that other endpoint has no relations allow-list of its own, the denied data is still reachable by nesting through it.
Constrain Parameter
By default, relations inherit the parent query's filters where applicable. To disable this:
?with=categories&constrain=falseDiscovering Relations from the OpenAPI Spec
Each resource's OpenAPI tag includes a vendor extension x-relations that lists all available relations with their cardinality type:
| Cardinality | Meaning |
|---|---|
belongs_to | The entity holds a foreign key to the related entity (e.g., product belongs to vendor) |
one_to_many | The related entity holds a foreign key back to this entity (e.g., product has many images) |
many_to_many | A pivot table connects the two entities (e.g., product has many categories) |
Example x-relations excerpt from a tag definition:
yaml
x-relations:
translations:
type: one_to_many
categories:
type: many_to_many
vendor:
type: belongs_to
images:
type: one_to_manyUse these vendor extensions to programmatically discover which relations are available for each resource and understand their cardinality without trial and error.