Documentation for v2.6.1. Read the latest, v2.12.0.

Reference

Maintenance API

maintenance.yaml version 2.6.1

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.

107 operations state no permission; the description of each has no "Requires the … permission" sentence.

Endpoints#

MethodPathSummaryPermissionScope
GET/admin/auth-configRead: auth-confignot statednot stated
PUT/admin/auth-configReplace: auth-confignot statednot stated
POST/admin/auth-config/testCreate or run: auth-config/testnot statednot stated
GET/admin/backup/sqliteRead: backup/sqlitenot statednot stated
GET/admin/branches/{name}/timelineRead: branches/name/timelinenot statednot stated
GET/admin/trunk/graphRead: trunk/graphnot statednot stated
GET/admin/trunk/timelineRead: trunk/timelinenot statednot stated
POST/admin/cache/clearCreate or run: cache/clearnot statednot stated
POST/admin/cleanup/dependenciesCreate or run: cleanup/dependenciesnot statednot stated
POST/admin/cleanup/trunkCreate or run: cleanup/trunknot statednot stated
POST/admin/cleanup/snapshotsCreate or run: cleanup/snapshotsnot statednot stated
GET/admin/consumersRead: consumersnot statednot stated
GET/admin/consumers/{name}Read: consumers/namenot statednot stated
DELETE/admin/consumers/{name}Delete: consumers/namenot statednot stated
GET/admin/consumers/{name}/endpointsRead: consumers/name/endpointsnot statednot stated
GET/admin/endpoint-versionsRead: endpoint-versionsnot statednot stated
GET/admin/endpoint-yamlRead: endpoint-yamlnot statednot stated
GET/admin/groupsRead: groupsnot statednot stated
POST/admin/groupsCreate or run: groupsnot statednot stated
PUT/admin/groups/{id}Replace: groups/idnot statednot stated
DELETE/admin/groups/{id}Delete: groups/idnot statednot stated
POST/admin/groups/{id}/membersCreate or run: groups/id/membersnot statednot stated
DELETE/admin/groups/{id}/members/{user_id}Delete: groups/id/members/user_idnot statednot stated
GET/admin/maintainersRead: maintainersnot statednot stated
POST/admin/nuke/consumersCreate or run: nuke/consumersnot statednot stated
POST/admin/nuke/databaseCreate or run: nuke/databasenot statednot stated
POST/admin/nuke/producersCreate or run: nuke/producersnot statednot stated
POST/admin/nuke/usersCreate or run: nuke/usersnot statednot stated
GET/admin/observability/audit-logsRead: observability/audit-logsnot statednot stated
GET/admin/observability/audit-logs/exportRead: observability/audit-logs/exportnot statednot stated
GET/admin/observability/debug-configRead: observability/debug-confignot statednot stated
POST/admin/observability/debug-config-updateCreate or run: observability/debug-config-updatenot statednot stated
GET/admin/observability/logsRead: observability/logsnot statednot stated
GET/admin/observability/statsRead: observability/statsnot statednot stated
GET/admin/graph/diffRead: graph/diffnot statednot stated
GET/admin/peripheryRead: peripherynot statednot stated
GET/admin/graph/scopeRead: graph scopenot statednot stated
GET/admin/producersRead: producersnot statednot stated
POST/admin/producers/metadataCreate or run: producers/metadatanot statednot stated
GET/admin/producers/{name}Read: producers/namenot statednot stated
DELETE/admin/producers/{name}Delete: producers/namenot statednot stated
GET/admin/producers/{name}/branch-membershipsRead: producers/name/branch-membershipsnot statednot stated
GET/admin/producers/{name}/diffRead: producers/name/diffnot statednot stated
GET/admin/producers/{name}/blameRead: producers/name/blamenot statednot stated
GET/admin/branchesRead: branchesnot statednot stated
POST/admin/branchesWrite: branchesnot statednot stated
PUT/admin/branches/{name}Write: branches/namenot statednot stated
DELETE/admin/branches/{name}Write: branches/namenot statednot stated
GET/admin/branches/{name}/graphRead: branches/name/graphnot statednot stated
GET/admin/producers/{name}/endpointsRead: producers/name/endpointsnot statednot stated
GET/admin/producers/{name}/full-specRead: producers/name/full-specnot statednot stated
GET/admin/producers/{name}/maintainersRead: producers/name/maintainersnot statednot stated
POST/admin/producers/{name}/maintainersCreate or run: producers/name/maintainersnot statednot stated
DELETE/admin/producers/{name}/maintainers/groups/{group_id}Delete: producers/name/maintainers/groups/group_idnot statednot stated
DELETE/admin/producers/{name}/maintainers/users/{user_id}Delete: producers/name/maintainers/users/user_idnot statednot stated
GET/admin/producers/{name}/versionsRead: producers/name/versionsnot statednot stated
DELETE/admin/producers/{name}/versions/{api_type}/{version}Delete: producers/name/versions/api_type/versionnot statednot stated
POST/admin/producers/{name}/versions/{api_type}/{version}/promoteWrite: producers/name/versions/api_type/version/promotenot statednot stated
GET/admin/producers/{name}/versions/{api_type}/{version}/dependentsRead: producers/name/versions/api_type/version/dependentsnot statednot stated
GET/admin/rolesRead: rolesnot statednot stated
GET/admin/settings/auto-approveRead: settings/auto-approvenot statednot stated
POST/admin/settings/auto-approveCreate or run: settings/auto-approvenot statednot stated
GET/admin/settings/cacheRead: settings/cachenot statednot stated
POST/admin/settings/cacheCreate or run: settings/cachenot statednot stated
GET/admin/settings/databaseRead: settings/databasenot statednot stated
GET/admin/settings/dependency-max-ageRead: settings/dependency-max-agenot statednot stated
POST/admin/settings/dependency-max-ageCreate or run: settings/dependency-max-agenot statednot stated
GET/admin/settings/trunk-max-ageRead: settings/trunk-max-agenot statednot stated
POST/admin/settings/trunk-max-ageCreate or run: settings/trunk-max-agenot statednot stated
GET/admin/settings/snapshot-max-ageRead: settings/snapshot-max-agenot statednot stated
POST/admin/settings/snapshot-max-ageCreate or run: settings/snapshot-max-agenot statednot stated
GET/admin/webhooksRead: webhooks/webhooksnot statednot stated
POST/admin/webhooksCreate or run: webhooks/webhooksnot statednot stated
GET/admin/webhooks/{id}Read: webhooks/webhooks/idnot statednot stated
PATCH/admin/webhooks/{id}Update: webhooks/webhooks/idnot statednot stated
DELETE/admin/webhooks/{id}Delete: webhooks/webhooks/idnot statednot stated
POST/admin/webhooks/{id}/testCreate or run: webhooks/webhooks/id/testnot statednot stated
POST/admin/webhooks/{id}/rotate-secretCreate or run: webhooks/webhooks/id/rotate-secretnot statednot stated
GET/admin/webhooks/{id}/deliveriesRead: webhooks/webhooks/id/deliveriesnot statednot stated
POST/admin/webhooks/{id}/deliveries/{delivery_id}/redeliverCreate or run: webhooks/webhooks/id/deliveries/delivery_id/redelivernot statednot stated
GET/admin/producers/{name}/webhooksRead: producers/name/webhooksnot statednot stated
POST/admin/producers/{name}/webhooksCreate or run: producers/name/webhooksnot statednot stated
GET/admin/producers/{name}/webhooks/{id}Read: producers/name/webhooks/idnot statednot stated
PATCH/admin/producers/{name}/webhooks/{id}Update: producers/name/webhooks/idnot statednot stated
DELETE/admin/producers/{name}/webhooks/{id}Delete: producers/name/webhooks/idnot statednot stated
POST/admin/producers/{name}/webhooks/{id}/testCreate or run: producers/name/webhooks/id/testnot statednot stated
POST/admin/producers/{name}/webhooks/{id}/rotate-secretCreate or run: producers/name/webhooks/id/rotate-secretnot statednot stated
GET/admin/producers/{name}/webhooks/{id}/deliveriesRead: producers/name/webhooks/id/deliveriesnot statednot stated
POST/admin/producers/{name}/webhooks/{id}/deliveries/{delivery_id}/redeliverCreate or run: producers/name/webhooks/id/deliveries/delivery_id/redelivernot statednot stated
GET/admin/consumers/{name}/webhooksRead: consumers/name/webhooksnot statednot stated
POST/admin/consumers/{name}/webhooksCreate or run: consumers/name/webhooksnot statednot stated
GET/admin/consumers/{name}/webhooks/{id}Read: consumers/name/webhooks/idnot statednot stated
PATCH/admin/consumers/{name}/webhooks/{id}Update: consumers/name/webhooks/idnot statednot stated
DELETE/admin/consumers/{name}/webhooks/{id}Delete: consumers/name/webhooks/idnot statednot stated
POST/admin/consumers/{name}/webhooks/{id}/testCreate or run: consumers/name/webhooks/id/testnot statednot stated
POST/admin/consumers/{name}/webhooks/{id}/rotate-secretCreate or run: consumers/name/webhooks/id/rotate-secretnot statednot stated
GET/admin/consumers/{name}/webhooks/{id}/deliveriesRead: consumers/name/webhooks/id/deliveriesnot statednot stated
POST/admin/consumers/{name}/webhooks/{id}/deliveries/{delivery_id}/redeliverCreate or run: consumers/name/webhooks/id/deliveries/delivery_id/redelivernot statednot stated
GET/admin/settings/webhook-allowed-hostsRead: settings/webhook-allowed-hostsnot statednot stated
POST/admin/settings/webhook-allowed-hostsCreate or run: settings/webhook-allowed-hostsnot statednot stated
GET/admin/usersRead: usersnot statednot stated
DELETE/admin/users/{id}Delete: users/idnot statednot stated
POST/admin/users/{id}/approveCreate or run: users/id/approvenot statednot stated
GET/admin/users/{id}/maintainsRead: users/id/maintainsnot statednot stated
GET/admin/users/{id}/rolesRead: users/id/rolesnot statednot stated
POST/admin/users/{id}/rolesCreate or run: users/id/rolesnot statednot stated
DELETE/admin/users/{id}/roles/{role}Delete: users/id/roles/rolenot statednot stated

/admin/auth-config#

GET /admin/auth-config#

Read: auth-config

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_auth_config permission.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

PUT /admin/auth-config#

Replace: auth-config

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_auth_config permission.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/auth-config/test#

POST /admin/auth-config/test#

Create or run: auth-config/test

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_auth_config permission.

Responses

StatusDescriptionBody
200

Success.

—
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: not stated · Permission: not stated · Scope: not stated

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

StatusDescriptionBody
200

The database snapshot.

string (binary) (application/vnd.sqlite3)
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody
409

A snapshot is already being produced, or this instance runs PostgreSQL — the message names pg_dump.

ErrorBody

/admin/branches/{name}/timeline#

GET /admin/branches/{name}/timeline#

Read: branches/name/timeline

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring

Responses

StatusDescriptionBody
200

The change instants as a JSON array of RFC 3339 strings.

—
401

Not signed in.

ErrorBody
404

No sanshain-branch with this name.

ErrorBody

/admin/trunk/graph#

GET /admin/trunk/graph#

Read: trunk/graph

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
atquery—string

Responses

StatusDescriptionBody
200

The pin set as a JSON array.

—
401

Not signed in.

ErrorBody

/admin/trunk/timeline#

GET /admin/trunk/timeline#

Read: trunk/timeline

Authentication: not stated · Permission: not stated · Scope: not stated

The instants the main graph changed, distinct and ascending — the timeline slider's markers (ADR-0005).

Responses

StatusDescriptionBody
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: not stated · Permission: not stated · Scope: not stated

Requires the manage_settings permission.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/cleanup/dependencies#

POST /admin/cleanup/dependencies#

Create or run: cleanup/dependencies

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_settings permission.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/cleanup/trunk#

POST /admin/cleanup/trunk#

Create or run: cleanup/trunk

Authentication: not stated · Permission: not stated · Scope: not stated

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

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/cleanup/snapshots#

POST /admin/cleanup/snapshots#

Create or run: cleanup/snapshots

Authentication: not stated · Permission: not stated · Scope: not stated

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

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/consumers#

GET /admin/consumers#

Read: consumers

Authentication: not stated · Permission: not stated · Scope: not stated

Any signed-in caller.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/consumers/{name}#

GET /admin/consumers/{name}#

Read: consumers/name

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring

Responses

StatusDescriptionBody
200

The Consumer's name and context.

ParticipantContext

Example 200 response (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"
      }
    ]
  }
}
401

Not signed in.

ErrorBody
404

No such Consumer.

ErrorBody

DELETE /admin/consumers/{name}#

Delete: consumers/name

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/consumers/{name}/endpoints#

GET /admin/consumers/{name}/endpoints#

Read: consumers/name/endpoints

Authentication: not stated · Permission: not stated · Scope: not stated

Any signed-in caller.

Every endpoint the Consumer is recorded as depending on, with the pinned version and its current stability.

Parameters

NameInRequiredTypeDescription
namepathyesstring

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/endpoint-versions#

GET /admin/endpoint-versions#

Read: endpoint-versions

Authentication: not stated · Permission: not stated · Scope: not stated

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

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/endpoint-yaml#

GET /admin/endpoint-yaml#

Read: endpoint-yaml

Authentication: not stated · Permission: not stated · Scope: not stated

Any signed-in caller.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/groups#

GET /admin/groups#

Read: groups

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_roles permission.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

POST /admin/groups#

Create or run: groups

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_roles permission.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/groups/{id}#

PUT /admin/groups/{id}#

Replace: groups/id

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
idpathyesinteger

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

DELETE /admin/groups/{id}#

Delete: groups/id

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
idpathyesinteger

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/groups/{id}/members#

POST /admin/groups/{id}/members#

Create or run: groups/id/members

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
idpathyesinteger

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/groups/{id}/members/{user_id}#

DELETE /admin/groups/{id}/members/{user_id}#

Delete: groups/id/members/user_id

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
idpathyesinteger
user_idpathyesinteger

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/maintainers#

GET /admin/maintainers#

Read: maintainers

Authentication: not stated · Permission: not stated · Scope: not stated

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

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/nuke/consumers#

POST /admin/nuke/consumers#

Create or run: nuke/consumers

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the run_destructive_operations permission.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/nuke/database#

POST /admin/nuke/database#

Create or run: nuke/database

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the run_destructive_operations permission.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/nuke/producers#

POST /admin/nuke/producers#

Create or run: nuke/producers

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the run_destructive_operations permission.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/nuke/users#

POST /admin/nuke/users#

Create or run: nuke/users

Authentication: not stated · Permission: not stated · Scope: not stated

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

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/observability/audit-logs#

GET /admin/observability/audit-logs#

Read: observability/audit-logs

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the view_audit permission. The most recent audit entries for the observability panel; optional limit (default 100, capped at 200).

Parameters

NameInRequiredTypeDescription
limitquery—integer

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/observability/audit-logs/export#

GET /admin/observability/audit-logs/export#

Read: observability/audit-logs/export

Authentication: not stated · Permission: not stated · Scope: not stated

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

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/observability/debug-config#

GET /admin/observability/debug-config#

Read: observability/debug-config

Authentication: not stated · Permission: not stated · Scope: not stated

Any signed-in caller.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/observability/debug-config-update#

POST /admin/observability/debug-config-update#

Create or run: observability/debug-config-update

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_settings permission.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/observability/logs#

GET /admin/observability/logs#

Read: observability/logs

Authentication: not stated · Permission: not stated · Scope: not stated

Any signed-in caller.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/observability/stats#

GET /admin/observability/stats#

Read: observability/stats

Authentication: not stated · Permission: not stated · Scope: not stated

Any signed-in caller.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/graph/diff#

GET /admin/graph/diff#

Read: graph/diff

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
leftqueryyesstring
rightqueryyesstring

Responses

StatusDescriptionBody
200

The structured diff.

—
401

Not signed in.

ErrorBody
404

A named branch does not exist.

ErrorBody

/admin/periphery#

GET /admin/periphery#

Read: periphery

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
scopequery—string

Responses

StatusDescriptionBody
200

A JSON array of {system, resource} edges, sorted.

—
400

A selector instant that is not RFC 3339, or dev@….

ErrorBody
401

Not signed in.

ErrorBody
404

A named branch does not exist.

ErrorBody

/admin/graph/scope#

GET /admin/graph/scope#

Read: graph scope

Authentication: not stated · Permission: not stated · Scope: not stated

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. stability is null when the version was deleted since; last_provided_at is the latest provide known at the instant (null when 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 Backstage catalog-info.yaml — so the node panel needs no extra request. A present-day fact, the same in every scope.

Parameters

NameInRequiredTypeDescription
scopequery—string

Responses

StatusDescriptionBody
200

The scope's producers, harvested subscriptions and system contexts.

object

Example 200 response (placeholder values derived from the schema)

{
  "producers": [
    {
      "name": "string",
      "versions": [
        {
          "api_type": "openapi",
          "version": "string",
          "stability": "snapshot",
          "last_provided_at": "string"
        }
      ]
    }
  ],
  "harvested_subscriptions": [
    {
      "client": "string",
      "channel": "string",
      "message_name": "string",
      "owner": "string",
      "trunk": false
    }
  ],
  "systems": {
    "key": {
      "owner": {
        "kind": "string",
        "name": "string"
      },
      "description": "string",
      "source_location": "string",
      "links": [
        {
          "url": "string",
          "title": "string",
          "type": "string",
          "icon": "string"
        }
      ]
    }
  }
}
400

A selector instant that is not RFC 3339, or dev@….

ErrorBody
401

Not signed in.

ErrorBody
404

A named branch does not exist.

ErrorBody

/admin/producers#

GET /admin/producers#

Read: producers

Authentication: not stated · Permission: not stated · Scope: not stated

Any signed-in caller.

Every Producer with metadata and its full version lines (version, stability, endpoint count, snapshot expiry).

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/producers/metadata#

POST /admin/producers/metadata#

Create or run: producers/metadata

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_producers permission.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/producers/{name}#

GET /admin/producers/{name}#

Read: producers/name

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring

Responses

StatusDescriptionBody
200

The Producer's name and context.

ParticipantContext

Example 200 response (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"
      }
    ]
  }
}
401

Not signed in.

ErrorBody
404

No such Producer.

ErrorBody

DELETE /admin/producers/{name}#

Delete: producers/name

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/producers/{name}/branch-memberships#

GET /admin/producers/{name}/branch-memberships#

Read: producers/name/branch-memberships

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring

Responses

StatusDescriptionBody
200

The memberships as a JSON array.

—
401

Not signed in.

ErrorBody
404

Producer not found.

ErrorBody

/admin/producers/{name}/diff#

GET /admin/producers/{name}/diff#

Read: producers/name/diff

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring
api_typequery—string

One of openapi, asyncapi, proto.

Default "openapi".

fromqueryyesstring

The old side's version.

toqueryyesstring

The new side's version.

pathquery—string

Diff this endpoint's snippet instead of the document; needs method.

methodquery—string

The endpoint's method (or RPC/operation); needs path.

ignore_whitespacequery—boolean

Compare lines without leading and trailing whitespace, so indentation and trailing-whitespace differences are not changes.

Default false.

contextquery—string

Unchanged lines kept around each change, or all for the whole document in one hunk.

Default "3".

formatquery—string

text answers a unified-diff patch (empty when nothing differs). json answers {from, to, hunks}; each hunk has old_start, old_len, new_start, new_len and lines of {op: ctx|add|del, old_no, new_no, text, old_text?} (old_text only on a context line whose old side differs in whitespace).

One of text, json.

Default "text".

Responses

StatusDescriptionBody
200

The diff, as text/plain or JSON per format.

—
400

Only one of path/method, or a malformed context or format.

ErrorBody
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody
404

The Producer or one of the two versions does not exist.

ErrorBody

/admin/producers/{name}/blame#

GET /admin/producers/{name}/blame#

Read: producers/name/blame

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring
api_typequery—string

One of openapi, asyncapi, proto.

Default "openapi".

versionqueryyesstring

The version to blame.

pathquery—string

Blame this endpoint's snippet instead of the document; needs method.

methodquery—string

The endpoint's method (or RPC/operation); needs path.

Responses

StatusDescriptionBody
200

The blame blocks.

—
400

Only one of path/method.

ErrorBody
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody
404

The Producer or the version does not exist.

ErrorBody

/admin/branches#

GET /admin/branches#

Read: branches

Authentication: not stated · Permission: not stated · Scope: not stated

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

StatusDescriptionBody
200

The branch listing as a JSON array.

—
401

Not signed in.

ErrorBody

POST /admin/branches#

Write: branches

Authentication: not stated · Permission: not stated · Scope: not stated

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

StatusDescriptionBody
201

Created. The body is the branch record (see GET).

—
400

Empty or reserved name (main, dev, trunk), or as_of is not an RFC 3339 instant.

ErrorBody
401

Not signed in.

ErrorBody
403

Signed in, but without the release_ga permission.

ErrorBody
404

The source branch does not exist. Nothing was created.

ErrorBody
409

A branch with this name already exists.

ErrorBody

/admin/branches/{name}#

PUT /admin/branches/{name}#

Write: branches/name

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring

Responses

StatusDescriptionBody
200

Renamed; the body is the updated branch record.

—
400

Empty new name.

ErrorBody
401

Not signed in.

ErrorBody
403

Signed in, but not an admin.

ErrorBody
404

No sanshain-branch with this name.

ErrorBody
409

The new name is already taken by a live branch.

ErrorBody

DELETE /admin/branches/{name}#

Write: branches/name

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring

Responses

StatusDescriptionBody
204

Deleted.

—
401

Not signed in.

ErrorBody
403

Signed in, but not an admin.

ErrorBody
404

No sanshain-branch with this name.

ErrorBody

/admin/branches/{name}/graph#

GET /admin/branches/{name}/graph#

Read: branches/name/graph

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring
atquery—string

Responses

StatusDescriptionBody
200

The pin set as a JSON array.

—
401

Not signed in.

ErrorBody
404

No sanshain-branch with this name.

ErrorBody

/admin/producers/{name}/endpoints#

GET /admin/producers/{name}/endpoints#

Read: producers/name/endpoints

Authentication: not stated · Permission: not stated · Scope: not stated

Any signed-in caller.

The endpoints of one version-line entry (api_type, version query parameters).

Parameters

NameInRequiredTypeDescription
namepathyesstring

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/producers/{name}/full-spec#

GET /admin/producers/{name}/full-spec#

Read: producers/name/full-spec

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/producers/{name}/maintainers#

GET /admin/producers/{name}/maintainers#

Read: producers/name/maintainers

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_producers permission, or maintainership of the Producer named in the path.

Parameters

NameInRequiredTypeDescription
namepathyesstring

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

POST /admin/producers/{name}/maintainers#

Create or run: producers/name/maintainers

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_roles permission.

Parameters

NameInRequiredTypeDescription
namepathyesstring

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/producers/{name}/maintainers/groups/{group_id}#

DELETE /admin/producers/{name}/maintainers/groups/{group_id}#

Delete: producers/name/maintainers/groups/group_id

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_roles permission.

Parameters

NameInRequiredTypeDescription
namepathyesstring
group_idpathyesinteger

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/producers/{name}/maintainers/users/{user_id}#

DELETE /admin/producers/{name}/maintainers/users/{user_id}#

Delete: producers/name/maintainers/users/user_id

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_roles permission.

Parameters

NameInRequiredTypeDescription
namepathyesstring
user_idpathyesinteger

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/producers/{name}/versions#

GET /admin/producers/{name}/versions#

Read: producers/name/versions

Authentication: not stated · Permission: not stated · Scope: not stated

Any signed-in caller.

One Producer's version lines, optionally narrowed with an api_type query parameter.

Parameters

NameInRequiredTypeDescription
namepathyesstring

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/producers/{name}/versions/{api_type}/{version}#

DELETE /admin/producers/{name}/versions/{api_type}/{version}#

Delete: producers/name/versions/api_type/version

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring
api_typepathyesstring
versionpathyesstring

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/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: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring
api_typepathyesstring
versionpathyesstring

Responses

StatusDescriptionBody
202

Promoted (or already GA — idempotent no-op). Standard Provide response body.

—
401

Not signed in.

ErrorBody
403

Signed in, but without the release_ga permission.

ErrorBody
404

Unknown Producer or version.

ErrorBody
409

Rejected by the same rules a GA Provide faces — semver honesty against the GA baseline (carries proposed_version), an AsyncAPI channel-message contract owned by another Producer, or the snapshot changing between click and release.

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: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring
api_typepathyesstring
versionpathyesstring

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/roles#

GET /admin/roles#

Read: roles

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_roles permission.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/settings/auto-approve#

GET /admin/settings/auto-approve#

Read: settings/auto-approve

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_settings permission.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

POST /admin/settings/auto-approve#

Create or run: settings/auto-approve

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_settings permission.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/settings/cache#

GET /admin/settings/cache#

Read: settings/cache

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_settings permission.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

POST /admin/settings/cache#

Create or run: settings/cache

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_settings permission.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/settings/database#

GET /admin/settings/database#

Read: settings/database

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_settings permission.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/settings/dependency-max-age#

GET /admin/settings/dependency-max-age#

Read: settings/dependency-max-age

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_settings permission.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

POST /admin/settings/dependency-max-age#

Create or run: settings/dependency-max-age

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_settings permission. Body: {"days": n}, at least 1 and at most 36500 (~100 years); values outside answer 400.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/settings/trunk-max-age#

GET /admin/settings/trunk-max-age#

Read: settings/trunk-max-age

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_settings permission. The trunk TTL in days (ADR-0004), default 90; 0 disables the cleanup.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

POST /admin/settings/trunk-max-age#

Create or run: settings/trunk-max-age

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_settings permission. Body: {"days": n}, at most 36500 (~100 years); larger values answer 400.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/settings/snapshot-max-age#

GET /admin/settings/snapshot-max-age#

Read: settings/snapshot-max-age

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_settings permission.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

POST /admin/settings/snapshot-max-age#

Create or run: settings/snapshot-max-age

Authentication: not stated · Permission: not stated · Scope: not stated

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

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/webhooks#

GET /admin/webhooks#

Read: webhooks/webhooks

Authentication: not stated · Permission: not stated · Scope: not stated

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

StatusDescriptionBody
200

The hooks.

WebhookList

Example 200 response (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"
  }
]
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

POST /admin/webhooks#

Create or run: webhooks/webhooks

Authentication: not stated · Permission: not stated · Scope: not stated

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

StatusDescriptionBody
201

Registered; the secret is shown once.

WebhookCreated

Example 201 response (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"
}
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: not stated · Permission: not stated · Scope: not stated

Requires the manage_settings permission.

Parameters

NameInRequiredTypeDescription
idpathyesinteger

Responses

StatusDescriptionBody
200

The hook.

Webhook

Example 200 response (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"
}
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: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
idpathyesinteger

Responses

StatusDescriptionBody
200

The hook after the patch.

Webhook

Example 200 response (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"
}
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: not stated · Permission: not stated · Scope: not stated

Requires the manage_settings permission.

Deletes the hook and its delivery log.

Parameters

NameInRequiredTypeDescription
idpathyesinteger

Responses

StatusDescriptionBody
204

Deleted.

—
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}/test#

POST /admin/webhooks/{id}/test#

Create or run: webhooks/webhooks/id/test

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
idpathyesinteger

Responses

StatusDescriptionBody
202

Queued; event_id names the event the delivery log will show.

—
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}/rotate-secret#

POST /admin/webhooks/{id}/rotate-secret#

Create or run: webhooks/webhooks/id/rotate-secret

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_settings permission.

A fresh secret, shown once; deliveries from now on are signed with it.

Parameters

NameInRequiredTypeDescription
idpathyesinteger

Responses

StatusDescriptionBody
200

The hook and its new secret.

WebhookCreated

Example 200 response (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"
}
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: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
idpathyesinteger

Responses

StatusDescriptionBody
200

The delivery log.

WebhookDeliveryList

Example 200 response (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"
  }
]
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: not stated · Permission: not stated · Scope: not stated

Requires the manage_settings permission.

Reset one delivery to pending, due now, attempt count kept — one more attempt even for a dead delivery.

Parameters

NameInRequiredTypeDescription
idpathyesinteger
delivery_idpathyesinteger

Responses

StatusDescriptionBody
202

Reset; the delivery as it now is.

WebhookDelivery

Example 202 response (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"
}
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: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring

Responses

StatusDescriptionBody
200

The hooks.

WebhookList

Example 200 response (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"
  }
]
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: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring

Responses

StatusDescriptionBody
201

Registered; the secret is shown once.

WebhookCreated

Example 201 response (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"
}
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: not stated · Permission: not stated · Scope: not stated

Requires the manage_producers permission, or maintainership of the Producer named in the path.

Parameters

NameInRequiredTypeDescription
namepathyesstring
idpathyesinteger

Responses

StatusDescriptionBody
200

The hook.

Webhook

Example 200 response (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"
}
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: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring
idpathyesinteger

Responses

StatusDescriptionBody
200

The hook after the patch.

Webhook

Example 200 response (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"
}
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: not stated · Permission: not stated · Scope: not stated

Requires the manage_producers permission, or maintainership of the Producer named in the path.

Deletes the hook and its delivery log.

Parameters

NameInRequiredTypeDescription
namepathyesstring
idpathyesinteger

Responses

StatusDescriptionBody
204

Deleted.

—
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}/test#

POST /admin/producers/{name}/webhooks/{id}/test#

Create or run: producers/name/webhooks/id/test

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring
idpathyesinteger

Responses

StatusDescriptionBody
202

Queued; event_id names the event the delivery log will show.

—
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}/rotate-secret#

POST /admin/producers/{name}/webhooks/{id}/rotate-secret#

Create or run: producers/name/webhooks/id/rotate-secret

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring
idpathyesinteger

Responses

StatusDescriptionBody
200

The hook and its new secret.

WebhookCreated

Example 200 response (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"
}
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: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring
idpathyesinteger

Responses

StatusDescriptionBody
200

The delivery log.

WebhookDeliveryList

Example 200 response (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"
  }
]
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: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring
idpathyesinteger
delivery_idpathyesinteger

Responses

StatusDescriptionBody
202

Reset; the delivery as it now is.

WebhookDelivery

Example 202 response (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"
}
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: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring

Responses

StatusDescriptionBody
200

The hooks.

WebhookList

Example 200 response (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"
  }
]
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: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring

Responses

StatusDescriptionBody
201

Registered; the secret is shown once.

WebhookCreated

Example 201 response (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"
}
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: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring
idpathyesinteger

Responses

StatusDescriptionBody
200

The hook.

Webhook

Example 200 response (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"
}
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: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring
idpathyesinteger

Responses

StatusDescriptionBody
200

The hook after the patch.

Webhook

Example 200 response (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"
}
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: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring
idpathyesinteger

Responses

StatusDescriptionBody
204

Deleted.

—
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}/test#

POST /admin/consumers/{name}/webhooks/{id}/test#

Create or run: consumers/name/webhooks/id/test

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring
idpathyesinteger

Responses

StatusDescriptionBody
202

Queued; event_id names the event the delivery log will show.

—
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}/rotate-secret#

POST /admin/consumers/{name}/webhooks/{id}/rotate-secret#

Create or run: consumers/name/webhooks/id/rotate-secret

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring
idpathyesinteger

Responses

StatusDescriptionBody
200

The hook and its new secret.

WebhookCreated

Example 200 response (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"
}
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: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring
idpathyesinteger

Responses

StatusDescriptionBody
200

The delivery log.

WebhookDeliveryList

Example 200 response (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"
  }
]
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: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
namepathyesstring
idpathyesinteger
delivery_idpathyesinteger

Responses

StatusDescriptionBody
202

Reset; the delivery as it now is.

WebhookDelivery

Example 202 response (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"
}
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: not stated · Permission: not stated · Scope: not stated

Requires the manage_settings permission.

The egress allow-list: host patterns a hook URL may point at.

Responses

StatusDescriptionBody
200

The list, as {"hosts": [...]}.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

POST /admin/settings/webhook-allowed-hosts#

Create or run: settings/webhook-allowed-hosts

Authentication: not stated · Permission: not stated · Scope: not stated

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

StatusDescriptionBody
200

The list as stored (trimmed, lower-cased, de-duplicated).

—
400

A pattern is not a host pattern.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/users#

GET /admin/users#

Read: users

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_users permission.

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/users/{id}#

DELETE /admin/users/{id}#

Delete: users/id

Authentication: not stated · Permission: not stated · Scope: not stated

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

NameInRequiredTypeDescription
idpathyesinteger

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/users/{id}/approve#

POST /admin/users/{id}/approve#

Create or run: users/id/approve

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_users permission.

Parameters

NameInRequiredTypeDescription
idpathyesinteger

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/users/{id}/maintains#

GET /admin/users/{id}/maintains#

Read: users/id/maintains

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_roles permission.

Parameters

NameInRequiredTypeDescription
idpathyesinteger

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/users/{id}/roles#

GET /admin/users/{id}/roles#

Read: users/id/roles

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_roles permission.

Parameters

NameInRequiredTypeDescription
idpathyesinteger

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

POST /admin/users/{id}/roles#

Create or run: users/id/roles

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_roles permission. Granting an admin-guarded role (admin, releaser) additionally requires the caller to be an admin.

Parameters

NameInRequiredTypeDescription
idpathyesinteger

Responses

StatusDescriptionBody
201

Created. The role is granted; the body is empty.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

/admin/users/{id}/roles/{role}#

DELETE /admin/users/{id}/roles/{role}#

Delete: users/id/roles/role

Authentication: not stated · Permission: not stated · Scope: not stated

Requires the manage_roles permission. Revoking an admin-guarded role (admin, releaser) additionally requires the caller to be an admin.

Parameters

NameInRequiredTypeDescription
idpathyesinteger
rolepathyesstring

Responses

StatusDescriptionBody
200

Success.

—
401

Not signed in.

ErrorBody
403

Signed in, but without what this endpoint requires.

ErrorBody

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.

FieldTypeRequiredDescription
ownerobject | nullyes

The owner ref's kind (group unless the ref says otherwise) and name, lower-cased.

owner.kindstringyes
owner.namestringyes
descriptionstring | nullyes

Trimmed, at most 1000 characters (a longer one is cut with an ellipsis).

source_locationstring | nullyes

The annotation without its url: prefix; only an http or https URL is kept.

linksobject[]yes

At most 20; a link whose url is not http or https is dropped.

links[].urlstringyes
links[].titlestringyes

The link's title, or the URL's host when it has none.

links[].typestring | nullyes
links[].iconstring | nullyes

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#

FieldTypeRequiredDescription
namestringyes
contextSystemContextyes

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.

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).

FieldTypeRequiredDescription
kindstringyes

One of global, producer, consumer.

namestring—

The Producer or Consumer; absent for global.

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.

FieldTypeRequiredDescription
idinteger (int64)yes
scopeWebhookScopeyes

Who a hook belongs to (#47).

urlstringyes
formatstringyes

One of json, slack, teams.

event_typesstring[]yes

The event types the hook receives; empty means every type.

producer_globstring | nullyes

Only events about Producers whose name matches (* and ?); null means every Producer.

secret_hintstringyes
pausedbooleanyes
allow_list_exemptbooleanyes

Registered by a caller with manage_settings; the allow-list does not apply.

created_bystringyes
created_atstringyes

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#

FieldTypeRequiredDescription
urlstringyes
formatstring—

One of json, slack, teams.

Default "json".

event_typesstring[]—

Empty or absent means every type; webhook.test cannot be subscribed to.

producer_globstring | null—

Example (placeholder values derived from the schema)

{
  "url": "string",
  "format": "json",
  "event_types": [
    "string"
  ],
  "producer_glob": "string"
}

WebhookCreated#

FieldTypeRequiredDescription
webhookWebhookyes

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.

secretstringyes

The signing secret, shown this once (whsec_ + 64 hex characters).

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).

FieldTypeRequiredDescription
idinteger (int64)yes
hook_idinteger (int64)yes
event_idstringyes
event_typestringyes
occurred_atstringyes
statusstringyes

One of pending, delivered, failed, dead.

attemptsintegeryes
next_attempt_atstringyes
last_response_codeinteger | nullyes
last_errorstring | nullyes
delivered_atstring | nullyes
updated_atstringyes

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.

FieldTypeRequiredDescription
errorstringyes
proposed_versionstring—

Example (placeholder values derived from the schema)

{
  "error": "string",
  "proposed_version": "string"
}