Scope Additional & Related Collections
Build a Multi-Tenant App with Scopes scoped a single orders collection with down inheritance. Real apps scope many collections — and each one decides its own scope field name and inheritance behavior. This tutorial scopes a second collection with a different field name and exact inheritance, then scopes a related child collection so a nested create carries the parent’s scope automatically. See Scopes for the full option reference.
Concepts
| Concept | Description |
|---|---|
Per-collection field_name | The scope column can be named anything — it does not have to be resource_uri |
Per-collection inheritance_mode | Each collection chooses down (roll up descendants) or exact (this scope only) |
| Nested scope propagation | On an inline O2M create, the parent’s scope is injected into every child record |
Scope a second collection with a custom field name
A scope-enabled collection just needs a string column to hold the URI — you choose its name in the config. Create a customers collection whose scope column is tenant_uri (not the default resource_uri):
| Field | Type | Notes |
|---|---|---|
name | string | required |
tenant_uri | string | the scope field — readonly; filled in by the scope system |
Then on /scopes → Collection Config, add a config that points at it and uses exact inheritance:
- Collection:
customers - Field Name:
tenant_uri - Missing URI Mode:
strict - Inheritance Mode:
exact
See how exact differs from down
Seed one customer at the Sales department and one at the North Region team beneath it. Now read customers at the Sales scope — with exact, you get only the row tagged exactly at Sales:
# customers uses exact → Sales scope returns ONLY the Sales-level customer
curl https://your-domain.com/api/items/customers \
-H "Authorization: Bearer <token>" \
-H "X-Resource-Uri: /<tenantTypeId>:<acmeId>/<deptTypeId>:<salesId>"
# → [{ "name": "Sales-level Customer" }]Compare this with orders (which uses down) read at the same scope — that one rolls up every descendant:
# orders uses down → Sales scope returns North + South Region orders too
curl https://your-domain.com/api/items/orders \
-H "Authorization: Bearer <token>" \
-H "X-Resource-Uri: /<tenantTypeId>:<acmeId>/<deptTypeId>:<salesId>"Same scope, two collections, two behaviors — each driven by its own config.
Use down for roll-up views (a manager seeing everything beneath them) and exact when a record belongs to one precise scope and should never leak upward or downward.
Scope a related child collection
Child records should live in the same scope as their parent. Create an order_lines collection (line items belonging to an order) with its own resource_uri column, relate it to orders (M2O order → orders, exposed as an O2M lines on the parent), then scope it:
- Collection:
order_lines - Field Name:
resource_uri - Missing URI Mode:
strict - Inheritance Mode:
down
Create nested records — scope propagates automatically
Create an order with its line items inline, sending the scope once on the request. The scope system injects the parent’s URI into the order and into every child line:
curl -X POST https://your-domain.com/api/items/orders \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-H "X-Resource-Uri: /<...>/<teamTypeId>:<northRegionId>" \
-d '{
"customer_name": "Acme North — Order with lines",
"total": 250,
"lines": { "create": [
{ "product": "Widget A", "qty": 2 },
{ "product": "Widget B", "qty": 1 }
]}
}'Read the lines back at that scope and both carry the North Region URI — you never set it on the children:
[
{ "product": "Widget A", "qty": 2, "resource_uri": "/.../<teamTypeId>:<northRegionId>" },
{ "product": "Widget B", "qty": 1, "resource_uri": "/.../<teamTypeId>:<northRegionId>" }
]Per-collection behavior, side by side
| Collection | Scope field | Inheritance | Read at Sales returns |
|---|---|---|---|
orders | resource_uri | down | Sales + North + South Region orders |
customers | tenant_uri | exact | only customers tagged exactly at Sales |
order_lines | resource_uri | down | lines for all orders beneath Sales |
Next Steps
- Repeat the Collection Config step for every collection that holds tenant data — pick
downorexactper collection. - Restrict who can read each collection with Scope-Aware Roles & Access Control.
- Set Missing URI Mode to
rejecton any collection that must never be queried without a scope.