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.