Documentation for v2.8.0. Read the latest, v2.12.0.
Reference
Maintenance API
The administrative surface of Sanshain: users, roles, groups, maintainers, Producer and Consumer administration, version deletion, settings and observability.
Kept separate from api.yaml deliberately. That file is the contract build plugins and CLIs are written against and must stay stable; this one changes whenever the admin interface does. One document would imply one stability promise for both.
Authorisation. Every endpoint states what it requires. Any signed-in caller marks the read-only listings the dashboard needs before it knows who is looking; everything else names a permission. Producer-scoped endpoints additionally admit a maintainer of the Producer named in the path. An account listed in SANSHAIN_ROOT_USERS holds every permission.
See Roles and permissions for the concepts.
Tokens, scopes, sessions and error shapes are explained in Using the API.
Endpoints#
| Method | Path | Summary | Permission | Scope |
|---|---|---|---|---|
| GET | /admin/auth-config | Read: auth-config | manage_auth_config | global |
| PUT | /admin/auth-config | Replace: auth-config | manage_auth_config | global |
| POST | /admin/auth-config/test | Create or run: auth-config/test | manage_auth_config | global |
| GET | /admin/backup/sqlite | Read: backup/sqlite | run_destructive_operations | global |
| GET | /admin/branches/{name}/timeline | Read: branches/name/timeline | any signed-in caller | global |
| GET | /admin/trunk/graph | Read: trunk/graph | any signed-in caller | global |
| GET | /admin/trunk/timeline | Read: trunk/timeline | any signed-in caller | global |
| POST | /admin/cache/clear | Create or run: cache/clear | manage_settings | global |
| POST | /admin/cleanup/dependencies | Create or run: cleanup/dependencies | manage_settings | global |
| POST | /admin/cleanup/trunk | Create or run: cleanup/trunk | manage_settings | global |
| POST | /admin/cleanup/snapshots | Create or run: cleanup/snapshots | manage_settings | global |
| GET | /admin/consumers | Read: consumers | any signed-in caller | global |
| GET | /admin/consumers/{name} | Read: consumers/name | any signed-in caller | global |
| DELETE | /admin/consumers/{name} | Delete: consumers/name | manage_consumers | global |
| GET | /admin/consumers/{name}/endpoints | Read: consumers/name/endpoints | any signed-in caller | global |
| GET | /admin/endpoint-versions | Read: endpoint-versions | any signed-in caller | global |
| GET | /admin/endpoint-yaml | Read: endpoint-yaml | any signed-in caller | global |
| GET | /admin/groups | Read: groups | manage_roles | global |
| POST | /admin/groups | Create or run: groups | manage_roles | global |
| PUT | /admin/groups/{id} | Replace: groups/id | manage_roles | global |
| DELETE | /admin/groups/{id} | Delete: groups/id | manage_roles | global |
| POST | /admin/groups/{id}/members | Create or run: groups/id/members | manage_roles | global |
| DELETE | /admin/groups/{id}/members/{user_id} | Delete: groups/id/members/user_id | manage_roles | global |
| GET | /admin/maintainers | Read: maintainers | manage_roles | global |
| POST | /admin/nuke/consumers | Create or run: nuke/consumers | run_destructive_operations | global |
| POST | /admin/nuke/database | Create or run: nuke/database | run_destructive_operations | global |
| POST | /admin/nuke/producers | Create or run: nuke/producers | run_destructive_operations | global |
| POST | /admin/nuke/users | Create or run: nuke/users | run_destructive_operations | global |
| GET | /admin/observability/audit-logs | Read: observability/audit-logs | view_audit | global |
| GET | /admin/observability/audit-logs/export | Read: observability/audit-logs/export | view_audit | global |
| GET | /admin/observability/debug-config | Read: observability/debug-config | any signed-in caller | global |
| POST | /admin/observability/debug-config-update | Create or run: observability/debug-config-update | manage_settings | global |
| GET | /admin/observability/logs | Read: observability/logs | any signed-in caller | global |
| GET | /admin/observability/stats | Read: observability/stats | any signed-in caller | global |
| GET | /admin/graph/diff | Read: graph/diff | any signed-in caller | global |
| GET | /admin/periphery | Read: periphery | any signed-in caller | global |
| GET | /admin/graph/scope | Read: graph scope | any signed-in caller | global |
| GET | /admin/producers | Read: producers | any signed-in caller | global |
| POST | /admin/producers/metadata | Create or run: producers/metadata | manage_producers | global |
| GET | /admin/producers/{name} | Read: producers/name | any signed-in caller | global |
| DELETE | /admin/producers/{name} | Delete: producers/name | manage_producers | per Producer: also its maintainers |
| GET | /admin/producers/{name}/branch-memberships | Read: producers/name/branch-memberships | any signed-in caller | global |
| GET | /admin/producers/{name}/diff | Read: producers/name/diff | any signed-in caller | global |
| GET | /admin/producers/{name}/blame | Read: producers/name/blame | any signed-in caller | global |
| GET | /admin/branches | Read: branches | any signed-in caller | global |
| POST | /admin/branches | Write: branches | release_ga | global |
| PUT | /admin/branches/{name} | Write: branches/name | manage_producers | global |
| DELETE | /admin/branches/{name} | Write: branches/name | manage_producers | global |
| GET | /admin/branches/{name}/graph | Read: branches/name/graph | any signed-in caller | global |
| GET | /admin/producers/{name}/endpoints | Read: producers/name/endpoints | any signed-in caller | global |
| GET | /admin/producers/{name}/full-spec | Read: producers/name/full-spec | any signed-in caller | global |
| GET | /admin/producers/{name}/maintainers | Read: producers/name/maintainers | manage_producers | per Producer: also its maintainers |
| POST | /admin/producers/{name}/maintainers | Create or run: producers/name/maintainers | manage_roles | global |
| DELETE | /admin/producers/{name}/maintainers/groups/{group_id} | Delete: producers/name/maintainers/groups/group_id | manage_roles | global |
| DELETE | /admin/producers/{name}/maintainers/users/{user_id} | Delete: producers/name/maintainers/users/user_id | manage_roles | global |
| GET | /admin/producers/{name}/versions | Read: producers/name/versions | any signed-in caller | global |
| DELETE | /admin/producers/{name}/versions/{api_type}/{version} | Delete: producers/name/versions/api_type/version | manage_producers | per Producer: also its maintainers |
| POST | /admin/producers/{name}/versions/{api_type}/{version}/promote | Write: producers/name/versions/api_type/version/promote | release_ga | global |
| GET | /admin/producers/{name}/versions/{api_type}/{version}/dependents | Read: producers/name/versions/api_type/version/dependents | any signed-in caller | global |
| GET | /admin/roles | Read: roles | manage_roles | global |
| GET | /admin/settings/auto-approve | Read: settings/auto-approve | manage_settings | global |
| POST | /admin/settings/auto-approve | Create or run: settings/auto-approve | manage_settings | global |
| GET | /admin/settings/cache | Read: settings/cache | manage_settings | global |
| POST | /admin/settings/cache | Create or run: settings/cache | manage_settings | global |
| GET | /admin/settings/database | Read: settings/database | manage_settings | global |
| GET | /admin/settings/dependency-max-age | Read: settings/dependency-max-age | manage_settings | global |
| POST | /admin/settings/dependency-max-age | Create or run: settings/dependency-max-age | manage_settings | global |
| GET | /admin/settings/trunk-max-age | Read: settings/trunk-max-age | manage_settings | global |
| POST | /admin/settings/trunk-max-age | Create or run: settings/trunk-max-age | manage_settings | global |
| GET | /admin/settings/snapshot-max-age | Read: settings/snapshot-max-age | manage_settings | global |
| POST | /admin/settings/snapshot-max-age | Create or run: settings/snapshot-max-age | manage_settings | global |
| GET | /admin/webhooks | Read: webhooks/webhooks | manage_settings | global |
| POST | /admin/webhooks | Create or run: webhooks/webhooks | manage_settings | global |
| GET | /admin/webhooks/{id} | Read: webhooks/webhooks/id | manage_settings | global |
| PATCH | /admin/webhooks/{id} | Update: webhooks/webhooks/id | manage_settings | global |
| DELETE | /admin/webhooks/{id} | Delete: webhooks/webhooks/id | manage_settings | global |
| POST | /admin/webhooks/{id}/test | Create or run: webhooks/webhooks/id/test | manage_settings | global |
| POST | /admin/webhooks/{id}/rotate-secret | Create or run: webhooks/webhooks/id/rotate-secret | manage_settings | global |
| GET | /admin/webhooks/{id}/deliveries | Read: webhooks/webhooks/id/deliveries | manage_settings | global |
| POST | /admin/webhooks/{id}/deliveries/{delivery_id}/redeliver | Create or run: webhooks/webhooks/id/deliveries/delivery_id/redeliver | manage_settings | global |
| GET | /admin/producers/{name}/webhooks | Read: producers/name/webhooks | manage_producers | per Producer: also its maintainers |
| POST | /admin/producers/{name}/webhooks | Create or run: producers/name/webhooks | manage_producers | per Producer: also its maintainers |
| GET | /admin/producers/{name}/webhooks/{id} | Read: producers/name/webhooks/id | manage_producers | per Producer: also its maintainers |
| PATCH | /admin/producers/{name}/webhooks/{id} | Update: producers/name/webhooks/id | manage_producers | per Producer: also its maintainers |
| DELETE | /admin/producers/{name}/webhooks/{id} | Delete: producers/name/webhooks/id | manage_producers | per Producer: also its maintainers |
| POST | /admin/producers/{name}/webhooks/{id}/test | Create or run: producers/name/webhooks/id/test | manage_producers | per Producer: also its maintainers |
| POST | /admin/producers/{name}/webhooks/{id}/rotate-secret | Create or run: producers/name/webhooks/id/rotate-secret | manage_producers | per Producer: also its maintainers |
| GET | /admin/producers/{name}/webhooks/{id}/deliveries | Read: producers/name/webhooks/id/deliveries | manage_producers | per Producer: also its maintainers |
| POST | /admin/producers/{name}/webhooks/{id}/deliveries/{delivery_id}/redeliver | Create or run: producers/name/webhooks/id/deliveries/delivery_id/redeliver | manage_producers | per Producer: also its maintainers |
| GET | /admin/consumers/{name}/webhooks | Read: consumers/name/webhooks | manage_producers | per Consumer: also maintainers of the Producer of the same name |
| POST | /admin/consumers/{name}/webhooks | Create or run: consumers/name/webhooks | manage_producers | per Consumer: also maintainers of the Producer of the same name |
| GET | /admin/consumers/{name}/webhooks/{id} | Read: consumers/name/webhooks/id | manage_producers | per Consumer: also maintainers of the Producer of the same name |
| PATCH | /admin/consumers/{name}/webhooks/{id} | Update: consumers/name/webhooks/id | manage_producers | per Consumer: also maintainers of the Producer of the same name |
| DELETE | /admin/consumers/{name}/webhooks/{id} | Delete: consumers/name/webhooks/id | manage_producers | per Consumer: also maintainers of the Producer of the same name |
| POST | /admin/consumers/{name}/webhooks/{id}/test | Create or run: consumers/name/webhooks/id/test | manage_producers | per Consumer: also maintainers of the Producer of the same name |
| POST | /admin/consumers/{name}/webhooks/{id}/rotate-secret | Create or run: consumers/name/webhooks/id/rotate-secret | manage_producers | per Consumer: also maintainers of the Producer of the same name |
| GET | /admin/consumers/{name}/webhooks/{id}/deliveries | Read: consumers/name/webhooks/id/deliveries | manage_producers | per Consumer: also maintainers of the Producer of the same name |
| POST | /admin/consumers/{name}/webhooks/{id}/deliveries/{delivery_id}/redeliver | Create or run: consumers/name/webhooks/id/deliveries/delivery_id/redeliver | manage_producers | per Consumer: also maintainers of the Producer of the same name |
| GET | /admin/settings/webhook-allowed-hosts | Read: settings/webhook-allowed-hosts | manage_settings | global |
| POST | /admin/settings/webhook-allowed-hosts | Create or run: settings/webhook-allowed-hosts | manage_settings | global |
| GET | /admin/users | Read: users | manage_users | global |
| DELETE | /admin/users/{id} | Delete: users/id | manage_users | global |
| POST | /admin/users/{id}/approve | Create or run: users/id/approve | manage_users | global |
| GET | /admin/users/{id}/maintains | Read: users/id/maintains | manage_roles | global |
| GET | /admin/users/{id}/roles | Read: users/id/roles | manage_roles | global |
| POST | /admin/users/{id}/roles | Create or run: users/id/roles | manage_roles | global |
| DELETE | /admin/users/{id}/roles/{role} | Delete: users/id/roles/role | manage_roles | global |
/admin/auth-config#
GET /admin/auth-config#
Read: auth-config
Authentication: session token · Permission: manage_auth_config · Scope: global
Requires the manage_auth_config permission.
Responses
PUT /admin/auth-config#
Replace: auth-config
Authentication: session token · Permission: manage_auth_config · Scope: global
Requires the manage_auth_config permission.
Responses
/admin/auth-config/test#
POST /admin/auth-config/test#
Create or run: auth-config/test
Authentication: session token · Permission: manage_auth_config · Scope: global
Requires the manage_auth_config permission. Connects to the directory named by the submitted LDAP configuration and binds with its service account; nothing is saved.
Responses
| Status | Description | Body |
|---|---|---|
200 | Connected and bound. | — |
400 | The connection or the bind failed; | ConnectionTestFailure |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without what this endpoint requires. | ErrorBody |
/admin/backup/sqlite#
GET /admin/backup/sqlite#
Read: backup/sqlite
Authentication: session token API token (full) · Permission: run_destructive_operations · Scope: global
Requires the run_destructive_operations permission. A consistent snapshot of the SQLite database, produced by VACUUM INTO while Sanshain runs, streamed as application/vnd.sqlite3 with a Content-Disposition filename sanshain-<instance version>-<UTC timestamp>.db. Only one snapshot runs at a time. Meant for the scheduled backup: a full API token of an account holding the permission is accepted beside a session, a read_only token is refused with 403. See the deployment guide, Backup and restore.
Responses
/admin/branches/{name}/timeline#
GET /admin/branches/{name}/timeline#
Read: branches/name/timeline
Authentication: session token · Permission: any signed-in caller · Scope: global
The instants this branch's graph changed (every open/close event of its append-only pin store), distinct and ascending — the timeline slider's markers (ADR-0005).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string |
Responses
/admin/trunk/graph#
GET /admin/trunk/graph#
Read: trunk/graph
Authentication: session token · Permission: any signed-in caller · Scope: global
The main graph's pin set — current, or as it was at the optional at instant, reconstructed from the append-only trunk history (ADR-0005). Pins on deleted versions are marked dangling; a non-RFC-3339 at answers 400.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
at | query | — | string |
Responses
| Status | Description | Body |
|---|---|---|
200 | The pin set as a JSON array. | — |
401 | Not signed in. | ErrorBody |
/admin/trunk/timeline#
GET /admin/trunk/timeline#
Read: trunk/timeline
Authentication: session token · Permission: any signed-in caller · Scope: global
The instants the main graph changed, distinct and ascending — the timeline slider's markers (ADR-0005).
Responses
| Status | Description | Body |
|---|---|---|
200 | The change instants as a JSON array of RFC 3339 strings. | — |
401 | Not signed in. | ErrorBody |
/admin/cache/clear#
POST /admin/cache/clear#
Create or run: cache/clear
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
Responses
/admin/cleanup/dependencies#
POST /admin/cleanup/dependencies#
Create or run: cleanup/dependencies
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
Responses
/admin/cleanup/trunk#
POST /admin/cleanup/trunk#
Create or run: cleanup/trunk
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
Runs the trunk TTL cleanup immediately (ADR-0004): open trunk pins not re-required within trunk_max_age_days are closed (they leave the main graph's current view; the rows stay as timeline history) and stale trunk version markers are cleared. Answers {"closed": n}.
Responses
/admin/cleanup/snapshots#
POST /admin/cleanup/snapshots#
Create or run: cleanup/snapshots
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
Runs the use-based snapshot expiry immediately: snapshots neither provided nor required within snapshot_max_age_days are deleted. GA versions are never age-culled.
Responses
/admin/consumers#
GET /admin/consumers#
Read: consumers
Authentication: session token · Permission: any signed-in caller · Scope: global
Any signed-in caller.
Responses
/admin/consumers/{name}#
GET /admin/consumers/{name}#
Read: consumers/name
Authentication: session token · Permission: any signed-in caller · Scope: global
Any signed-in caller.
The Consumer's context (#48): what its Backstage catalog-info.yaml says about it — owner, description, source location and links. context is null until a catalog push described the system.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string |
Responses
| Status | Description | Body |
|---|---|---|
200 | The Consumer's name and context. | ParticipantContext
Example 200 response (placeholder values derived from the schema) |
401 | Not signed in. | ErrorBody |
404 | No such Consumer. | ErrorBody |
DELETE /admin/consumers/{name}#
Delete: consumers/name
Authentication: session token · Permission: manage_consumers · Scope: global
Requires the manage_consumers permission.
Answers {"deleted": name}. Refused with 409 while any sanshain-branch's recorded graph still references the Consumer — a release cut is a frozen record, and the delete would remove its edges retroactively. The message names the branches to retire first. Trunk presence does not block.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string |
Responses
/admin/consumers/{name}/endpoints#
GET /admin/consumers/{name}/endpoints#
Read: consumers/name/endpoints
Authentication: session token · Permission: any signed-in caller · Scope: global
Any signed-in caller.
Every endpoint the Consumer is recorded as depending on, with the pinned version and its current stability.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string |
Responses
/admin/endpoint-versions#
GET /admin/endpoint-versions#
Read: endpoint-versions
Authentication: session token · Permission: any signed-in caller · Scope: global
Any signed-in caller.
The blame trail of one endpoint: which versions of the line changed it, with the Author attribution recorded on each Provide.
Responses
/admin/endpoint-yaml#
GET /admin/endpoint-yaml#
Read: endpoint-yaml
Authentication: session token · Permission: any signed-in caller · Scope: global
Any signed-in caller.
Responses
/admin/groups#
GET /admin/groups#
Read: groups
Authentication: session token · Permission: manage_roles · Scope: global
Requires the manage_roles permission.
Responses
POST /admin/groups#
Create or run: groups
Authentication: session token · Permission: manage_roles · Scope: global
Requires the manage_roles permission.
Responses
/admin/groups/{id}#
PUT /admin/groups/{id}#
Replace: groups/id
Authentication: session token · Permission: manage_roles · Scope: global
Requires the manage_roles permission. Adding an admin-guarded role (admin, releaser) to the group's role set — or removing one it holds — additionally requires the caller to be an admin.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
id | path | yes | integer |
Responses
DELETE /admin/groups/{id}#
Delete: groups/id
Authentication: session token · Permission: manage_roles · Scope: global
Requires the manage_roles permission. Deleting a group that holds an admin-guarded role (admin, releaser) strips that role from every member at once, so it additionally requires the caller to be an admin.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
id | path | yes | integer |
Responses
/admin/groups/{id}/members#
POST /admin/groups/{id}/members#
Create or run: groups/id/members
Authentication: session token · Permission: manage_roles · Scope: global
Requires the manage_roles permission. Membership of a group that holds an admin-guarded role (admin, releaser) IS a grant of that role, so adding a member then additionally requires the caller to be an admin.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
id | path | yes | integer |
Responses
/admin/groups/{id}/members/{user_id}#
DELETE /admin/groups/{id}/members/{user_id}#
Delete: groups/id/members/user_id
Authentication: session token · Permission: manage_roles · Scope: global
Requires the manage_roles permission. Removing a member from a group that holds an admin-guarded role (admin, releaser) strips that role, so it additionally requires the caller to be an admin.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
id | path | yes | integer | |
user_id | path | yes | integer |
Responses
/admin/maintainers#
GET /admin/maintainers#
Read: maintainers
Authentication: session token · Permission: manage_roles · Scope: global
Requires the manage_roles permission.
Every Producer with its maintainer user and group ids, in one response — the aggregate behind the dashboard's Maintainers section, so it does not ask per Producer.
Responses
/admin/nuke/consumers#
POST /admin/nuke/consumers#
Create or run: nuke/consumers
Authentication: session token · Permission: run_destructive_operations · Scope: global
Requires the run_destructive_operations permission.
Responses
/admin/nuke/database#
POST /admin/nuke/database#
Create or run: nuke/database
Authentication: session token · Permission: run_destructive_operations · Scope: global
Requires the run_destructive_operations permission.
Responses
/admin/nuke/producers#
POST /admin/nuke/producers#
Create or run: nuke/producers
Authentication: session token · Permission: run_destructive_operations · Scope: global
Requires the run_destructive_operations permission.
Responses
/admin/nuke/users#
POST /admin/nuke/users#
Create or run: nuke/users
Authentication: session token · Permission: run_destructive_operations · Scope: global
Deletes every user who is not an effective administrator — users with a direct admin role, admin via group membership, or a configured root username survive. Requires the run_destructive_operations permission.
Responses
/admin/observability/audit-logs#
GET /admin/observability/audit-logs#
Read: observability/audit-logs
Authentication: session token · Permission: view_audit · Scope: global
Requires the view_audit permission. The most recent audit entries for the observability panel; optional limit (default 100, capped at 200).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
limit | query | — | integer |
Responses
/admin/observability/audit-logs/export#
GET /admin/observability/audit-logs/export#
Read: observability/audit-logs/export
Authentication: session token · Permission: view_audit · Scope: global
Requires the view_audit permission. CSV of the most recent audit entries, columns id,timestamp,username,action,details,service,version, action_type,stream — every field except the bulky diff blob.
Responses
/admin/observability/debug-config#
GET /admin/observability/debug-config#
Read: observability/debug-config
Authentication: session token · Permission: any signed-in caller · Scope: global
Any signed-in caller.
Responses
/admin/observability/debug-config-update#
POST /admin/observability/debug-config-update#
Create or run: observability/debug-config-update
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
Responses
/admin/observability/logs#
GET /admin/observability/logs#
Read: observability/logs
Authentication: session token · Permission: any signed-in caller · Scope: global
Any signed-in caller.
Responses
/admin/observability/stats#
GET /admin/observability/stats#
Read: observability/stats
Authentication: session token · Permission: any signed-in caller · Scope: global
Any signed-in caller.
Responses
/admin/graph/diff#
GET /admin/graph/diff#
Read: graph/diff
Authentication: session token · Permission: any signed-in caller · Scope: global
Structured diff between two graph selections (ADR-0005) — release vs release, release vs main, one graph at two instants. left/right are main[@rfc3339] or <branch>[@rfc3339]. Answers services added/removed, pins added/removed, per-pin version changes, and periphery edges (system → Peripheral Resource) added/removed; all arrays empty means no differences.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
left | query | yes | string | |
right | query | yes | string |
Responses
/admin/periphery#
GET /admin/periphery#
Read: periphery
Authentication: session token · Permission: any signed-in caller · Scope: global
Any signed-in caller.
The edges from systems to their Peripheral Resources (#46) — what their Backstage catalog-info.yaml lists under dependsOn — for one graph scope: dev (the default), main[@rfc3339] or <branch>[@rfc3339], the selector grammar of /admin/graph/diff. A past instant answers the periphery as it was then.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
scope | query | — | string |
Responses
/admin/graph/scope#
GET /admin/graph/scope#
Read: graph scope
Authentication: session token · Permission: any signed-in caller · Scope: global
Any signed-in caller.
What the dependency graph needs of one scope beyond its pins, for dev (the default), main[@rfc3339] or <branch>[@rfc3339] — the selector grammar of /admin/graph/diff:
producers: the producers in the scope at its instant, each with one version line per API type. dev: every producer with any version (its newest per line). main: trunk's member versions — every trunk-flagged provide records the version it provided, closed again by the trunk TTL, a retire, or a version/producer delete. A branch: its member versions (tag-flagged provides) and, for lines without one, the highest version its pins name.stabilityisnullwhen the version was deleted since;last_provided_atis the latest provide known at the instant (nullwhen none is known).harvested_subscriptions: dev all, live main the trunk-flagged ones, everything else none (there is no harvested timeline).systems: the context (#48) of every system that pushed one, by name — owner, description, source location and links from its Backstagecatalog-info.yaml— so the node panel needs no extra request. A present-day fact, the same in every scope.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
scope | query | — | string |
Responses
| Status | Description | Body |
|---|---|---|
200 | The scope's producers, harvested subscriptions and system contexts. | object
Example 200 response (placeholder values derived from the schema) |
400 | A selector instant that is not RFC 3339, or | ErrorBody |
401 | Not signed in. | ErrorBody |
404 | A named branch does not exist. | ErrorBody |
/admin/producers#
GET /admin/producers#
Read: producers
Authentication: session token · Permission: any signed-in caller · Scope: global
Any signed-in caller.
Every Producer with metadata and its full version lines (version, stability, endpoint count, snapshot expiry).
Responses
/admin/producers/metadata#
POST /admin/producers/metadata#
Create or run: producers/metadata
Authentication: session token · Permission: manage_producers · Scope: global
Requires the manage_producers permission.
Responses
/admin/producers/{name}#
GET /admin/producers/{name}#
Read: producers/name
Authentication: session token · Permission: any signed-in caller · Scope: global
Any signed-in caller.
The Producer's context (#48): what its Backstage catalog-info.yaml says about it — owner, description, source location and links. context is null until a catalog push described the system.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string |
Responses
| Status | Description | Body |
|---|---|---|
200 | The Producer's name and context. | ParticipantContext
Example 200 response (placeholder values derived from the schema) |
401 | Not signed in. | ErrorBody |
404 | No such Producer. | ErrorBody |
DELETE /admin/producers/{name}#
Delete: producers/name
Authentication: session token · Permission: manage_producers · Scope: per Producer: also its maintainers
Requires the manage_producers permission, or maintainership of the Producer named in the path.
Answers {"deleted": name}. Refused with 409 while any sanshain-branch's recorded graph still references the Producer — a release cut is a frozen record, and the delete would remove its edges retroactively. The message names the branches to retire first. Trunk presence does not block.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string |
Responses
/admin/producers/{name}/branch-memberships#
GET /admin/producers/{name}/branch-memberships#
Read: producers/name/branch-memberships
Authentication: session token · Permission: any signed-in caller · Scope: global
Reverse lookup (ADR-0005): every (api_type, version, branch) this producer is currently referenced by across all sanshain-branches — "which releases pin b@1.0.0?" answered where you're already looking.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string |
Responses
/admin/producers/{name}/diff#
GET /admin/producers/{name}/diff#
Read: producers/name/diff
Authentication: session token · Permission: any signed-in caller · Scope: global
Any signed-in caller.
Line diff between two versions of a line (api_type, from, to query parameters), computed with the similar (Myers) diff. Both stored documents are compared, or, with path and method, one endpoint's snippet (a version without the endpoint diffs as an empty document).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string | |
api_type | query | — | string | One of Default |
from | query | yes | string | The old side's version. |
to | query | yes | string | The new side's version. |
path | query | — | string | Diff this endpoint's snippet instead of the document; needs |
method | query | — | string | The endpoint's method (or RPC/operation); needs |
ignore_whitespace | query | — | boolean | Compare lines without leading and trailing whitespace, so indentation and trailing-whitespace differences are not changes. Default |
context | query | — | string | Unchanged lines kept around each change, or Default |
format | query | — | string |
One of Default |
Responses
/admin/producers/{name}/blame#
GET /admin/producers/{name}/blame#
Read: producers/name/blame
Authentication: session token · Permission: any signed-in caller · Scope: global
Any signed-in caller.
Blame for one version of a line: the version's text (the stored document, or with path and method one endpoint's snippet) as a JSON array of blocks of consecutive lines last changed in the same version, oldest version first walked with the same similar diff as /diff. Each block is {version, stability, provided_by, updated_at, start_line, lines}; start_line is 1-based. A version with identical content (a promotion) changes no line; in endpoint mode a version without the endpoint is an empty text. An empty array means the version's text is empty.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string | |
api_type | query | — | string | One of Default |
version | query | yes | string | The version to blame. |
path | query | — | string | Blame this endpoint's snippet instead of the document; needs |
method | query | — | string | The endpoint's method (or RPC/operation); needs |
Responses
/admin/branches#
GET /admin/branches#
Read: branches
Authentication: session token · Permission: any signed-in caller · Scope: global
Every sanshain-branch (ADR-0005), newest first: id, name, created_at, created_by, source (trunk or the source branch's then-current name) and as_of (the instant of the source graph the branch was born from).
Responses
| Status | Description | Body |
|---|---|---|
200 | The branch listing as a JSON array. | — |
401 | Not signed in. | ErrorBody |
POST /admin/branches#
Write: branches
Authentication: session token · Permission: release_ga · Scope: global
Requires the release_ga permission (the releaser role; admins and root hold it implicitly) — creating a named release graph is release work, and this endpoint's primary caller is the DevOps release-cut script, which needs nothing beyond this description:
Creates a sanshain-branch: a named copy of a source graph at a chosen instant, from then on updated by tag-flagged hotfix builds.
Body (JSON):
name(string, required): unique among existing branches; free text ("Release Maribou"). Duplicate →409.source(string, optional): the name of an existing branch to copy from. Omitted → the trunk graph. Unknown name →404, nothing is created.as_of(string, optional): RFC 3339 instant of the source graph to copy. Omitted → now. A past instant creates the branch retroactively — trunk-at-that-date is reconstructed from the append-only history, so a forgotten release day is repairable. Malformed →400.
The call is not idempotent: repeating it answers 409. Creation is audited (BRANCH_CREATED, naming the caller, source and instant).
Responses
| Status | Description | Body |
|---|---|---|
201 | Created. The body is the branch record (see GET). | — |
400 | Empty or reserved name ( | ErrorBody |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without the | ErrorBody |
404 | The | ErrorBody |
409 | A branch with this name already exists. | ErrorBody |
/admin/branches/{name}#
PUT /admin/branches/{name}#
Write: branches/name
Authentication: session token · Permission: manage_producers · Scope: global
Requires the manage_producers permission (admins) — deliberately a higher bar than creation. Renames the branch: identity is the internal id, so membership, timeline and audit stamps survive; a pipeline still sending the old tag name gets the instructive 404 until its configuration is updated (intended for a name wrong enough to rename). Body: {"new_name": "..."}. Audited with old and new name.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string |
Responses
DELETE /admin/branches/{name}#
Write: branches/name
Authentication: session token · Permission: manage_producers · Scope: global
Requires the manage_producers permission (admins). Deletes the branch and its graph rows — the deliberate, audited EOL act — and frees the name for reuse.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string |
Responses
/admin/branches/{name}/graph#
GET /admin/branches/{name}/graph#
Read: branches/name/graph
Authentication: session token · Permission: any signed-in caller · Scope: global
The branch's pin set — its graph edges, each {client, service, api_type, version, path, method, valid_from, last_required_at} with the version by value (a deleted spec version renders as a dangling reference and heals when the number is re-provided). Optional at (RFC 3339) answers the branch's graph as it was at that instant; a non-RFC-3339 at answers 400.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string | |
at | query | — | string |
Responses
/admin/producers/{name}/endpoints#
GET /admin/producers/{name}/endpoints#
Read: producers/name/endpoints
Authentication: session token · Permission: any signed-in caller · Scope: global
Any signed-in caller.
The endpoints of one version-line entry (api_type, version query parameters).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string |
Responses
/admin/producers/{name}/full-spec#
GET /admin/producers/{name}/full-spec#
Read: producers/name/full-spec
Authentication: session token · Permission: any signed-in caller · Scope: global
Any signed-in caller.
The full provided document of one version-line entry, exactly as the Producer submitted it (api_type, version query parameters).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string |
Responses
/admin/producers/{name}/maintainers#
GET /admin/producers/{name}/maintainers#
Read: producers/name/maintainers
Authentication: session token · Permission: manage_producers · Scope: per Producer: also its maintainers
Requires the manage_producers permission, or maintainership of the Producer named in the path.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string |
Responses
POST /admin/producers/{name}/maintainers#
Create or run: producers/name/maintainers
Authentication: session token · Permission: manage_roles · Scope: global
Requires the manage_roles permission.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string |
Responses
/admin/producers/{name}/maintainers/groups/{group_id}#
DELETE /admin/producers/{name}/maintainers/groups/{group_id}#
Delete: producers/name/maintainers/groups/group_id
Authentication: session token · Permission: manage_roles · Scope: global
Requires the manage_roles permission.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string | |
group_id | path | yes | integer |
Responses
/admin/producers/{name}/maintainers/users/{user_id}#
DELETE /admin/producers/{name}/maintainers/users/{user_id}#
Delete: producers/name/maintainers/users/user_id
Authentication: session token · Permission: manage_roles · Scope: global
Requires the manage_roles permission.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string | |
user_id | path | yes | integer |
Responses
/admin/producers/{name}/versions#
GET /admin/producers/{name}/versions#
Read: producers/name/versions
Authentication: session token · Permission: any signed-in caller · Scope: global
Any signed-in caller.
One Producer's version lines, optionally narrowed with an api_type query parameter.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string |
Responses
/admin/producers/{name}/versions/{api_type}/{version}#
DELETE /admin/producers/{name}/versions/{api_type}/{version}#
Delete: producers/name/versions/api_type/version
Authentication: session token · Permission: manage_producers · Scope: per Producer: also its maintainers
Requires the manage_producers permission, or maintainership of the Producer named in the path.
The sole escape hatch from GA immutability (ADR-0003): delete the version outright, freeing its number. Consumers pinned to it hard-fail on their next require — check the dependents listing first. Audited, naming the pinned Consumers.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string | |
api_type | path | yes | string | |
version | path | yes | string |
Responses
/admin/producers/{name}/versions/{api_type}/{version}/promote#
POST /admin/producers/{name}/versions/{api_type}/{version}/promote#
Write: producers/name/versions/api_type/version/promote
Authentication: session token · Permission: release_ga · Scope: global
Requires the release_ga permission — enforced by the same GA gate every release goes through, so an unauthorized attempt answers the instructive 403 and is recorded as a VERSION_REJECTED audit entry with reason ga_requires_releaser.
One-click promote: releases the stored snapshot in place, exactly as if its content were re-provided with stability: ga — the original provider stays credited, the promoting Actor is named in the VERSION_PROMOTED audit entry, and AsyncAPI GA contract checks apply. Promoting an already-GA version is an idempotent no-op (promoted: false).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string | |
api_type | path | yes | string | |
version | path | yes | string |
Responses
| Status | Description | Body |
|---|---|---|
202 | Promoted (or already GA — idempotent no-op). Standard Provide response body. | — |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without the | ErrorBody |
404 | Unknown Producer or version. | ErrorBody |
409 | Rejected by the same rules a GA Provide faces — semver honesty against the GA baseline (carries | ErrorBody |
/admin/producers/{name}/versions/{api_type}/{version}/dependents#
GET /admin/producers/{name}/versions/{api_type}/{version}/dependents#
Read: producers/name/versions/api_type/version/dependents
Authentication: session token · Permission: any signed-in caller · Scope: global
Any signed-in caller.
The Consumers currently pinned to this version — what a delete would break. Shown by the UI before a delete-version is confirmed.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string | |
api_type | path | yes | string | |
version | path | yes | string |
Responses
/admin/roles#
GET /admin/roles#
Read: roles
Authentication: session token · Permission: manage_roles · Scope: global
Requires the manage_roles permission.
Responses
/admin/settings/auto-approve#
GET /admin/settings/auto-approve#
Read: settings/auto-approve
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
Responses
POST /admin/settings/auto-approve#
Create or run: settings/auto-approve
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
Responses
/admin/settings/cache#
GET /admin/settings/cache#
Read: settings/cache
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
Responses
POST /admin/settings/cache#
Create or run: settings/cache
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
Responses
/admin/settings/database#
GET /admin/settings/database#
Read: settings/database
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
Responses
/admin/settings/dependency-max-age#
GET /admin/settings/dependency-max-age#
Read: settings/dependency-max-age
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
Responses
POST /admin/settings/dependency-max-age#
Create or run: settings/dependency-max-age
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission. Body: {"days": n}, at least 1 and at most 36500 (~100 years); values outside answer 400.
Responses
/admin/settings/trunk-max-age#
GET /admin/settings/trunk-max-age#
Read: settings/trunk-max-age
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission. The trunk TTL in days (ADR-0004), default 90; 0 disables the cleanup.
Responses
POST /admin/settings/trunk-max-age#
Create or run: settings/trunk-max-age
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission. Body: {"days": n}, at most 36500 (~100 years); larger values answer 400.
Responses
/admin/settings/snapshot-max-age#
GET /admin/settings/snapshot-max-age#
Read: settings/snapshot-max-age
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
Responses
POST /admin/settings/snapshot-max-age#
Create or run: settings/snapshot-max-age
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
Days a snapshot survives without being provided or required. 0 disables the cleanup. At most 36500 (~100 years); larger values answer 400.
Responses
/admin/webhooks#
GET /admin/webhooks#
Read: webhooks/webhooks
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
The hooks of this scope, newest last, without their secrets (secret_hint is a prefix of the secret's SHA-256).
Responses
| Status | Description | Body |
|---|---|---|
200 | The hooks. | WebhookList
Example 200 response (placeholder values derived from the schema) |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without what this endpoint requires. | ErrorBody |
POST /admin/webhooks#
Create or run: webhooks/webhooks
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
Register a hook (WebhookCreate). The URL must be https://, or http:// to a host the allow-list names with http://; callers without manage_settings are refused outside the allow-list (and with an empty allow-list), callers with it are exempt for good. The answer carries the signing secret once.
Responses
| Status | Description | Body |
|---|---|---|
201 | Registered; the secret is shown once. | WebhookCreated
Example 201 response (placeholder values derived from the schema) |
400 | Not a valid hook (URL, format, event type or glob). | — |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without what this endpoint requires. | ErrorBody |
/admin/webhooks/{id}#
GET /admin/webhooks/{id}#
Read: webhooks/webhooks/id
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
id | path | yes | integer |
Responses
| Status | Description | Body |
|---|---|---|
200 | The hook. | Webhook
Example 200 response (placeholder values derived from the schema) |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without what this endpoint requires. | ErrorBody |
404 | No such hook in this scope. | — |
PATCH /admin/webhooks/{id}#
Update: webhooks/webhooks/id
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
Pause or resume (paused), replace the event-type filter (event_types, [] = every type) or the Producer glob (producer_glob, null clears it). Fields left out stay as they are.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
id | path | yes | integer |
Responses
| Status | Description | Body |
|---|---|---|
200 | The hook after the patch. | Webhook
Example 200 response (placeholder values derived from the schema) |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without what this endpoint requires. | ErrorBody |
404 | No such hook in this scope. | — |
DELETE /admin/webhooks/{id}#
Delete: webhooks/webhooks/id
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
Deletes the hook and its delivery log.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
id | path | yes | integer |
Responses
/admin/webhooks/{id}/test#
POST /admin/webhooks/{id}/test#
Create or run: webhooks/webhooks/id/test
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
Queue a webhook.test event for this hook alone; the worker delivers it like any other event, so the delivery log shows whether the receiver, the secret and the allow-list are in order.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
id | path | yes | integer |
Responses
/admin/webhooks/{id}/rotate-secret#
POST /admin/webhooks/{id}/rotate-secret#
Create or run: webhooks/webhooks/id/rotate-secret
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
A fresh secret, shown once; deliveries from now on are signed with it.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
id | path | yes | integer |
Responses
| Status | Description | Body |
|---|---|---|
200 | The hook and its new secret. | WebhookCreated
Example 200 response (placeholder values derived from the schema) |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without what this endpoint requires. | ErrorBody |
404 | No such hook in this scope. | — |
/admin/webhooks/{id}/deliveries#
GET /admin/webhooks/{id}/deliveries#
Read: webhooks/webhooks/id/deliveries
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
The newest deliveries of the hook (limit, default 50, at most 200): status, attempts, next attempt, last response code and error.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
id | path | yes | integer |
Responses
| Status | Description | Body |
|---|---|---|
200 | The delivery log. | WebhookDeliveryList
Example 200 response (placeholder values derived from the schema) |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without what this endpoint requires. | ErrorBody |
404 | No such hook in this scope. | — |
/admin/webhooks/{id}/deliveries/{delivery_id}/redeliver#
POST /admin/webhooks/{id}/deliveries/{delivery_id}/redeliver#
Create or run: webhooks/webhooks/id/deliveries/delivery_id/redeliver
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
Reset one delivery to pending, due now, attempt count kept — one more attempt even for a dead delivery.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
id | path | yes | integer | |
delivery_id | path | yes | integer |
Responses
| Status | Description | Body |
|---|---|---|
202 | Reset; the delivery as it now is. | WebhookDelivery
Example 202 response (placeholder values derived from the schema) |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without what this endpoint requires. | ErrorBody |
404 | No such delivery on this hook. | — |
/admin/producers/{name}/webhooks#
GET /admin/producers/{name}/webhooks#
Read: producers/name/webhooks
Authentication: session token · Permission: manage_producers · Scope: per Producer: also its maintainers
Requires the manage_producers permission, or maintainership of the Producer named in the path.
The hooks of this scope, newest last, without their secrets (secret_hint is a prefix of the secret's SHA-256).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string |
Responses
| Status | Description | Body |
|---|---|---|
200 | The hooks. | WebhookList
Example 200 response (placeholder values derived from the schema) |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without what this endpoint requires. | ErrorBody |
POST /admin/producers/{name}/webhooks#
Create or run: producers/name/webhooks
Authentication: session token · Permission: manage_producers · Scope: per Producer: also its maintainers
Requires the manage_producers permission, or maintainership of the Producer named in the path.
Register a hook (WebhookCreate). The URL must be https://, or http:// to a host the allow-list names with http://; callers without manage_settings are refused outside the allow-list (and with an empty allow-list), callers with it are exempt for good. The answer carries the signing secret once.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string |
Responses
| Status | Description | Body |
|---|---|---|
201 | Registered; the secret is shown once. | WebhookCreated
Example 201 response (placeholder values derived from the schema) |
400 | Not a valid hook (URL, format, event type or glob). | — |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without what this endpoint requires. | ErrorBody |
/admin/producers/{name}/webhooks/{id}#
GET /admin/producers/{name}/webhooks/{id}#
Read: producers/name/webhooks/id
Authentication: session token · Permission: manage_producers · Scope: per Producer: also its maintainers
Requires the manage_producers permission, or maintainership of the Producer named in the path.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string | |
id | path | yes | integer |
Responses
| Status | Description | Body |
|---|---|---|
200 | The hook. | Webhook
Example 200 response (placeholder values derived from the schema) |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without what this endpoint requires. | ErrorBody |
404 | No such hook in this scope. | — |
PATCH /admin/producers/{name}/webhooks/{id}#
Update: producers/name/webhooks/id
Authentication: session token · Permission: manage_producers · Scope: per Producer: also its maintainers
Requires the manage_producers permission, or maintainership of the Producer named in the path.
Pause or resume (paused), replace the event-type filter (event_types, [] = every type) or the Producer glob (producer_glob, null clears it). Fields left out stay as they are.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string | |
id | path | yes | integer |
Responses
| Status | Description | Body |
|---|---|---|
200 | The hook after the patch. | Webhook
Example 200 response (placeholder values derived from the schema) |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without what this endpoint requires. | ErrorBody |
404 | No such hook in this scope. | — |
DELETE /admin/producers/{name}/webhooks/{id}#
Delete: producers/name/webhooks/id
Authentication: session token · Permission: manage_producers · Scope: per Producer: also its maintainers
Requires the manage_producers permission, or maintainership of the Producer named in the path.
Deletes the hook and its delivery log.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string | |
id | path | yes | integer |
Responses
/admin/producers/{name}/webhooks/{id}/test#
POST /admin/producers/{name}/webhooks/{id}/test#
Create or run: producers/name/webhooks/id/test
Authentication: session token · Permission: manage_producers · Scope: per Producer: also its maintainers
Requires the manage_producers permission, or maintainership of the Producer named in the path.
Queue a webhook.test event for this hook alone; the worker delivers it like any other event, so the delivery log shows whether the receiver, the secret and the allow-list are in order.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string | |
id | path | yes | integer |
Responses
/admin/producers/{name}/webhooks/{id}/rotate-secret#
POST /admin/producers/{name}/webhooks/{id}/rotate-secret#
Create or run: producers/name/webhooks/id/rotate-secret
Authentication: session token · Permission: manage_producers · Scope: per Producer: also its maintainers
Requires the manage_producers permission, or maintainership of the Producer named in the path.
A fresh secret, shown once; deliveries from now on are signed with it.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string | |
id | path | yes | integer |
Responses
| Status | Description | Body |
|---|---|---|
200 | The hook and its new secret. | WebhookCreated
Example 200 response (placeholder values derived from the schema) |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without what this endpoint requires. | ErrorBody |
404 | No such hook in this scope. | — |
/admin/producers/{name}/webhooks/{id}/deliveries#
GET /admin/producers/{name}/webhooks/{id}/deliveries#
Read: producers/name/webhooks/id/deliveries
Authentication: session token · Permission: manage_producers · Scope: per Producer: also its maintainers
Requires the manage_producers permission, or maintainership of the Producer named in the path.
The newest deliveries of the hook (limit, default 50, at most 200): status, attempts, next attempt, last response code and error.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string | |
id | path | yes | integer |
Responses
| Status | Description | Body |
|---|---|---|
200 | The delivery log. | WebhookDeliveryList
Example 200 response (placeholder values derived from the schema) |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without what this endpoint requires. | ErrorBody |
404 | No such hook in this scope. | — |
/admin/producers/{name}/webhooks/{id}/deliveries/{delivery_id}/redeliver#
POST /admin/producers/{name}/webhooks/{id}/deliveries/{delivery_id}/redeliver#
Create or run: producers/name/webhooks/id/deliveries/delivery_id/redeliver
Authentication: session token · Permission: manage_producers · Scope: per Producer: also its maintainers
Requires the manage_producers permission, or maintainership of the Producer named in the path.
Reset one delivery to pending, due now, attempt count kept — one more attempt even for a dead delivery.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string | |
id | path | yes | integer | |
delivery_id | path | yes | integer |
Responses
| Status | Description | Body |
|---|---|---|
202 | Reset; the delivery as it now is. | WebhookDelivery
Example 202 response (placeholder values derived from the schema) |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without what this endpoint requires. | ErrorBody |
404 | No such delivery on this hook. | — |
/admin/consumers/{name}/webhooks#
GET /admin/consumers/{name}/webhooks#
Read: consumers/name/webhooks
Authentication: session token · Permission: manage_producers · Scope: per Consumer: also maintainers of the Producer of the same name
Requires the manage_producers permission, or maintainership of the Producer of the same name as the Consumer in the path (the "same system" rule).
The hooks of this scope, newest last, without their secrets (secret_hint is a prefix of the secret's SHA-256).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string |
Responses
| Status | Description | Body |
|---|---|---|
200 | The hooks. | WebhookList
Example 200 response (placeholder values derived from the schema) |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without what this endpoint requires. | ErrorBody |
POST /admin/consumers/{name}/webhooks#
Create or run: consumers/name/webhooks
Authentication: session token · Permission: manage_producers · Scope: per Consumer: also maintainers of the Producer of the same name
Requires the manage_producers permission, or maintainership of the Producer of the same name as the Consumer in the path (the "same system" rule).
Register a hook (WebhookCreate). The URL must be https://, or http:// to a host the allow-list names with http://; callers without manage_settings are refused outside the allow-list (and with an empty allow-list), callers with it are exempt for good. The answer carries the signing secret once.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string |
Responses
| Status | Description | Body |
|---|---|---|
201 | Registered; the secret is shown once. | WebhookCreated
Example 201 response (placeholder values derived from the schema) |
400 | Not a valid hook (URL, format, event type or glob). | — |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without what this endpoint requires. | ErrorBody |
/admin/consumers/{name}/webhooks/{id}#
GET /admin/consumers/{name}/webhooks/{id}#
Read: consumers/name/webhooks/id
Authentication: session token · Permission: manage_producers · Scope: per Consumer: also maintainers of the Producer of the same name
Requires the manage_producers permission, or maintainership of the Producer of the same name as the Consumer in the path (the "same system" rule).
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string | |
id | path | yes | integer |
Responses
| Status | Description | Body |
|---|---|---|
200 | The hook. | Webhook
Example 200 response (placeholder values derived from the schema) |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without what this endpoint requires. | ErrorBody |
404 | No such hook in this scope. | — |
PATCH /admin/consumers/{name}/webhooks/{id}#
Update: consumers/name/webhooks/id
Authentication: session token · Permission: manage_producers · Scope: per Consumer: also maintainers of the Producer of the same name
Requires the manage_producers permission, or maintainership of the Producer of the same name as the Consumer in the path (the "same system" rule).
Pause or resume (paused), replace the event-type filter (event_types, [] = every type) or the Producer glob (producer_glob, null clears it). Fields left out stay as they are.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string | |
id | path | yes | integer |
Responses
| Status | Description | Body |
|---|---|---|
200 | The hook after the patch. | Webhook
Example 200 response (placeholder values derived from the schema) |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without what this endpoint requires. | ErrorBody |
404 | No such hook in this scope. | — |
DELETE /admin/consumers/{name}/webhooks/{id}#
Delete: consumers/name/webhooks/id
Authentication: session token · Permission: manage_producers · Scope: per Consumer: also maintainers of the Producer of the same name
Requires the manage_producers permission, or maintainership of the Producer of the same name as the Consumer in the path (the "same system" rule).
Deletes the hook and its delivery log.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string | |
id | path | yes | integer |
Responses
/admin/consumers/{name}/webhooks/{id}/test#
POST /admin/consumers/{name}/webhooks/{id}/test#
Create or run: consumers/name/webhooks/id/test
Authentication: session token · Permission: manage_producers · Scope: per Consumer: also maintainers of the Producer of the same name
Requires the manage_producers permission, or maintainership of the Producer of the same name as the Consumer in the path (the "same system" rule).
Queue a webhook.test event for this hook alone; the worker delivers it like any other event, so the delivery log shows whether the receiver, the secret and the allow-list are in order.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string | |
id | path | yes | integer |
Responses
/admin/consumers/{name}/webhooks/{id}/rotate-secret#
POST /admin/consumers/{name}/webhooks/{id}/rotate-secret#
Create or run: consumers/name/webhooks/id/rotate-secret
Authentication: session token · Permission: manage_producers · Scope: per Consumer: also maintainers of the Producer of the same name
Requires the manage_producers permission, or maintainership of the Producer of the same name as the Consumer in the path (the "same system" rule).
A fresh secret, shown once; deliveries from now on are signed with it.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string | |
id | path | yes | integer |
Responses
| Status | Description | Body |
|---|---|---|
200 | The hook and its new secret. | WebhookCreated
Example 200 response (placeholder values derived from the schema) |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without what this endpoint requires. | ErrorBody |
404 | No such hook in this scope. | — |
/admin/consumers/{name}/webhooks/{id}/deliveries#
GET /admin/consumers/{name}/webhooks/{id}/deliveries#
Read: consumers/name/webhooks/id/deliveries
Authentication: session token · Permission: manage_producers · Scope: per Consumer: also maintainers of the Producer of the same name
Requires the manage_producers permission, or maintainership of the Producer of the same name as the Consumer in the path (the "same system" rule).
The newest deliveries of the hook (limit, default 50, at most 200): status, attempts, next attempt, last response code and error.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string | |
id | path | yes | integer |
Responses
| Status | Description | Body |
|---|---|---|
200 | The delivery log. | WebhookDeliveryList
Example 200 response (placeholder values derived from the schema) |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without what this endpoint requires. | ErrorBody |
404 | No such hook in this scope. | — |
/admin/consumers/{name}/webhooks/{id}/deliveries/{delivery_id}/redeliver#
POST /admin/consumers/{name}/webhooks/{id}/deliveries/{delivery_id}/redeliver#
Create or run: consumers/name/webhooks/id/deliveries/delivery_id/redeliver
Authentication: session token · Permission: manage_producers · Scope: per Consumer: also maintainers of the Producer of the same name
Requires the manage_producers permission, or maintainership of the Producer of the same name as the Consumer in the path (the "same system" rule).
Reset one delivery to pending, due now, attempt count kept — one more attempt even for a dead delivery.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
name | path | yes | string | |
id | path | yes | integer | |
delivery_id | path | yes | integer |
Responses
| Status | Description | Body |
|---|---|---|
202 | Reset; the delivery as it now is. | WebhookDelivery
Example 202 response (placeholder values derived from the schema) |
401 | Not signed in. | ErrorBody |
403 | Signed in, but without what this endpoint requires. | ErrorBody |
404 | No such delivery on this hook. | — |
/admin/settings/webhook-allowed-hosts#
GET /admin/settings/webhook-allowed-hosts#
Read: settings/webhook-allowed-hosts
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
The egress allow-list: host patterns a hook URL may point at.
Responses
POST /admin/settings/webhook-allowed-hosts#
Create or run: settings/webhook-allowed-hosts
Authentication: session token · Permission: manage_settings · Scope: global
Requires the manage_settings permission.
Replace the allow-list ({"hosts": [...]}). A pattern is a host name with */? wildcards (hooks.slack.com, *.webhook.office.com); prefixed http:// it also admits plain HTTP to that host (http://n8n.corp.internal). Ports are not matched. An empty list means only callers with manage_settings may register hooks. Evaluated at registration and again at every delivery.
Responses
/admin/users#
GET /admin/users#
Read: users
Authentication: session token · Permission: manage_users · Scope: global
Requires the manage_users permission.
Responses
/admin/users/{id}#
DELETE /admin/users/{id}#
Delete: users/id
Authentication: session token · Permission: manage_users · Scope: global
Requires the manage_users permission. Deleting a user who holds an admin-guarded role (admin, releaser) — directly or via a stored group — strips those roles at once, and deleting a configured root account un-claims the reserved name, so both additionally require the caller to be an admin.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
id | path | yes | integer |
Responses
/admin/users/{id}/approve#
POST /admin/users/{id}/approve#
Create or run: users/id/approve
Authentication: session token · Permission: manage_users · Scope: global
Requires the manage_users permission.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
id | path | yes | integer |
Responses
/admin/users/{id}/maintains#
GET /admin/users/{id}/maintains#
Read: users/id/maintains
Authentication: session token · Permission: manage_roles · Scope: global
Requires the manage_roles permission.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
id | path | yes | integer |
Responses
/admin/users/{id}/roles#
GET /admin/users/{id}/roles#
Read: users/id/roles
Authentication: session token · Permission: manage_roles · Scope: global
Requires the manage_roles permission.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
id | path | yes | integer |
Responses
POST /admin/users/{id}/roles#
Create or run: users/id/roles
Authentication: session token · Permission: manage_roles · Scope: global
Requires the manage_roles permission. Granting an admin-guarded role (admin, releaser) additionally requires the caller to be an admin.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
id | path | yes | integer |
Responses
/admin/users/{id}/roles/{role}#
DELETE /admin/users/{id}/roles/{role}#
Delete: users/id/roles/role
Authentication: session token · Permission: manage_roles · Scope: global
Requires the manage_roles permission. Revoking an admin-guarded role (admin, releaser) additionally requires the caller to be an admin.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
id | path | yes | integer | |
role | path | yes | string |
Responses
Schemas#
SystemContext#
What a system's Backstage catalog-info.yaml says about it (#48), read from the Component named like the system: spec.owner, metadata.description, the backstage.io/source-location annotation and metadata.links. One per system, replaced on every catalog push; a field the file does not have is null or empty.
| Field | Type | Required | Description |
|---|---|---|---|
owner | object | null | yes | The owner ref's kind ( |
owner.kind | string | yes | |
owner.name | string | yes | |
description | string | null | yes | Trimmed, at most 1000 characters (a longer one is cut with an ellipsis). |
source_location | string | null | yes | The annotation without its |
links | object[] | yes | At most 20; a link whose |
links[].url | string | yes | |
links[].title | string | yes | The link's title, or the URL's host when it has none. |
links[].type | string | null | yes | |
links[].icon | string | null | yes |
Example (placeholder values derived from the schema)
{
"owner": {
"kind": "string",
"name": "string"
},
"description": "string",
"source_location": "string",
"links": [
{
"url": "string",
"title": "string",
"type": "string",
"icon": "string"
}
]
}
ParticipantContext#
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | |
context | SystemContext | yes | What a system's Backstage |
Example (placeholder values derived from the schema)
{
"name": "string",
"context": {
"owner": {
"kind": "string",
"name": "string"
},
"description": "string",
"source_location": "string",
"links": [
{
"url": "string",
"title": "string",
"type": "string",
"icon": "string"
}
]
}
}
WebhookScope#
Who a hook belongs to (#47).
| Field | Type | Required | Description |
|---|---|---|---|
kind | string | yes | One of |
name | string | — | The Producer or Consumer; absent for |
Example (placeholder values derived from the schema)
{
"kind": "global",
"name": "string"
}
Webhook#
A registered hook (#47). The signing secret is never part of it; secret_hint is the first 8 hex characters of the secret's SHA-256, to tell hooks apart.
| Field | Type | Required | Description |
|---|---|---|---|
id | integer (int64) | yes | |
scope | WebhookScope | yes | Who a hook belongs to (#47). |
url | string | yes | |
format | string | yes | One of |
event_types | string[] | yes | The event types the hook receives; empty means every type. |
producer_glob | string | null | yes | Only events about Producers whose name matches ( |
secret_hint | string | yes | |
paused | boolean | yes | |
allow_list_exempt | boolean | yes | Registered by a caller with |
created_by | string | yes | |
created_at | string | yes |
Example (placeholder values derived from the schema)
{
"id": 1,
"scope": {
"kind": "global",
"name": "string"
},
"url": "string",
"format": "json",
"event_types": [
"string"
],
"producer_glob": "string",
"secret_hint": "string",
"paused": false,
"allow_list_exempt": false,
"created_by": "string",
"created_at": "string"
}
WebhookList#
Type: Webhook[].
WebhookCreate#
| Field | Type | Required | Description |
|---|---|---|---|
url | string | yes | |
format | string | — | One of Default |
event_types | string[] | — | Empty or absent means every type; |
producer_glob | string | null | — |
Example (placeholder values derived from the schema)
{
"url": "string",
"format": "json",
"event_types": [
"string"
],
"producer_glob": "string"
}
WebhookCreated#
| Field | Type | Required | Description |
|---|---|---|---|
webhook | Webhook | yes | A registered hook (#47). The signing secret is never part of it; |
secret | string | yes | The signing secret, shown this once ( |
Example (placeholder values derived from the schema)
{
"webhook": {
"id": 1,
"scope": {
"kind": "global",
"name": "string"
},
"url": "string",
"format": "json",
"event_types": [
"string"
],
"producer_glob": "string",
"secret_hint": "string",
"paused": false,
"allow_list_exempt": false,
"created_by": "string",
"created_at": "string"
},
"secret": "string"
}
WebhookDelivery#
One hook's delivery of one event — a delivery log row (#47).
| Field | Type | Required | Description |
|---|---|---|---|
id | integer (int64) | yes | |
hook_id | integer (int64) | yes | |
event_id | string | yes | |
event_type | string | yes | |
occurred_at | string | yes | |
status | string | yes | One of |
attempts | integer | yes | |
next_attempt_at | string | yes | |
last_response_code | integer | null | yes | |
last_error | string | null | yes | |
delivered_at | string | null | yes | |
updated_at | string | yes |
Example (placeholder values derived from the schema)
{
"id": 1,
"hook_id": 1,
"event_id": "string",
"event_type": "string",
"occurred_at": "string",
"status": "pending",
"attempts": 0,
"next_attempt_at": "string",
"last_response_code": 0,
"last_error": "string",
"delivered_at": "string",
"updated_at": "string"
}
WebhookDeliveryList#
Type: WebhookDelivery[].
ErrorBody#
The body every error response carries. Identical to the schema of the same name in api.yaml.
| Field | Type | Required | Description |
|---|---|---|---|
error | string | yes | |
proposed_version | string | — |
Example (placeholder values derived from the schema)
{
"error": "string",
"proposed_version": "string"
}
ConnectionTestFailure#
The 400 of POST /admin/auth-config/test: an ErrorBody whose diagnostics is present only when the directory was unreachable.
| Field | Type | Required | Description |
|---|---|---|---|
error | string | yes | |
diagnostics | string[] | — | One line per finding, in reading order. |
Example (placeholder values derived from the schema)
{
"error": "LDAP connection failed: Could not connect to LDAP server at ldaps://ldap.example.com:636: this container has no route to 10.1.2.3: check the network, VPN or Docker network of the pod",
"diagnostics": [
"DNS: ldap.example.com resolves to 10.1.2.3 (1.2 ms)",
"Resolvers: 10.96.0.10 (search default.svc.cluster.local, svc.cluster.local, cluster.local)",
"10.1.2.3: ping no route; route no route from this container; tcp/636 no route"
]
}