Skip to main content

Flag-namespace endpoints

Endpoints for flag-namespace lifecycle and namespace-admin membership.

EndpointAuthStatus
POST /api/v1/tenants/{tenant}/namespacestenant adminv0
GET /api/v1/namespacesauthenticated principalv0
GET /api/v1/tenants/{tenant}/namespaces/{namespace}namespace read or higherv0
DELETE /api/v1/tenants/{tenant}/namespaces/{namespace}tenant admindeferred
GET /api/v1/tenants/{tenant}/namespaces/{namespace}/adminsnamespace admin or higherdeferred
PUT /api/v1/tenants/{tenant}/namespaces/{namespace}/admins/{user_id}namespace admin or higherdeferred
DELETE /api/v1/tenants/{tenant}/namespaces/{namespace}/admins/{user_id}namespace admin or higherdeferred

See conventions for the auth header, error envelope, pagination, and rate limits.

Slug uniqueness. Flag-namespace slugs are unique per-tenant, not globally. Two tenants on the same installation may both own a payments namespace; every namespace-scoped URL therefore carries the owning tenant in its path so the (tenant, slug) pair is unambiguous. The cross-tenant GET /api/v1/namespaces is the only namespace endpoint that is not tenant-scoped in the path; it is reserved for superadmin tooling.


POST /api/v1/tenants/{tenant}/namespaces

Create a new flag namespace in {tenant}. The creator is added as the first namespace admin. Namespace creation does NOT automatically issue service tokens — create explicit tokens afterward with POST /api/v1/tokens.

Auth required: tenant_admin for {tenant}, tenant-admin token bound to {tenant}, or superadmin. Permission: namespace.create.

Path parameters

ParameterDescription
tenantThe owning tenant slug. The principal must be authorized for this tenant.

Request body

{
"slug": "payments",
"display_name": "Payments Team",
"description": "Feature flags for the payments service and checkout domain"
}
FieldTypeRequiredDescription
slugstringyesFlag-namespace slug. Pattern [a-z][a-z0-9-]*, max 63 chars. Unique within {tenant}. Immutable.
display_namestringnoHuman-readable name. Defaults to the slug.
descriptionstringnoFree-form description.

Response: 201 Created

{
"namespace": {
"tenant_slug": "acme",
"slug": "payments",
"display_name": "Payments Team",
"description": "Feature flags for the payments service and checkout domain",
"created_at": "2026-04-25T09:14:33Z",
"manifest_version": null,
"flag_count": 0,
"segment_count": 0
},
"request_id": "01HV5XK2GFQT8N3JRDCP7MW04B"
}

Example

curl -X POST https://exd.example.com/api/v1/tenants/acme/namespaces \
-H "Authorization: Bearer exd_tenant_5cNpQrStUvWxYzAbCdEfGhJkLmNoPqRsTuVwXz" \
-H "Content-Type: application/json" \
-d '{
"slug": "payments",
"display_name": "Payments Team",
"description": "Feature flags for the payments service and checkout domain"
}'

GET /api/v1/namespaces

List flag namespaces the authenticated principal has access to, across tenants.

Auth required: authenticated user, tenant-admin, superadmin, namespace-read, or namespace-write. List endpoints filter to the principal's visible scope:

  • Tenant admins see all namespaces in their tenant.
  • Namespace admins see namespaces where they hold that role.
  • Namespace-scoped tokens see only their bound flag namespace.
  • Superadmin tokens see every flag namespace in the installation.

This is the only flag-namespace endpoint NOT scoped under /api/v1/tenants/{tenant}/. It exists so superadmin tooling and cross-tenant principals can enumerate without iterating tenants.

Query parameters

ParameterDescription
tenantOptional. Limit to a single tenant. Tenant- and namespace-scoped tokens are implicitly filtered to their bound scope and may not widen via tenant=.
limit, afterPagination.

Response: 200 OK

{
"namespaces": [
{
"tenant_slug": "acme",
"slug": "payments",
"display_name": "Payments Team",
"description": "Feature flags for the payments service and checkout domain",
"created_at": "2026-04-25T09:14:33Z",
"manifest_version": 7,
"flag_count": 12,
"segment_count": 4,
"current_user_roles": ["tenant_admin"]
},
{
"tenant_slug": "acme",
"slug": "identity",
"display_name": "Identity & Auth Team",
"description": "Flags for login, MFA, and session management",
"created_at": "2026-03-10T14:22:11Z",
"manifest_version": 3,
"flag_count": 5,
"segment_count": 2,
"current_user_roles": ["namespace_admin"]
}
],
"next_cursor": null,
"request_id": "01HV5XK3RFQT8N3JRDCP7MW04C"
}

Example

curl https://exd.example.com/api/v1/namespaces \
-H "Authorization: Bearer exd_admin_2mNpQrStUvWxYzAbCdEfGhJkLmNoPqRsTuVwXy"

GET /api/v1/tenants/{tenant}/namespaces/{namespace}

Retrieve metadata for a single flag namespace.

Auth required: tenant_admin for {tenant}, namespace admin, tenant-admin token bound to {tenant}, superadmin, namespace-read, or namespace-write bound to (tenant, namespace). Permission: namespace.read.

Path parameters

ParameterDescription
tenantThe owning tenant slug.
namespaceThe flag-namespace slug, unique within {tenant}.

Response: 200 OK

{
"namespace": {
"tenant_slug": "acme",
"slug": "payments",
"display_name": "Payments Team",
"description": "Feature flags for the payments service and checkout domain",
"created_at": "2026-04-25T09:14:33Z",
"manifest_version": 7,
"manifest_uploaded_at": "2026-04-25T11:30:00Z",
"flag_count": 12,
"segment_count": 4,
"telemetry_enabled": true,
"current_user_roles": ["namespace_admin"],
"environments": {
"development": { "display_name": "Development" },
"staging": { "display_name": "Staging" },
"production": { "display_name": "Production" }
}
},
"request_id": "01HV5XK4SFQT8N3JRDCP7MW04D"
}

Example

curl https://exd.example.com/api/v1/tenants/acme/namespaces/payments \
-H "Authorization: Bearer exd_read_4tRvBn9wKjMpXzQsUyAeCdFgHiJkLnOqRtWvYb"

DELETE /api/v1/tenants/{tenant}/namespaces/{namespace}

Deferred. Not implemented in v0.

Permanently delete a flag namespace and all its manifest history. This action is irreversible.

Auth required: tenant_admin for {tenant}, tenant-admin token bound to {tenant}, or superadmin. Permission: namespace.delete.

Request body

A confirmation token MUST be supplied to prevent accidental deletion.

{
"confirmation_token": "payments-delete"
}

confirmation_token must equal <namespace-slug>-delete. Mismatch → 400 invalid_request.

Response: 200 OK

{
"deleted": true,
"namespace": "payments",
"request_id": "01HV5XK5TFQT8N3JRDCP7MW04E"
}

Example

curl -X DELETE https://exd.example.com/api/v1/tenants/acme/namespaces/payments \
-H "Authorization: Bearer exd_admin_2mNpQrStUvWxYzAbCdEfGhJkLmNoPqRsTuVwXy" \
-H "Content-Type: application/json" \
-d '{"confirmation_token": "payments-delete"}'

GET /api/v1/tenants/{tenant}/namespaces/{namespace}/admins

Deferred. Not implemented in v0.

List explicit namespace admins of a flag namespace. Tenant admins have effective admin rights even when not listed here.

Auth required: tenant_admin for {tenant}, namespace admin, tenant-admin token bound to {tenant}, or superadmin. Permission: namespace.admin.read.

Response: 200 OK

{
"admins": [
{
"user_id": "usr_01HV5Z9R4Y0XJ7A2W8WJ9R7S3A",
"email": "owner@acme.example",
"added_at": "2026-04-25T09:14:33Z",
"added_by": "usr_01HV5Z8Q6WRQZF4C8A7Y3DSN9K"
}
],
"request_id": "01HV5XK5ZFQT8N3JRDCP7MW04Z"
}

PUT /api/v1/tenants/{tenant}/namespaces/{namespace}/admins/{user_id}

Deferred. Not implemented in v0.

Grant namespace-admin access to a user in {tenant}.

Auth required: tenant_admin for {tenant}, namespace admin, tenant-admin token, or superadmin. Permission: namespace.admin.manage.

Response: 204 No Content


DELETE /api/v1/tenants/{tenant}/namespaces/{namespace}/admins/{user_id}

Deferred. Not implemented in v0.

Revoke explicit namespace-admin access. The server rejects removal of the final explicit namespace admin unless the flag namespace belongs to an email-domain tenant (where all users are tenant admins by definition).

Auth required: tenant_admin for {tenant}, namespace admin, tenant-admin token, or superadmin. Permission: namespace.admin.manage.

Response: 204 No Content


See also