Spaces API
Spaces are the primary workspace boundary for catalog, quality, governance, collaboration, and integration resources.
All endpoints below use the public API base path:
/api/v1.0
Scope And Access
Most space-scoped product APIs use a {slug} path parameter. The space resolver accepts either a space slug or a UUID string for many routes, but client code should prefer stable slugs in URLs.
Space access is enforced by authorize_space_only and get_current_space_context. Access succeeds when the authenticated user is a superadmin, has a direct UserSpaceRole, or has access through the parent organization where the route uses the DB-backed space access check. JWT-backed requests can also use embedded space grants.
GET /spaces/mine is more specific: for non-superadmins it currently lists direct space memberships from UserSpaceRole, while superadmins see every space.
Endpoint Overview
| Method | Endpoint | Description |
|---|---|---|
GET | /spaces/mine | List spaces available in the space selector. |
POST | /spaces | Create a space. Superadmin only. |
DELETE | /spaces/{space_id} | Delete a space and its contents. Superadmin only. |
GET | /spaces/{slug}/members | List direct space members. |
POST | /spaces/{slug}/members | Add an existing user to the space by email. |
PATCH | /spaces/{slug}/members/{user_id} | Update a member's platform role. |
DELETE | /spaces/{slug}/members/{user_id} | Remove a direct space member. |
PATCH | /spaces/{slug}/default-workflows | Set the default request workflow. Superadmin only. |
GET | /spaces/{slug}/my-role | Return the current user's direct platform role in the space. |
GET | /spaces/{slug}/my-governance-roles | Return product governance roles held by the current user. |
GET | /spaces/{slug}/my-permissions | Return effective resource actions for the current user. |
GET | /spaces/{slug}/attachments | List unified attachments across the space. |
The current /spaces router does not expose a public GET /spaces/{slug} detail endpoint or a general PATCH /spaces/{slug} update endpoint. Global list/update/settings operations are handled by the adjacent admin and organization APIs described in Adjacent Space APIs.
Space Object
Space responses use the platform SpaceResponse shape:
{
"id": "64bcfa65-2e1f-4c97-9a5f-c582a0b26d03",
"name": "Finance Data",
"slug": "finance-data",
"created_at": "2026-06-29T08:30:00Z",
"default_governance_workflow_id": "4f83b770-3b7a-40d5-8587-aa30a5c803ac",
"organization_id": "94a6c620-942f-4b6e-8b55-f613c8859544"
}
There is no description field on this response in the current schema.
List My Spaces
GET /api/v1.0/spaces/mine
Returns an array of spaces for the current user. The frontend SpaceProvider uses this endpoint to populate and persist the active space selection.
[
{
"id": "64bcfa65-2e1f-4c97-9a5f-c582a0b26d03",
"name": "Finance Data",
"slug": "finance-data",
"created_at": "2026-06-29T08:30:00Z",
"default_governance_workflow_id": null,
"organization_id": null
}
]
For non-superadmins, the list is based on direct space memberships. Use the Organizations API when you need organization membership, organization space assignment, or organization-level rollups.
Create Space
POST /api/v1.0/spaces
Requires superadmin access and enforces the catalog.max_spaces tier limit.
{
"name": "Finance Data",
"slug": "finance-data"
}
The service rejects duplicate slugs. After the row is created, default catalog metadata and document structure defaults are seeded for the space.
The same superadmin creation workflow is also exposed through POST /api/v1.0/admin/spaces.
Delete Space
DELETE /api/v1.0/spaces/{space_id}
Requires superadmin access. The path parameter is the space UUID, not the slug.
Deletion walks the foreign-key graph for space-owned resources, removes reachable child records first, and then deletes the space row.
{
"message": "Space 'Finance Data' deleted successfully"
}
Because this removes the space and its contents, integrations should treat it as a destructive administrative operation.
Members
Member responses include the user's ID, email, display name, current platform role, and optional avatar color:
{
"id": "1b8f697c-14d1-442a-a80f-90434255d941",
"email": "ana@example.com",
"full_name": "Ana Smith",
"role": "Admin",
"avatar_color": "#4f46e5"
}
Platform roles are stored by name. Seeded roles include Admin, Editor, Viewer, Data Governance Professional, Developer, and General User. role_name values must match a stored PlatformRole.name.
List Members
GET /api/v1.0/spaces/{slug}/members
Returns direct UserSpaceRole members for the space. Organization-level members are managed separately and are not returned as direct space members by this endpoint.
[
{
"id": "1b8f697c-14d1-442a-a80f-90434255d941",
"email": "ana@example.com",
"full_name": "Ana Smith",
"role": "Admin",
"avatar_color": "#4f46e5"
}
]
Add Member
POST /api/v1.0/spaces/{slug}/members
Adds an existing user by email. The caller must be a superadmin or a direct space member with the Admin role.
{
"email": "new.member@example.com",
"role_name": "Viewer"
}
Errors include unknown space, unknown user, unknown role, duplicate membership, or insufficient permission.
Update Member Role
PATCH /api/v1.0/spaces/{slug}/members/{user_id}
{
"role_name": "Editor"
}
The route requires space access. The service validates that the target user is a direct member and that the requested role exists, updates the UserSpaceRole, invalidates role/permission caches, and emits a space member audit event when an actor is available.
Remove Member
DELETE /api/v1.0/spaces/{slug}/members/{user_id}
The route requires space access. The service validates that the target user is a direct member, removes the UserSpaceRole, bumps the user's session version, invalidates role/permission caches, and emits a member removal audit event when an actor is available.
Response:
{
"message": "Member removed successfully"
}
Default Workflows
PATCH /api/v1.0/spaces/{slug}/default-workflows
Sets the default request workflow used for general requests such as access, recertification, or change workflows. The current route requires superadmin access.
{
"default_request_workflow_id": "10cd0804-f63b-4f9e-a890-f00118fe5e57"
}
Send null to clear the default request workflow.
{
"default_request_workflow_id": "10cd0804-f63b-4f9e-a890-f00118fe5e57",
"default_governance_workflow_id": "4f83b770-3b7a-40d5-8587-aa30a5c803ac"
}
Default governance workflow configuration is updated through the admin space update endpoint, not this route.
Viewer Context
The frontend ViewerContext and permission hooks use these endpoints to render space-aware actions.
My Role
GET /api/v1.0/spaces/{slug}/my-role
Returns the current user's direct platform role in the space. Superadmins receive Admin. Users who only have inherited organization access can receive null here.
{
"role": "Editor"
}
My Governance Roles
GET /api/v1.0/spaces/{slug}/my-governance-roles
Returns product-level governance roles held by the current user in the space.
[
{
"id": "2f69ad79-caf3-43df-9c65-aa9bba46dcfb",
"product_id": "8da2bc25-6358-4be6-af9a-5e545f00517f",
"product_name": "Customer Risk Scores",
"role_type": "owner"
}
]
My Permissions
GET /api/v1.0/spaces/{slug}/my-permissions
Returns the current user's effective allowed actions by resource type. Only resource types with at least one allowed action are included.
{
"permissions": {
"product": ["view", "create", "edit"],
"ticket": ["view"],
"request": ["view", "approve"]
}
}
Permissions are calculated from configurable permission rules first, then baseline RBAC behavior. The frontend usePermissions hook caches this map per active space and exposes a synchronous can(action, resourceType) helper.
Space Attachments Index
GET /api/v1.0/spaces/{slug}/attachments?entity_type=product&limit=50
Lists unified attachments across the space. This is an inventory/read endpoint; upload, download, and delete actions remain on each feature's attachment routes.
Query parameters:
| Parameter | Type | Notes |
|---|---|---|
entity_type | string | Optional filter such as product, meeting, ticket, document_page, analysis, repository, or another registered attachment entity type. |
limit | integer | Defaults to 50; capped at 100 by the route. |
Response:
{
"attachments": [
{
"id": "1d5e36d0-0fc3-42a2-aa13-43c9d0924e67",
"entity_type": "product",
"file_name": "dq-runbook.md",
"file_type": "text/markdown",
"file_size_bytes": 2048,
"storage_uri": "uploads/products/...",
"storage_backend": "filesystem",
"markdown_snippet": null,
"created_at": "2026-06-29T08:35:00Z",
"product_id": "8da2bc25-6358-4be6-af9a-5e545f00517f",
"product_name": "Customer Risk Scores",
"uploader": {
"id": "1b8f697c-14d1-442a-a80f-90434255d941",
"display_name": "Ana Smith",
"email": "ana@example.com"
}
}
],
"total": 1,
"limit": 50
}
Adjacent Space APIs
Some space lifecycle and organization operations intentionally live outside the /spaces router:
| API | Purpose |
|---|---|
GET /api/v1.0/admin/spaces | Superadmin list of all spaces. |
POST /api/v1.0/admin/spaces | Superadmin space creation. |
PATCH /api/v1.0/admin/spaces/{space_id} | Superadmin update of name, slug, and default_governance_workflow_id. |
PATCH /api/v1.0/admin/spaces/{space_id}/settings | Superadmin shallow merge of space_settings. |
POST /api/v1.0/organizations/{slug}/spaces | Organization admin attaches a space to an organization by space_id. |
DELETE /api/v1.0/organizations/{slug}/spaces/{space_id} | Organization admin removes a space from an organization. |
Use the Organizations API for organization membership and cross-space organization views. Use the Admin API for global space lifecycle operations and per-space system settings.
Failure Cases
| Status | Common cause |
|---|---|
400 | Duplicate slug, missing required parameter, invalid organization-space assignment, or malformed request body. |
403 | Caller lacks superadmin access, space access, direct space Admin rights for adding a member, or organization admin rights for organization assignment. |
404 | Space, member, user, or role not found. |
422 | Invalid UUID or request payload type. |
500 | Space deletion failed during dependency cleanup. |