Expanding responses
Embed related sub-resources in a single response by passing the expand query parameter.
By default, list and retrieve responses return the smallest useful representation of each resource. When the related data is small and the caller usually needs it on the next render, pass the expand query parameter to embed named sub-resources directly in the response — one round trip instead of two.
Syntax
expand accepts a comma-separated list of expandable field names:
GET /v1/organizations?expand=workspaces
GET /v1/organizations?expand=workspaces,billingWhitespace around each name is trimmed and duplicates are ignored. The set of expandable fields is per-endpoint — each operation lists what it accepts in its OpenAPI parameter docs and on its reference page. Passing an unknown field returns 400 VALIDATION:
{
"error": {
"code": "VALIDATION",
"message": "Unknown expand field: \"foo\". Available: workspaces."
}
}Example
GET /v1/organizations returns the list of organizations the caller belongs to, with the user's role and computed org permission set:
{
"data": [
{
"id": "org_01HJ…",
"slug": "acme",
"name": "Acme",
"logo": null,
"role": "admin",
"permissions": ["org:members:read", "org:members:write", "..."]
}
],
"nextPageUrl": null,
"previousPageUrl": null
}Pass ?expand=workspaces to embed each organization's workspaces in the same response, with the user's resolved per-workspace role and permission set:
{
"data": [
{
"id": "org_01HJ…",
"slug": "acme",
"name": "Acme",
"logo": null,
"role": "admin",
"permissions": ["org:members:read", "..."],
"workspaces": [
{
"id": "wsp_01HJ…",
"slug": "main",
"name": "Main",
"image": null,
"role": "admin",
"implicit": true,
"permissions": ["workspace:products:read", "workspace:products:write", "..."]
}
]
}
],
"nextPageUrl": null,
"previousPageUrl": null
}In the typed SDK, expand accepts the same string and the response type widens to include the embedded fields:
import { listOrganizations } from "@mercel/sdk";
const { data } = await listOrganizations({
client,
query: { expand: "workspaces" },
});
for (const org of data.data) {
for (const workspace of org.workspaces ?? []) {
// …
}
}When to expand
Expand when the next thing the caller will do is iterate the embedded collection. Two common cases on Mercel:
- Mobile app cold start issues
GET /v1/meandGET /v1/organizations?expand=workspacesin parallel to hydrate the user identity and the permission cache used by every gated screen — one network round trip instead of1 + N. - Permission-gated dashboards that render an org switcher with per-workspace role badges read the full tree in one call.
If the embedded data isn't always needed, leave expand off — the default response is leaner.
Limitations
- One level of nesting.
expand=workspacesis valid;expand=workspaces.productsis not. Resources reached through two hops are fetched via a follow-up request. - Per-endpoint allowlist. Each operation declares the fields it accepts. Unknown fields return
400 VALIDATION. - Pagination is unchanged by expand. Pass-through parameters (
limit, cursors) behave the same whether or not sub-resources are embedded.