---
id: rest-api
title: REST API
sidebar_label: REST API
---

The control plane's HTTP API, on port `8080`. The web UI is a client of it and
has no privileges it does not.

## Authentication

Most endpoints take a session: an opaque 32-byte token in the `km_session`
cookie, with the body in Redis for 24 hours.

One endpoint takes a bearer token instead the External Secrets Operator read
path.

## Unauthenticated

```
GET  /install            /install.ps1        # dynamic agent install scripts
GET  /update             /update.ps1
GET  /auth/bootstrap-status
POST /auth/bootstrap     /auth/login  /auth/logout
GET  /auth/me
GET  /auth/providers                          # {local_enabled, providers:[{id,name,preset}]} — no issuer, client ID or secret
GET  /auth/oidc/:providerId/start · /auth/oidc/:providerId/callback
GET  /api/secrets/:group/values               # bearer token (ESO)
```

`/install` and `/install.ps1` take `server_id` and `token` as query parameters
and return a shell script with the newest agent version substituted in.

`POST /auth/bootstrap` works only while the database has no users.

## Session-authenticated, under `/api`

### Servers

```
GET,POST   /servers
GET,POST   /servers/new
GET,DELETE /servers/:id
POST       /servers/:id/generate-key
POST       /servers/:id/update-agent
POST       /servers/:id/apply-updates
```

### Keys

```
GET,POST   /keys
GET,DELETE /keys/:id
GET        /keys/:id/private-key
POST       /keys/:id/assign
DELETE     /keys/:id/assign/:serverId
```

### Workflows and steps

```
GET,POST       /steps
PUT,DELETE     /steps/:id
GET            /steps/:id/export
POST           /steps/import · /steps/seed-defaults · /steps/parse
GET            /steps/usage
GET,POST       /workflows
GET,PUT,DELETE /workflows/:id
POST           /workflows/:id/run
GET            /workflows/:id/runs
GET            /runs/:runId
POST           /runs/:runId/cancel
GET            /runs/:runId/servers/:serverId/logs
GET            /runs/:runId/servers/:serverId/logs/stream
```

`PUT` and `DELETE` on a step whose source is `default` answer `409`. See
[Workflows](../vantage/workflows.md#default-steps).

### Monitors and channels

```
GET,POST       /monitors
GET,PUT,DELETE /monitors/:id
GET            /monitors/:id/incidents · /monitors/:id/uptime
GET,POST       /channels
PUT,DELETE     /channels/:id
POST           /channels/:id/test
```

### Secrets

```
GET,POST       /secrets
GET,PUT,DELETE /secrets/:group
POST           /secrets/:group/reveal
DELETE         /secrets/:group/:key
```

### Console

```
POST /console/connect
GET  /console/tunnel        # websocket
```

### Other

```
GET  /audit
GET  /agent/latest-version
GET,PUT /settings                            (owner|admin)
POST /settings/secrets-token                 (owner|admin)
GET  /license
POST /license                                (self-hosted only)
GET,POST   /org/users
PUT        /org/users/:id/role
DELETE     /org/users/:id
GET,POST       /auth/providers                        (owner|admin)
PUT,DELETE     /auth/providers/:id                     (owner|admin)
POST           /auth/providers/:id/test · /auth/providers/:id/ack-notice   (owner|admin)
GET             /auth/presets                          (owner|admin)
```

## Notable refusals

| Endpoint                                           | Condition                      | Status              |
| -------------------------------------------------- | ------------------------------ | ------------------- |
| `POST /license`                                    | deployment is `cloud`          | `409 cloud_managed` |
| `PUT,DELETE /steps/:id`                            | the step's source is `default` | `409`               |
| `PUT /org/users/:id/role`, `DELETE /org/users/:id` | the user's auth source is `hq` | `409`               |

`POST /license` is exempt from the licence check, so pasting a valid licence
works while the current one is expired that is the way out of degraded mode.

## Multi-tenancy

Every request is scoped to the instance resolved from the session. On a
multi-tenant deployment, a request arriving at `<slug>.vantage.<tld>` also has
its host checked against the session's instance, and a mismatch is rejected.

## Errors

Errors are JSON with an `error` field. Customer-facing endpoints in the HQ API
answer `404` rather than `403` for another account's resource, because a `403`
confirms the resource exists; the control plane's own API is single-tenant per
session and does not need that distinction.

## Admin API

Vantage HQ is a separate hosted service with its own API and its own session.
Its behaviour is described in the [Vantage HQ](../hq/accounts-and-signup.md)
section rather than here; the two services share no session and no
authentication.
