Wardengate

Reference

API reference

The Wardengate REST API is the same surface the admin console and the CLI use. Every resource is JSON; every mutating request is idempotent when given an Idempotency-Key header. The base URL is the control plane's user-facing hostname, prefixed with /api/v1.

Authentication

Authenticate with a bearer token on every request. Tokens are scoped to a principal (human or service) and a set of permissions; they can be short-lived and refreshable, or long-lived for trusted automation. Mint tokens from the console or via wgctl token create.

curl https://wardengate.example.com/api/v1/users/me \
  -H "Authorization: Bearer $WG_TOKEN"

Rate limits

The default per-token limit is 600 requests per minute with a burst of 60, enforced server-side. Every response includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers. When you exceed the limit you receive HTTP 429 with a Retry-After header. Admin tokens can request a higher quota per service.

Errors

Errors are a stable JSON envelope. Never parse error text — the code field is what you build conditionals on.

{
  "error": {
    "code": "policy.not_found",
    "message": "no policy with id pol_9JK2 exists",
    "requestId": "req_01HE6W3R8Z9JXN",
    "details": { "policyId": "pol_9JK2" }
  }
}

HTTP status usage is conventional: 400 validation, 401 missing or invalid token, 403 authorized but disallowed, 404 not found, 409 conflict, 429 rate-limited, 5xx server-side.

Users

Users are projections of identities from a federated IdP. You can read them; you cannot create or delete them through the API — lifecycle is owned by the IdP and SCIM.

GET /api/v1/users?group=sre&limit=25
Authorization: Bearer $WG_TOKEN

200 OK
{
  "data": [
    {
      "id": "usr_01HE6...",
      "email": "avery@example.com",
      "displayName": "Avery Chen",
      "groups": ["sre", "sre-leads"],
      "status": "active",
      "lastSignInAt": "2026-04-18T14:22:19Z"
    }
  ],
  "nextCursor": null
}

Targets

A target is anything Wardengate can broker to. Create them programmatically from your asset inventory or your IaC pipeline.

POST /api/v1/targets
Authorization: Bearer $WG_TOKEN
Content-Type: application/json
Idempotency-Key: a78df0c2-0c6c-4f4a-8e2b-1f6b5a3c9c11

{
  "name": "web-01.prod",
  "protocol": "ssh",
  "address": "10.10.4.20:22",
  "tags": { "env": "prod", "role": "web" },
  "accounts": [
    { "name": "deploy", "credentialRef": "vault/ssh/deploy-prod" }
  ]
}

201 Created
{
  "id": "tgt_01HE6W...",
  "name": "web-01.prod",
  "protocol": "ssh",
  "status": "ready"
}
GET /api/v1/targets?tag=env:prod&protocol=ssh
Authorization: Bearer $WG_TOKEN

Policies

Policies bind principals to targets under constraints. A POST creates or replaces a policy by name (upsert semantics); a GET returns the compiled form including the effective principals and targets after group and tag expansion.

POST /api/v1/policies
Authorization: Bearer $WG_TOKEN
Content-Type: application/json

{
  "name": "prod-ssh-read",
  "principals": { "groups": ["sre"] },
  "targets": { "tags": { "env": "prod" } },
  "protocols": ["ssh"],
  "accounts": ["readonly"],
  "constraints": {
    "mfa": "required",
    "sessionMinutes": 60
  },
  "recording": { "mode": "full" }
}

200 OK
{
  "id": "pol_01HE6W...",
  "name": "prod-ssh-read",
  "revision": 3,
  "updatedAt": "2026-04-20T09:11:02Z"
}
GET /api/v1/policies/pol_01HE6W.../compiled
Authorization: Bearer $WG_TOKEN

Sessions

Sessions are read-only through the API: list, inspect, and terminate. You cannot start a session via REST — sessions begin when a user connects through the gateway. Terminating a session is a POST to a sub-resource so it slots cleanly into automation.

GET /api/v1/sessions?state=active&limit=50
Authorization: Bearer $WG_TOKEN

200 OK
{
  "data": [
    {
      "id": "ses_01HE6W...",
      "user": "avery@example.com",
      "target": "web-01.prod",
      "protocol": "ssh",
      "startedAt": "2026-04-20T10:04:11Z",
      "policyId": "pol_01HE6W...",
      "recording": { "mode": "full", "bytes": 218411 }
    }
  ],
  "nextCursor": null
}
POST /api/v1/sessions/ses_01HE6W.../terminate
Authorization: Bearer $WG_TOKEN
Content-Type: application/json

{ "reason": "policy violation: forbidden command attempted" }

202 Accepted
{ "id": "ses_01HE6W...", "state": "terminating" }

Pagination and filtering

List endpoints are cursor-paginated: pass the nextCursor from the previous response as the cursor query parameter on the next call. The maximum limit is 200. Filtering uses simple key=value query params with tag:key=value for tagged resources.

Webhooks

Subscribe to session, approval, and policy events. Deliveries are signed with HMAC-SHA256 over the body; verify the X-Wardengate-Signature header against the shared secret. Failed deliveries are retried with exponential backoff for twenty-four hours.