Registers the management routes.
This page is generated from the Depot route table. Every operation carries the permission it needs and the anchor an agent can link to.
POST /api/v1/console/invites/accept
Section titled “POST /api/v1/console/invites/accept”POSTNo permission neededshared facehosteditmspremote
Source: [object Object]
acceptInvite spends an invitation and sets the account’s first password.
Request body
Section titled “Request body”Required, sent as application/json.
| Field | Type | Description |
|---|---|---|
passwordrequired | string | |
tokenrequired | string |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
204 | None | Success, with no body. |
400 | None | The request was refused. |
Request samples
Section titled “Request samples”# This operation is public. It takes no credentials.curl -X POST 'https://depot.example.com/api/v1/console/invites/accept' \ -H 'Content-Type: application/json' \ --data '{ "password": "string", "token": "string"}'# This operation is public. It takes no credentials.
$headers = @{ 'Content-Type' = 'application/json'}
$body = @'{ "password": "string", "token": "string"}'@
$response = Invoke-RestMethod ` -Method Post ` -Uri 'https://depot.example.com/api/v1/console/invites/accept' ` -Headers $headers ` -ContentType 'application/json' ` -Body $body
$response | ConvertTo-Json -Depth 10# This operation is public. It takes no credentials.
import requests
url = "https://depot.example.com/api/v1/console/invites/accept"headers = { "Content-Type": "application/json",}payload = { "password": "string", "token": "string",}
response = requests.post(url, headers=headers, json=payload, timeout=30)response.raise_for_status()print(response.json())// This operation is public. It takes no credentials.package main
import ( "bytes" "fmt" "io" "log" "net/http")
func main() { body := []byte(`{ "password": "string", "token": "string"}`)
req, err := http.NewRequest(http.MethodPost, "https://depot.example.com/api/v1/console/invites/accept", bytes.NewReader(body)) if err != nil { log.Fatal(err) }
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// This operation is public. It takes no credentials.
const url = "https://depot.example.com/api/v1/console/invites/accept";
const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ "password": "string", "token": "string" }),});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// This operation is public. It takes no credentials.
using System;using System.Net.Http;using System.Text;
using var client = new HttpClient();
const string body = """{ "password": "string", "token": "string"}""";
var request = new HttpRequestMessage(HttpMethod.Post, "https://depot.example.com/api/v1/console/invites/accept");request.Content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());GET /api/v1/console/login-policy
Section titled “GET /api/v1/console/login-policy”GETclient:readshared facehosteditmspremoteIdempotent
Source: [object Object]
getLoginPolicy returns the client-wide rules and the caller’s own address.
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
200 | application/json, LoginPolicyResponse | Success. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold client:read. |
200 response body
| Field | Type | Description |
|---|---|---|
callerIprequired | string | |
ipAllowlistrequired | string | |
timeZonerequired | string | |
week | array of array of WindowView or null | |
week[][].endMinuterequired | integer | |
week[][].startMinuterequired | integer |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.curl -X GET 'https://depot.example.com/api/v1/console/login-policy' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -b 'outpost_console=<console-session>'# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$response = Invoke-RestMethod ` -Method Get ` -Uri 'https://depot.example.com/api/v1/console/login-policy' ` -Headers $headers
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
import requests
url = "https://depot.example.com/api/v1/console/login-policy"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json",}cookies = { "outpost_console": "<console-session>",}
response = requests.get(url, headers=headers, cookies=cookies, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.package main
import ( "fmt" "io" "log" "net/http")
func main() { req, err := http.NewRequest(http.MethodGet, "https://depot.example.com/api/v1/console/login-policy", nil) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/login-policy";
const response = await fetch(url, { method: "GET", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", }, credentials: "include",});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.
using System;using System.Net.Http;
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://depot.example.com/api/v1/console/login-policy");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());PUT /api/v1/console/login-policy
Section titled “PUT /api/v1/console/login-policy”PUTclient:manageshared facehosteditmspremoteIdempotent
Source: [object Object]
saveLoginPolicy replaces the client-wide rules.
THE LOCKOUT GUARD
Section titled “THE LOCKOUT GUARD”Saving rules that exclude the caller from where they are standing right now returns 409 naming their address, unless the body carries an explicit acknowledgeLockout.
This mirrors refuseIfLastOwner and rests on the same argument. There is no way back that does not involve somebody else: the rules can only be edited from inside the console, and the console is what the rules just closed. Under an hours rule that is a wait; under a network rule it is a support call, and on a hosted fleet it is a support call to us. So the accident is refused and the deliberate act is allowed, and the difference between them is a field somebody had to set.
AND EVERY OWNER
Section titled “AND EVERY OWNER”It also refuses, on the same acknowledgement, rules that would shut out EVERY live owner: the caller may be an administrator who is not an owner, and rules that pass them can still leave nobody able to manage the organisation. Each owner is evaluated against where they last signed in from (their newest session’s address) and the time now; an owner with no recorded address counts as excluded by any allowlist, because the guard cannot show they are inside it. It refuses only when ALL of them are out: refusing a rule because it might exclude SOMEBODY would refuse every useful rule there is.
Break-glass (breakglass.go) is the way back for an owner who acknowledged the warning and was wrong; the guard is what stops it being needed by accident.
RECORDED AND ANNOUNCED
Section titled “RECORDED AND ANNOUNCED”Every save is audited against the policy, and every owner is told by email. A rule that changes who can reach the console is the change an owner most needs to hear about from somebody other than the person who made it.
Request body
Section titled “Request body”Required, sent as application/json.
| Field | Type | Description |
|---|---|---|
acknowledgeLockoutrequired | boolean | |
ipAllowlistrequired | string | |
timeZonerequired | string | |
week | array of array of WindowView or null | |
week[][].endMinuterequired | integer | |
week[][].startMinuterequired | integer |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
204 | None | Success, with no body. |
400 | application/problem+json, ProblemDetails | The request body is not acceptable. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold client:manage. |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.curl -X PUT 'https://depot.example.com/api/v1/console/login-policy' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -b 'outpost_console=<console-session>' \ --data '{ "acknowledgeLockout": false, "ipAllowlist": "string", "timeZone": "string", "week": [ [ { "endMinute": 0, "startMinute": 0 } ] ]}'# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Content-Type' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$body = @'{ "acknowledgeLockout": false, "ipAllowlist": "string", "timeZone": "string", "week": [ [ { "endMinute": 0, "startMinute": 0 } ] ]}'@
$response = Invoke-RestMethod ` -Method Put ` -Uri 'https://depot.example.com/api/v1/console/login-policy' ` -Headers $headers ` -ContentType 'application/json' ` -Body $body
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
import requests
url = "https://depot.example.com/api/v1/console/login-policy"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", "Content-Type": "application/json",}cookies = { "outpost_console": "<console-session>",}payload = { "acknowledgeLockout": False, "ipAllowlist": "string", "timeZone": "string", "week": [ [ { "endMinute": 0, "startMinute": 0, }, ], ],}
response = requests.put(url, headers=headers, cookies=cookies, json=payload, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.package main
import ( "bytes" "fmt" "io" "log" "net/http")
func main() { body := []byte(`{ "acknowledgeLockout": false, "ipAllowlist": "string", "timeZone": "string", "week": [ [ { "endMinute": 0, "startMinute": 0 } ] ]}`)
req, err := http.NewRequest(http.MethodPut, "https://depot.example.com/api/v1/console/login-policy", bytes.NewReader(body)) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.Header.Set("Content-Type", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/login-policy";
const response = await fetch(url, { method: "PUT", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", "Content-Type": "application/json", }, credentials: "include", body: JSON.stringify({ "acknowledgeLockout": false, "ipAllowlist": "string", "timeZone": "string", "week": [ [ { "endMinute": 0, "startMinute": 0 } ] ] }),});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.
using System;using System.Net.Http;using System.Text;
using var client = new HttpClient();
const string body = """{ "acknowledgeLockout": false, "ipAllowlist": "string", "timeZone": "string", "week": [ [ { "endMinute": 0, "startMinute": 0 } ] ]}""";
var request = new HttpRequestMessage(HttpMethod.Put, "https://depot.example.com/api/v1/console/login-policy");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");request.Content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());GET /api/v1/console/operators
Section titled “GET /api/v1/console/operators”GETticket:readshared facehosteditmspremoteIdempotent
Source: [object Object]
listOperators lists the active console accounts a desk operator can pick as an assignee: a macro’s owner, a queue’s members, an incident’s commander.
Invited and disabled accounts are left out because neither can work what they are handed. Unpaged on purpose: a picker needs the whole list, and it is one query with no per-row lookups.
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
200 | application/json, object | Success. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold ticket:read. |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.curl -X GET 'https://depot.example.com/api/v1/console/operators' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -b 'outpost_console=<console-session>'# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$response = Invoke-RestMethod ` -Method Get ` -Uri 'https://depot.example.com/api/v1/console/operators' ` -Headers $headers
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
import requests
url = "https://depot.example.com/api/v1/console/operators"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json",}cookies = { "outpost_console": "<console-session>",}
response = requests.get(url, headers=headers, cookies=cookies, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.package main
import ( "fmt" "io" "log" "net/http")
func main() { req, err := http.NewRequest(http.MethodGet, "https://depot.example.com/api/v1/console/operators", nil) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/operators";
const response = await fetch(url, { method: "GET", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", }, credentials: "include",});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.
using System;using System.Net.Http;
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://depot.example.com/api/v1/console/operators");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());GET /api/v1/console/permissions
Section titled “GET /api/v1/console/permissions”GETrole:manageshared facehosteditmspremoteIdempotent
Source: [object Object]
listPermissions serves the permission vocabulary, grouped by area.
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
200 | application/json, object | Success. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold role:manage. |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.curl -X GET 'https://depot.example.com/api/v1/console/permissions' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -b 'outpost_console=<console-session>'# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$response = Invoke-RestMethod ` -Method Get ` -Uri 'https://depot.example.com/api/v1/console/permissions' ` -Headers $headers
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
import requests
url = "https://depot.example.com/api/v1/console/permissions"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json",}cookies = { "outpost_console": "<console-session>",}
response = requests.get(url, headers=headers, cookies=cookies, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.package main
import ( "fmt" "io" "log" "net/http")
func main() { req, err := http.NewRequest(http.MethodGet, "https://depot.example.com/api/v1/console/permissions", nil) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/permissions";
const response = await fetch(url, { method: "GET", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", }, credentials: "include",});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.
using System;using System.Net.Http;
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://depot.example.com/api/v1/console/permissions");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());GET /api/v1/console/roles
Section titled “GET /api/v1/console/roles”GETrole:manageshared facehosteditmspremoteIdempotent
Source: [object Object]
listRoles serves the role catalog: every role this client has, with what each one can do, who holds it, and whether the caller may edit it.
Two queries for the whole page, not one per role. The grants come back as a map keyed by role code from a single join, so adding a role to the catalog costs nothing here.
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
200 | application/json, object | Success. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold role:manage. |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.curl -X GET 'https://depot.example.com/api/v1/console/roles' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -b 'outpost_console=<console-session>'# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$response = Invoke-RestMethod ` -Method Get ` -Uri 'https://depot.example.com/api/v1/console/roles' ` -Headers $headers
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
import requests
url = "https://depot.example.com/api/v1/console/roles"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json",}cookies = { "outpost_console": "<console-session>",}
response = requests.get(url, headers=headers, cookies=cookies, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.package main
import ( "fmt" "io" "log" "net/http")
func main() { req, err := http.NewRequest(http.MethodGet, "https://depot.example.com/api/v1/console/roles", nil) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/roles";
const response = await fetch(url, { method: "GET", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", }, credentials: "include",});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.
using System;using System.Net.Http;
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://depot.example.com/api/v1/console/roles");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());POST /api/v1/console/roles
Section titled “POST /api/v1/console/roles”POSTrole:manageshared facehosteditmspremoteNot fully resolved
What this page does not know
- response-status
These are parts of the route the extractor could not read from the source. Everything else on this page came straight from it.
Source: [object Object]
createRole makes a custom role, or clones one with fromRole.
The code is slugged from the name and never changes afterwards.
Request body
Section titled “Request body”Required, sent as application/json.
| Field | Type | Description |
|---|---|---|
description | string or null | |
fromRole | string or null | |
namerequired | string | |
permissions | array of string or null |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
200 | application/json, RoleView | Success. |
400 | application/problem+json, ProblemDetails | The request body is not acceptable. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold role:manage. |
200 response body
| Field | Type | Description |
|---|---|---|
clippedPermissionsrequired | array of string | |
code | string or null | |
descriptionrequired | string | |
idrequired | string | |
isSystemrequired | boolean | |
memberCountrequired | integer | |
namerequired | string | |
permissionsrequired | array of string | |
rowVersionrequired | integer | int64. |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.curl -X POST 'https://depot.example.com/api/v1/console/roles' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -b 'outpost_console=<console-session>' \ --data '{ "description": "string", "fromRole": "string", "name": "string", "permissions": [ "string" ]}'# Sign in first. outpost_console is a session cookie, so send it with every request.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Content-Type' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$body = @'{ "description": "string", "fromRole": "string", "name": "string", "permissions": [ "string" ]}'@
$response = Invoke-RestMethod ` -Method Post ` -Uri 'https://depot.example.com/api/v1/console/roles' ` -Headers $headers ` -ContentType 'application/json' ` -Body $body
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.
import requests
url = "https://depot.example.com/api/v1/console/roles"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", "Content-Type": "application/json",}cookies = { "outpost_console": "<console-session>",}payload = { "description": "string", "fromRole": "string", "name": "string", "permissions": [ "string", ],}
response = requests.post(url, headers=headers, cookies=cookies, json=payload, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.package main
import ( "bytes" "fmt" "io" "log" "net/http")
func main() { body := []byte(`{ "description": "string", "fromRole": "string", "name": "string", "permissions": [ "string" ]}`)
req, err := http.NewRequest(http.MethodPost, "https://depot.example.com/api/v1/console/roles", bytes.NewReader(body)) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.Header.Set("Content-Type", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/roles";
const response = await fetch(url, { method: "POST", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", "Content-Type": "application/json", }, credentials: "include", body: JSON.stringify({ "description": "string", "fromRole": "string", "name": "string", "permissions": [ "string" ] }),});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.
using System;using System.Net.Http;using System.Text;
using var client = new HttpClient();
const string body = """{ "description": "string", "fromRole": "string", "name": "string", "permissions": [ "string" ]}""";
var request = new HttpRequestMessage(HttpMethod.Post, "https://depot.example.com/api/v1/console/roles");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");request.Content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());PATCH /api/v1/console/roles/{roleCode}
Section titled “PATCH /api/v1/console/roles/{roleCode}”PATCHrole:manageshared facehosteditmspremoteNot fully resolved
What this page does not know
- response-status
These are parts of the route the extractor could not read from the source. Everything else on this page came straight from it.
Source: [object Object]
updateRole changes a role’s name or description.
The code never changes.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
roleCode | path | string | Yes |
Request body
Section titled “Request body”Required, sent as application/json.
| Field | Type | Description |
|---|---|---|
description | string or null | |
name | string or null |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
200 | application/json, RoleView | Success. |
400 | application/problem+json, ProblemDetails | The request body is not acceptable. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold role:manage. |
404 | application/problem+json, ProblemDetails | No resource matches that id. |
200 response body
| Field | Type | Description |
|---|---|---|
clippedPermissionsrequired | array of string | |
code | string or null | |
descriptionrequired | string | |
idrequired | string | |
isSystemrequired | boolean | |
memberCountrequired | integer | |
namerequired | string | |
permissionsrequired | array of string | |
rowVersionrequired | integer | int64. |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.curl -X PATCH 'https://depot.example.com/api/v1/console/roles/<roleCode>' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -b 'outpost_console=<console-session>' \ --data '{ "description": "string", "name": "string"}'# Sign in first. outpost_console is a session cookie, so send it with every request.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Content-Type' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$body = @'{ "description": "string", "name": "string"}'@
$response = Invoke-RestMethod ` -Method Patch ` -Uri 'https://depot.example.com/api/v1/console/roles/<roleCode>' ` -Headers $headers ` -ContentType 'application/json' ` -Body $body
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.
import requests
url = "https://depot.example.com/api/v1/console/roles/<roleCode>"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", "Content-Type": "application/json",}cookies = { "outpost_console": "<console-session>",}payload = { "description": "string", "name": "string",}
response = requests.patch(url, headers=headers, cookies=cookies, json=payload, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.package main
import ( "bytes" "fmt" "io" "log" "net/http")
func main() { body := []byte(`{ "description": "string", "name": "string"}`)
req, err := http.NewRequest(http.MethodPatch, "https://depot.example.com/api/v1/console/roles/<roleCode>", bytes.NewReader(body)) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.Header.Set("Content-Type", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/roles/<roleCode>";
const response = await fetch(url, { method: "PATCH", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", "Content-Type": "application/json", }, credentials: "include", body: JSON.stringify({ "description": "string", "name": "string" }),});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.
using System;using System.Net.Http;using System.Text;
using var client = new HttpClient();
const string body = """{ "description": "string", "name": "string"}""";
var request = new HttpRequestMessage(HttpMethod.Patch, "https://depot.example.com/api/v1/console/roles/<roleCode>");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");request.Content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());DELETE /api/v1/console/roles/{roleCode}
Section titled “DELETE /api/v1/console/roles/{roleCode}”DELETErole:manageshared facehosteditmspremoteIdempotent
Source: [object Object]
deleteRole removes a custom role nobody holds.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
roleCode | path | string | Yes |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
204 | None | Success, with no body. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold role:manage. |
404 | application/problem+json, ProblemDetails | No resource matches that id. |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.curl -X DELETE 'https://depot.example.com/api/v1/console/roles/<roleCode>' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -b 'outpost_console=<console-session>'# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$response = Invoke-RestMethod ` -Method Delete ` -Uri 'https://depot.example.com/api/v1/console/roles/<roleCode>' ` -Headers $headers
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
import requests
url = "https://depot.example.com/api/v1/console/roles/<roleCode>"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json",}cookies = { "outpost_console": "<console-session>",}
response = requests.delete(url, headers=headers, cookies=cookies, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.package main
import ( "fmt" "io" "log" "net/http")
func main() { req, err := http.NewRequest(http.MethodDelete, "https://depot.example.com/api/v1/console/roles/<roleCode>", nil) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/roles/<roleCode>";
const response = await fetch(url, { method: "DELETE", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", }, credentials: "include",});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.
using System;using System.Net.Http;
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Delete, "https://depot.example.com/api/v1/console/roles/<roleCode>");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());GET /api/v1/console/roles/{roleCode}/holders
Section titled “GET /api/v1/console/roles/{roleCode}/holders”GETrole:manageshared facehosteditmspremoteIdempotent
Source: [object Object]
listRoleHolders lists the people who hold a role, of any account status.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
roleCode | path | string | Yes |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
200 | application/json, object | Success. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold role:manage. |
404 | application/problem+json, ProblemDetails | No resource matches that id. |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.curl -X GET 'https://depot.example.com/api/v1/console/roles/<roleCode>/holders' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -b 'outpost_console=<console-session>'# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$response = Invoke-RestMethod ` -Method Get ` -Uri 'https://depot.example.com/api/v1/console/roles/<roleCode>/holders' ` -Headers $headers
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
import requests
url = "https://depot.example.com/api/v1/console/roles/<roleCode>/holders"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json",}cookies = { "outpost_console": "<console-session>",}
response = requests.get(url, headers=headers, cookies=cookies, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.package main
import ( "fmt" "io" "log" "net/http")
func main() { req, err := http.NewRequest(http.MethodGet, "https://depot.example.com/api/v1/console/roles/<roleCode>/holders", nil) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/roles/<roleCode>/holders";
const response = await fetch(url, { method: "GET", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", }, credentials: "include",});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.
using System;using System.Net.Http;
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://depot.example.com/api/v1/console/roles/<roleCode>/holders");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());PUT /api/v1/console/roles/{roleCode}/permissions
Section titled “PUT /api/v1/console/roles/{roleCode}/permissions”PUTrole:manageshared facehosteditmspremoteIdempotentNot fully resolved
What this page does not know
- response-status
These are parts of the route the extractor could not read from the source. Everything else on this page came straight from it.
Source: [object Object]
setRolePermissions replaces what a role grants.
The floor codes are always kept. The change reaches every holder on their next request.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
roleCode | path | string | Yes |
Request body
Section titled “Request body”Required, sent as application/json.
| Field | Type | Description |
|---|---|---|
permissionsrequired | array of string |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
200 | application/json, RoleView | Success. |
400 | application/problem+json, ProblemDetails | The request body is not acceptable. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold role:manage. |
404 | application/problem+json, ProblemDetails | No resource matches that id. |
200 response body
| Field | Type | Description |
|---|---|---|
clippedPermissionsrequired | array of string | |
code | string or null | |
descriptionrequired | string | |
idrequired | string | |
isSystemrequired | boolean | |
memberCountrequired | integer | |
namerequired | string | |
permissionsrequired | array of string | |
rowVersionrequired | integer | int64. |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.curl -X PUT 'https://depot.example.com/api/v1/console/roles/<roleCode>/permissions' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -b 'outpost_console=<console-session>' \ --data '{ "permissions": [ "string" ]}'# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Content-Type' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$body = @'{ "permissions": [ "string" ]}'@
$response = Invoke-RestMethod ` -Method Put ` -Uri 'https://depot.example.com/api/v1/console/roles/<roleCode>/permissions' ` -Headers $headers ` -ContentType 'application/json' ` -Body $body
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
import requests
url = "https://depot.example.com/api/v1/console/roles/<roleCode>/permissions"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", "Content-Type": "application/json",}cookies = { "outpost_console": "<console-session>",}payload = { "permissions": [ "string", ],}
response = requests.put(url, headers=headers, cookies=cookies, json=payload, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.package main
import ( "bytes" "fmt" "io" "log" "net/http")
func main() { body := []byte(`{ "permissions": [ "string" ]}`)
req, err := http.NewRequest(http.MethodPut, "https://depot.example.com/api/v1/console/roles/<roleCode>/permissions", bytes.NewReader(body)) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.Header.Set("Content-Type", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/roles/<roleCode>/permissions";
const response = await fetch(url, { method: "PUT", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", "Content-Type": "application/json", }, credentials: "include", body: JSON.stringify({ "permissions": [ "string" ] }),});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.
using System;using System.Net.Http;using System.Text;
using var client = new HttpClient();
const string body = """{ "permissions": [ "string" ]}""";
var request = new HttpRequestMessage(HttpMethod.Put, "https://depot.example.com/api/v1/console/roles/<roleCode>/permissions");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");request.Content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());POST /api/v1/console/roles/{roleCode}/restore-defaults
Section titled “POST /api/v1/console/roles/{roleCode}/restore-defaults”POSTrole:manageshared facehosteditmspremoteNot fully resolved
What this page does not know
- response-status
These are parts of the route the extractor could not read from the source. Everything else on this page came straight from it.
Source: [object Object]
restoreRoleDefaults puts a built-in role’s permissions back the way the product ships them.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
roleCode | path | string | Yes |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
200 | application/json, RoleView | Success. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold role:manage. |
404 | application/problem+json, ProblemDetails | No resource matches that id. |
200 response body
| Field | Type | Description |
|---|---|---|
clippedPermissionsrequired | array of string | |
code | string or null | |
descriptionrequired | string | |
idrequired | string | |
isSystemrequired | boolean | |
memberCountrequired | integer | |
namerequired | string | |
permissionsrequired | array of string | |
rowVersionrequired | integer | int64. |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.curl -X POST 'https://depot.example.com/api/v1/console/roles/<roleCode>/restore-defaults' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -b 'outpost_console=<console-session>'# Sign in first. outpost_console is a session cookie, so send it with every request.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$response = Invoke-RestMethod ` -Method Post ` -Uri 'https://depot.example.com/api/v1/console/roles/<roleCode>/restore-defaults' ` -Headers $headers
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.
import requests
url = "https://depot.example.com/api/v1/console/roles/<roleCode>/restore-defaults"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json",}cookies = { "outpost_console": "<console-session>",}
response = requests.post(url, headers=headers, cookies=cookies, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.package main
import ( "fmt" "io" "log" "net/http")
func main() { req, err := http.NewRequest(http.MethodPost, "https://depot.example.com/api/v1/console/roles/<roleCode>/restore-defaults", nil) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/roles/<roleCode>/restore-defaults";
const response = await fetch(url, { method: "POST", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", }, credentials: "include",});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.
using System;using System.Net.Http;
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://depot.example.com/api/v1/console/roles/<roleCode>/restore-defaults");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());GET /api/v1/console/security-policy
Section titled “GET /api/v1/console/security-policy”GETclient:readshared facehosteditmspremoteIdempotent
Source: [object Object]
getSecurityPolicy answers the GET.
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
200 | application/json, SecurityPolicyResponse | Success. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold client:read. |
200 response body
| Field | Type | Description |
|---|---|---|
effectivePasswordrequired | PasswordView | |
effectivePassword.breachScreen | boolean or null | |
effectivePassword.historyCountrequired | integer | |
effectivePassword.maxAgeDaysrequired | integer | |
effectivePassword.minLengthrequired | integer | |
effectivePassword.requireDigitrequired | boolean | |
effectivePassword.requireSymbolrequired | boolean | |
effectivePassword.requireUpperrequired | boolean | |
frameworkrequired | string | |
frameworksrequired | array of FrameworkView | |
frameworks[].coderequired | string | |
frameworks[].labelrequired | string | |
frameworks[].lockoutrequired | LockoutView | |
frameworks[].lockout.minutesrequired | integer | |
frameworks[].lockout.thresholdrequired | integer | |
frameworks[].mfaRequirementrequired | string | |
frameworks[].noterequired | string | |
frameworks[].passwordrequired | PasswordView | |
frameworks[].password.breachScreen | boolean or null | |
frameworks[].password.historyCountrequired | integer | |
frameworks[].password.maxAgeDaysrequired | integer | |
frameworks[].password.minLengthrequired | integer | |
frameworks[].password.requireDigitrequired | boolean | |
frameworks[].password.requireSymbolrequired | boolean | |
frameworks[].password.requireUpperrequired | boolean | |
frameworks[].sessionrequired | SessionView | |
frameworks[].session.absoluteHoursrequired | integer | |
frameworks[].session.idleMinutesrequired | integer | |
lockoutrequired | LockoutView | |
lockout.minutesrequired | integer | |
lockout.thresholdrequired | integer | |
mfarequired | MfaView | |
mfa.acceptedFactorsrequired | array of string | |
mfa.enforcedFrom | string (date-time) or null | |
mfa.graceDaysrequired | integer | |
mfa.requiredSince | string (date-time) or null | |
mfa.requirementrequired | string | |
mfa.supportedFactorsrequired | array of string | |
passwordrequired | PasswordView | |
password.breachScreen | boolean or null | |
password.historyCountrequired | integer | |
password.maxAgeDaysrequired | integer | |
password.minLengthrequired | integer | |
password.requireDigitrequired | boolean | |
password.requireSymbolrequired | boolean | |
password.requireUpperrequired | boolean | |
passwordlessrequired | PasswordlessView | passwordlessView is whether a passkey alone may sign somebody in. |
passwordless.allowedrequired | boolean | |
policyVersionrequired | integer | |
reauthRequired | boolean or null | |
rememberDevicerequired | RememberView | |
rememberDevice.daysrequired | integer | |
rememberDevice.enabledrequired | boolean | |
rowVersionrequired | integer | int64. |
sessionrequired | SessionView | |
session.absoluteHoursrequired | integer | |
session.idleMinutesrequired | integer |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.curl -X GET 'https://depot.example.com/api/v1/console/security-policy' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -b 'outpost_console=<console-session>'# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$response = Invoke-RestMethod ` -Method Get ` -Uri 'https://depot.example.com/api/v1/console/security-policy' ` -Headers $headers
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
import requests
url = "https://depot.example.com/api/v1/console/security-policy"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json",}cookies = { "outpost_console": "<console-session>",}
response = requests.get(url, headers=headers, cookies=cookies, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.package main
import ( "fmt" "io" "log" "net/http")
func main() { req, err := http.NewRequest(http.MethodGet, "https://depot.example.com/api/v1/console/security-policy", nil) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/security-policy";
const response = await fetch(url, { method: "GET", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", }, credentials: "include",});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.
using System;using System.Net.Http;
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://depot.example.com/api/v1/console/security-policy");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());PUT /api/v1/console/security-policy
Section titled “PUT /api/v1/console/security-policy”PUTclient:manageshared facehosteditmspremoteIdempotent
Source: [object Object]
saveSecurityPolicy answers the PUT.
A TIGHTENING SAVE SIGNS EVERYBODY OUT, THE CALLER INCLUDED
Section titled “A TIGHTENING SAVE SIGNS EVERYBODY OUT, THE CALLER INCLUDED”When the save asks more of a password or a second factor than the old policy did (console.Tightens), PolicyVersion is bumped in the same statement and the middleware refuses every session issued under the old version. Everybody signs in again, and the sign-in is where a password that no longer meets the policy is caught (it is the only moment the plaintext exists) and where a missing second factor is caught. The caller is not exempt: an exemption would be the one session in the tenant that never met the rule its holder just set. The response says reauthRequired so the console can explain the sign-out rather than let it look like a fault.
Request body
Section titled “Request body”Required, sent as application/json.
| Field | Type | Description |
|---|---|---|
frameworkrequired | string | |
lockout | LockoutView | |
lockout.minutesrequired | integer | |
lockout.thresholdrequired | integer | |
mfa | object or null | |
mfa.acceptedFactorsrequired | array of string | |
mfa.graceDaysrequired | integer | |
mfa.requirementrequired | string | |
password | PasswordView | |
password.breachScreen | boolean or null | |
password.historyCountrequired | integer | |
password.maxAgeDaysrequired | integer | |
password.minLengthrequired | integer | |
password.requireDigitrequired | boolean | |
password.requireSymbolrequired | boolean | |
password.requireUpperrequired | boolean | |
passwordless | PasswordlessView | passwordlessView is whether a passkey alone may sign somebody in. |
passwordless.allowedrequired | boolean | |
rememberDevice | RememberView | |
rememberDevice.daysrequired | integer | |
rememberDevice.enabledrequired | boolean | |
rowVersion | integer or null | int64. |
session | SessionView | |
session.absoluteHoursrequired | integer | |
session.idleMinutesrequired | integer |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
200 | application/json, SecurityPolicyResponse | Success. |
400 | application/problem+json, ProblemDetails | The request body is not acceptable. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold client:manage. |
200 response body
| Field | Type | Description |
|---|---|---|
effectivePasswordrequired | PasswordView | |
effectivePassword.breachScreen | boolean or null | |
effectivePassword.historyCountrequired | integer | |
effectivePassword.maxAgeDaysrequired | integer | |
effectivePassword.minLengthrequired | integer | |
effectivePassword.requireDigitrequired | boolean | |
effectivePassword.requireSymbolrequired | boolean | |
effectivePassword.requireUpperrequired | boolean | |
frameworkrequired | string | |
frameworksrequired | array of FrameworkView | |
frameworks[].coderequired | string | |
frameworks[].labelrequired | string | |
frameworks[].lockoutrequired | LockoutView | |
frameworks[].lockout.minutesrequired | integer | |
frameworks[].lockout.thresholdrequired | integer | |
frameworks[].mfaRequirementrequired | string | |
frameworks[].noterequired | string | |
frameworks[].passwordrequired | PasswordView | |
frameworks[].password.breachScreen | boolean or null | |
frameworks[].password.historyCountrequired | integer | |
frameworks[].password.maxAgeDaysrequired | integer | |
frameworks[].password.minLengthrequired | integer | |
frameworks[].password.requireDigitrequired | boolean | |
frameworks[].password.requireSymbolrequired | boolean | |
frameworks[].password.requireUpperrequired | boolean | |
frameworks[].sessionrequired | SessionView | |
frameworks[].session.absoluteHoursrequired | integer | |
frameworks[].session.idleMinutesrequired | integer | |
lockoutrequired | LockoutView | |
lockout.minutesrequired | integer | |
lockout.thresholdrequired | integer | |
mfarequired | MfaView | |
mfa.acceptedFactorsrequired | array of string | |
mfa.enforcedFrom | string (date-time) or null | |
mfa.graceDaysrequired | integer | |
mfa.requiredSince | string (date-time) or null | |
mfa.requirementrequired | string | |
mfa.supportedFactorsrequired | array of string | |
passwordrequired | PasswordView | |
password.breachScreen | boolean or null | |
password.historyCountrequired | integer | |
password.maxAgeDaysrequired | integer | |
password.minLengthrequired | integer | |
password.requireDigitrequired | boolean | |
password.requireSymbolrequired | boolean | |
password.requireUpperrequired | boolean | |
passwordlessrequired | PasswordlessView | passwordlessView is whether a passkey alone may sign somebody in. |
passwordless.allowedrequired | boolean | |
policyVersionrequired | integer | |
reauthRequired | boolean or null | |
rememberDevicerequired | RememberView | |
rememberDevice.daysrequired | integer | |
rememberDevice.enabledrequired | boolean | |
rowVersionrequired | integer | int64. |
sessionrequired | SessionView | |
session.absoluteHoursrequired | integer | |
session.idleMinutesrequired | integer |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.curl -X PUT 'https://depot.example.com/api/v1/console/security-policy' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -b 'outpost_console=<console-session>' \ --data '{ "framework": "string", "lockout": { "minutes": 0, "threshold": 0 }, "mfa": { "acceptedFactors": [ "string" ], "graceDays": 0, "requirement": "string" }, "password": { "breachScreen": false, "historyCount": 0, "maxAgeDays": 0, "minLength": 0, "requireDigit": false, "requireSymbol": false, "requireUpper": false }, "passwordless": { "allowed": false }, "rememberDevice": { "days": 0, "enabled": false }, "rowVersion": 0, "session": { "absoluteHours": 0, "idleMinutes": 0 }}'# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Content-Type' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$body = @'{ "framework": "string", "lockout": { "minutes": 0, "threshold": 0 }, "mfa": { "acceptedFactors": [ "string" ], "graceDays": 0, "requirement": "string" }, "password": { "breachScreen": false, "historyCount": 0, "maxAgeDays": 0, "minLength": 0, "requireDigit": false, "requireSymbol": false, "requireUpper": false }, "passwordless": { "allowed": false }, "rememberDevice": { "days": 0, "enabled": false }, "rowVersion": 0, "session": { "absoluteHours": 0, "idleMinutes": 0 }}'@
$response = Invoke-RestMethod ` -Method Put ` -Uri 'https://depot.example.com/api/v1/console/security-policy' ` -Headers $headers ` -ContentType 'application/json' ` -Body $body
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
import requests
url = "https://depot.example.com/api/v1/console/security-policy"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", "Content-Type": "application/json",}cookies = { "outpost_console": "<console-session>",}payload = { "framework": "string", "lockout": { "minutes": 0, "threshold": 0, }, "mfa": { "acceptedFactors": [ "string", ], "graceDays": 0, "requirement": "string", }, "password": { "breachScreen": False, "historyCount": 0, "maxAgeDays": 0, "minLength": 0, "requireDigit": False, "requireSymbol": False, "requireUpper": False, }, "passwordless": { "allowed": False, }, "rememberDevice": { "days": 0, "enabled": False, }, "rowVersion": 0, "session": { "absoluteHours": 0, "idleMinutes": 0, },}
response = requests.put(url, headers=headers, cookies=cookies, json=payload, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.package main
import ( "bytes" "fmt" "io" "log" "net/http")
func main() { body := []byte(`{ "framework": "string", "lockout": { "minutes": 0, "threshold": 0 }, "mfa": { "acceptedFactors": [ "string" ], "graceDays": 0, "requirement": "string" }, "password": { "breachScreen": false, "historyCount": 0, "maxAgeDays": 0, "minLength": 0, "requireDigit": false, "requireSymbol": false, "requireUpper": false }, "passwordless": { "allowed": false }, "rememberDevice": { "days": 0, "enabled": false }, "rowVersion": 0, "session": { "absoluteHours": 0, "idleMinutes": 0 }}`)
req, err := http.NewRequest(http.MethodPut, "https://depot.example.com/api/v1/console/security-policy", bytes.NewReader(body)) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.Header.Set("Content-Type", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/security-policy";
const response = await fetch(url, { method: "PUT", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", "Content-Type": "application/json", }, credentials: "include", body: JSON.stringify({ "framework": "string", "lockout": { "minutes": 0, "threshold": 0 }, "mfa": { "acceptedFactors": [ "string" ], "graceDays": 0, "requirement": "string" }, "password": { "breachScreen": false, "historyCount": 0, "maxAgeDays": 0, "minLength": 0, "requireDigit": false, "requireSymbol": false, "requireUpper": false }, "passwordless": { "allowed": false }, "rememberDevice": { "days": 0, "enabled": false }, "rowVersion": 0, "session": { "absoluteHours": 0, "idleMinutes": 0 } }),});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.
using System;using System.Net.Http;using System.Text;
using var client = new HttpClient();
const string body = """{ "framework": "string", "lockout": { "minutes": 0, "threshold": 0 }, "mfa": { "acceptedFactors": [ "string" ], "graceDays": 0, "requirement": "string" }, "password": { "breachScreen": false, "historyCount": 0, "maxAgeDays": 0, "minLength": 0, "requireDigit": false, "requireSymbol": false, "requireUpper": false }, "passwordless": { "allowed": false }, "rememberDevice": { "days": 0, "enabled": false }, "rowVersion": 0, "session": { "absoluteHours": 0, "idleMinutes": 0 }}""";
var request = new HttpRequestMessage(HttpMethod.Put, "https://depot.example.com/api/v1/console/security-policy");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");request.Content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());GET /api/v1/console/users
Section titled “GET /api/v1/console/users”GETuser:manageshared facehosteditmspremoteIdempotent
Source: [object Object]
listUsers is the team page: one narrowed, ordered, paged slice of the roster.
PAGING IS A FIX HERE AND NOT ONLY A FEATURE. Each row costs two extra queries, the account’s roles and whether it has confirmed a second factor, and before this they ran for every user on the tenant on every load. They now run for the PAGE, so opening the team page stopped costing more as the team grew.
The response GAINS page and pageSize and keeps items and total, so it is a superset of what it sent before and every existing caller reads items unaffected. total was the row count and is now the count BEFORE paging, which is the number a pager needs and the same number whenever one page holds everybody, which today is every deployment.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
dir | query | string | No | |
page | query | string | No | |
pageSize | query | string | No | |
sort | query | string | No | |
status | query | string | No |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
200 | application/json, object | Success. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold user:manage. |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.curl -X GET 'https://depot.example.com/api/v1/console/users?dir=<dir>&page=<page>&pageSize=<pageSize>&sort=<sort>&status=<status>' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -b 'outpost_console=<console-session>'# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$response = Invoke-RestMethod ` -Method Get ` -Uri 'https://depot.example.com/api/v1/console/users?dir=<dir>&page=<page>&pageSize=<pageSize>&sort=<sort>&status=<status>' ` -Headers $headers
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
import requests
url = "https://depot.example.com/api/v1/console/users"params = { "dir": "<dir>", "page": "<page>", "pageSize": "<pageSize>", "sort": "<sort>", "status": "<status>",}headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json",}cookies = { "outpost_console": "<console-session>",}
response = requests.get(url, params=params, headers=headers, cookies=cookies, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.package main
import ( "fmt" "io" "log" "net/http")
func main() { req, err := http.NewRequest(http.MethodGet, "https://depot.example.com/api/v1/console/users?dir=<dir>&page=<page>&pageSize=<pageSize>&sort=<sort>&status=<status>", nil) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.// The session cookie is set by signing in. A script cannot set it itself.
const url = new URL("https://depot.example.com/api/v1/console/users");url.searchParams.set("dir", "<dir>");url.searchParams.set("page", "<page>");url.searchParams.set("pageSize", "<pageSize>");url.searchParams.set("sort", "<sort>");url.searchParams.set("status", "<status>");
const response = await fetch(url, { method: "GET", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", }, credentials: "include",});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.
using System;using System.Net.Http;
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://depot.example.com/api/v1/console/users?dir=<dir>&page=<page>&pageSize=<pageSize>&sort=<sort>&status=<status>");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());POST /api/v1/console/users
Section titled “POST /api/v1/console/users”POSTuser:manageshared facehosteditmspremote
Source: [object Object]
inviteUser creates an account and issues a single-use invitation.
The account starts “invited” with no credential, so it cannot sign in until the recipient accepts and chooses a password. The link is returned to the caller rather than emailed, because Depot has no outbound mail yet; when it does, this is the one line that changes.
Request body
Section titled “Request body”Required, sent as application/json.
| Field | Type | Description |
|---|---|---|
displayNamerequired | string | |
emailrequired | string | |
namedUserId | string or null | |
roleIdsrequired | array of string |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
201 | application/json, object | Created. |
400 | application/problem+json, ProblemDetails | The request body is not acceptable. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold user:manage. |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.curl -X POST 'https://depot.example.com/api/v1/console/users' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -b 'outpost_console=<console-session>' \ --data '{ "displayName": "string", "email": "string", "namedUserId": "string", "roleIds": [ "string" ]}'# Sign in first. outpost_console is a session cookie, so send it with every request.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Content-Type' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$body = @'{ "displayName": "string", "email": "string", "namedUserId": "string", "roleIds": [ "string" ]}'@
$response = Invoke-RestMethod ` -Method Post ` -Uri 'https://depot.example.com/api/v1/console/users' ` -Headers $headers ` -ContentType 'application/json' ` -Body $body
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.
import requests
url = "https://depot.example.com/api/v1/console/users"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", "Content-Type": "application/json",}cookies = { "outpost_console": "<console-session>",}payload = { "displayName": "string", "email": "string", "namedUserId": "string", "roleIds": [ "string", ],}
response = requests.post(url, headers=headers, cookies=cookies, json=payload, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.package main
import ( "bytes" "fmt" "io" "log" "net/http")
func main() { body := []byte(`{ "displayName": "string", "email": "string", "namedUserId": "string", "roleIds": [ "string" ]}`)
req, err := http.NewRequest(http.MethodPost, "https://depot.example.com/api/v1/console/users", bytes.NewReader(body)) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.Header.Set("Content-Type", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/users";
const response = await fetch(url, { method: "POST", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", "Content-Type": "application/json", }, credentials: "include", body: JSON.stringify({ "displayName": "string", "email": "string", "namedUserId": "string", "roleIds": [ "string" ] }),});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.
using System;using System.Net.Http;using System.Text;
using var client = new HttpClient();
const string body = """{ "displayName": "string", "email": "string", "namedUserId": "string", "roleIds": [ "string" ]}""";
var request = new HttpRequestMessage(HttpMethod.Post, "https://depot.example.com/api/v1/console/users");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");request.Content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());PATCH /api/v1/console/users/{userId}
Section titled “PATCH /api/v1/console/users/{userId}”PATCHuser:manageshared facehosteditmspremote
Source: [object Object]
patchUser changes an account’s status.
Disabling also ends its sessions, in the store, in the same transaction.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
userId | path | string | Yes |
Request body
Section titled “Request body”Required, sent as application/json.
| Field | Type | Description |
|---|---|---|
statusrequired | string |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
204 | None | Success, with no body. |
400 | application/problem+json, ProblemDetails | The request body is not acceptable. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold user:manage. |
404 | application/problem+json, ProblemDetails | No resource matches that id. |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.curl -X PATCH 'https://depot.example.com/api/v1/console/users/<userId>' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -b 'outpost_console=<console-session>' \ --data '{ "status": "string"}'# Sign in first. outpost_console is a session cookie, so send it with every request.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Content-Type' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$body = @'{ "status": "string"}'@
$response = Invoke-RestMethod ` -Method Patch ` -Uri 'https://depot.example.com/api/v1/console/users/<userId>' ` -Headers $headers ` -ContentType 'application/json' ` -Body $body
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.
import requests
url = "https://depot.example.com/api/v1/console/users/<userId>"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", "Content-Type": "application/json",}cookies = { "outpost_console": "<console-session>",}payload = { "status": "string",}
response = requests.patch(url, headers=headers, cookies=cookies, json=payload, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.package main
import ( "bytes" "fmt" "io" "log" "net/http")
func main() { body := []byte(`{ "status": "string"}`)
req, err := http.NewRequest(http.MethodPatch, "https://depot.example.com/api/v1/console/users/<userId>", bytes.NewReader(body)) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.Header.Set("Content-Type", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/users/<userId>";
const response = await fetch(url, { method: "PATCH", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", "Content-Type": "application/json", }, credentials: "include", body: JSON.stringify({ "status": "string" }),});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.
using System;using System.Net.Http;using System.Text;
using var client = new HttpClient();
const string body = """{ "status": "string"}""";
var request = new HttpRequestMessage(HttpMethod.Patch, "https://depot.example.com/api/v1/console/users/<userId>");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");request.Content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());DELETE /api/v1/console/users/{userId}
Section titled “DELETE /api/v1/console/users/{userId}”DELETEuser:manageshared facehosteditmspremoteIdempotent
Source: [object Object]
Delete user
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
userId | path | string | Yes |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
204 | None | Success, with no body. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold user:manage. |
404 | application/problem+json, ProblemDetails | No resource matches that id. |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.curl -X DELETE 'https://depot.example.com/api/v1/console/users/<userId>' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -b 'outpost_console=<console-session>'# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$response = Invoke-RestMethod ` -Method Delete ` -Uri 'https://depot.example.com/api/v1/console/users/<userId>' ` -Headers $headers
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
import requests
url = "https://depot.example.com/api/v1/console/users/<userId>"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json",}cookies = { "outpost_console": "<console-session>",}
response = requests.delete(url, headers=headers, cookies=cookies, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.package main
import ( "fmt" "io" "log" "net/http")
func main() { req, err := http.NewRequest(http.MethodDelete, "https://depot.example.com/api/v1/console/users/<userId>", nil) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/users/<userId>";
const response = await fetch(url, { method: "DELETE", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", }, credentials: "include",});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.
using System;using System.Net.Http;
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Delete, "https://depot.example.com/api/v1/console/users/<userId>");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());POST /api/v1/console/users/{userId}/invite
Section titled “POST /api/v1/console/users/{userId}/invite”POSTuser:manageshared facehosteditmspremote
Source: [object Object]
reinviteUser issues a fresh invitation for an account that has not accepted yet, for the ordinary case of a link that expired or never arrived.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
userId | path | string | Yes |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
200 | application/json, object | Success. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold user:manage. |
404 | application/problem+json, ProblemDetails | No resource matches that id. |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.curl -X POST 'https://depot.example.com/api/v1/console/users/<userId>/invite' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -b 'outpost_console=<console-session>'# Sign in first. outpost_console is a session cookie, so send it with every request.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$response = Invoke-RestMethod ` -Method Post ` -Uri 'https://depot.example.com/api/v1/console/users/<userId>/invite' ` -Headers $headers
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.
import requests
url = "https://depot.example.com/api/v1/console/users/<userId>/invite"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json",}cookies = { "outpost_console": "<console-session>",}
response = requests.post(url, headers=headers, cookies=cookies, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.package main
import ( "fmt" "io" "log" "net/http")
func main() { req, err := http.NewRequest(http.MethodPost, "https://depot.example.com/api/v1/console/users/<userId>/invite", nil) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/users/<userId>/invite";
const response = await fetch(url, { method: "POST", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", }, credentials: "include",});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.
using System;using System.Net.Http;
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://depot.example.com/api/v1/console/users/<userId>/invite");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());GET /api/v1/console/users/{userId}/login-policy
Section titled “GET /api/v1/console/users/{userId}/login-policy”GETuser:manageshared facehosteditmspremoteIdempotent
Source: [object Object]
getUserLoginPolicy returns one user’s additional restrictions.
It exists because the team page’s per-person panel is the SAME editor component the organisation tab uses, and an editor with no read opens holding its defaults. Pressing Save then replaces whatever that person actually had with them, silently, and the person finds out when they cannot sign in. A route that answers 405 to a GET is not a neutral omission here; it is a data loss the console cannot defend against on its own.
The rules ride the row GetConsoleUser already returns, so this costs one lookup and no new query. TimeZone is the CLIENT’s, echoed so the editor can say which zone the hours are read in; it is read only on this route, and saveUserLoginPolicy ignores it.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
userId | path | string | Yes |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
200 | application/json, LoginPolicyResponse | Success. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold user:manage. |
404 | application/problem+json, ProblemDetails | No resource matches that id. |
200 response body
| Field | Type | Description |
|---|---|---|
callerIprequired | string | |
ipAllowlistrequired | string | |
timeZonerequired | string | |
week | array of array of WindowView or null | |
week[][].endMinuterequired | integer | |
week[][].startMinuterequired | integer |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.curl -X GET 'https://depot.example.com/api/v1/console/users/<userId>/login-policy' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -b 'outpost_console=<console-session>'# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$response = Invoke-RestMethod ` -Method Get ` -Uri 'https://depot.example.com/api/v1/console/users/<userId>/login-policy' ` -Headers $headers
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
import requests
url = "https://depot.example.com/api/v1/console/users/<userId>/login-policy"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json",}cookies = { "outpost_console": "<console-session>",}
response = requests.get(url, headers=headers, cookies=cookies, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.package main
import ( "fmt" "io" "log" "net/http")
func main() { req, err := http.NewRequest(http.MethodGet, "https://depot.example.com/api/v1/console/users/<userId>/login-policy", nil) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/users/<userId>/login-policy";
const response = await fetch(url, { method: "GET", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", }, credentials: "include",});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.
using System;using System.Net.Http;
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://depot.example.com/api/v1/console/users/<userId>/login-policy");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());PUT /api/v1/console/users/{userId}/login-policy
Section titled “PUT /api/v1/console/users/{userId}/login-policy”PUTuser:manageshared facehosteditmspremoteIdempotent
Source: [object Object]
saveUserLoginPolicy writes one user’s additional restrictions.
THERE IS DELIBERATELY NO LOCKOUT GUARD HERE, and it is not an oversight.
An administrator setting rules on somebody else’s account is doing exactly what this feature is for - pinning a contractor to one network, or a part-timer to their shift - and refusing it because the SUBJECT would be excluded from where they happen to be sitting would refuse the ordinary case and, worse, would leak where that person currently is to whoever edits their account. The subject is not locked out of anything an administrator cannot undo from this same screen, which is the property the client-wide guard does not have.
An administrator who narrows their OWN account through this route can lock themselves out. That is accepted for the same reason: another owner can clear it, the route is guarded by user:manage, and adding a self-check here would mean the guard fires on one row in the list and not the others, which reads as a bug rather than as a warning.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
userId | path | string | Yes |
Request body
Section titled “Request body”Required, sent as application/json.
| Field | Type | Description |
|---|---|---|
acknowledgeLockoutrequired | boolean | |
ipAllowlistrequired | string | |
timeZonerequired | string | |
week | array of array of WindowView or null | |
week[][].endMinuterequired | integer | |
week[][].startMinuterequired | integer |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
204 | None | Success, with no body. |
400 | application/problem+json, ProblemDetails | The request body is not acceptable. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold user:manage. |
404 | application/problem+json, ProblemDetails | No resource matches that id. |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.curl -X PUT 'https://depot.example.com/api/v1/console/users/<userId>/login-policy' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -b 'outpost_console=<console-session>' \ --data '{ "acknowledgeLockout": false, "ipAllowlist": "string", "timeZone": "string", "week": [ [ { "endMinute": 0, "startMinute": 0 } ] ]}'# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Content-Type' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$body = @'{ "acknowledgeLockout": false, "ipAllowlist": "string", "timeZone": "string", "week": [ [ { "endMinute": 0, "startMinute": 0 } ] ]}'@
$response = Invoke-RestMethod ` -Method Put ` -Uri 'https://depot.example.com/api/v1/console/users/<userId>/login-policy' ` -Headers $headers ` -ContentType 'application/json' ` -Body $body
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
import requests
url = "https://depot.example.com/api/v1/console/users/<userId>/login-policy"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", "Content-Type": "application/json",}cookies = { "outpost_console": "<console-session>",}payload = { "acknowledgeLockout": False, "ipAllowlist": "string", "timeZone": "string", "week": [ [ { "endMinute": 0, "startMinute": 0, }, ], ],}
response = requests.put(url, headers=headers, cookies=cookies, json=payload, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.package main
import ( "bytes" "fmt" "io" "log" "net/http")
func main() { body := []byte(`{ "acknowledgeLockout": false, "ipAllowlist": "string", "timeZone": "string", "week": [ [ { "endMinute": 0, "startMinute": 0 } ] ]}`)
req, err := http.NewRequest(http.MethodPut, "https://depot.example.com/api/v1/console/users/<userId>/login-policy", bytes.NewReader(body)) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.Header.Set("Content-Type", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/users/<userId>/login-policy";
const response = await fetch(url, { method: "PUT", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", "Content-Type": "application/json", }, credentials: "include", body: JSON.stringify({ "acknowledgeLockout": false, "ipAllowlist": "string", "timeZone": "string", "week": [ [ { "endMinute": 0, "startMinute": 0 } ] ] }),});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.
using System;using System.Net.Http;using System.Text;
using var client = new HttpClient();
const string body = """{ "acknowledgeLockout": false, "ipAllowlist": "string", "timeZone": "string", "week": [ [ { "endMinute": 0, "startMinute": 0 } ] ]}""";
var request = new HttpRequestMessage(HttpMethod.Put, "https://depot.example.com/api/v1/console/users/<userId>/login-policy");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");request.Content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());GET /api/v1/console/users/{userId}/passkeys
Section titled “GET /api/v1/console/users/{userId}/passkeys”GETuser:manageshared facehosteditmspremoteIdempotent
Source: [object Object]
List user passkeys
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
userId | path | string | Yes |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
200 | application/json, object | Success. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold user:manage. |
404 | application/problem+json, ProblemDetails | No resource matches that id. |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.curl -X GET 'https://depot.example.com/api/v1/console/users/<userId>/passkeys' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -b 'outpost_console=<console-session>'# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$response = Invoke-RestMethod ` -Method Get ` -Uri 'https://depot.example.com/api/v1/console/users/<userId>/passkeys' ` -Headers $headers
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
import requests
url = "https://depot.example.com/api/v1/console/users/<userId>/passkeys"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json",}cookies = { "outpost_console": "<console-session>",}
response = requests.get(url, headers=headers, cookies=cookies, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.package main
import ( "fmt" "io" "log" "net/http")
func main() { req, err := http.NewRequest(http.MethodGet, "https://depot.example.com/api/v1/console/users/<userId>/passkeys", nil) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/users/<userId>/passkeys";
const response = await fetch(url, { method: "GET", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", }, credentials: "include",});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.
using System;using System.Net.Http;
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://depot.example.com/api/v1/console/users/<userId>/passkeys");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());DELETE /api/v1/console/users/{userId}/passkeys/{passkeyId}
Section titled “DELETE /api/v1/console/users/{userId}/passkeys/{passkeyId}”DELETEuser:manageshared facehosteditmspremoteIdempotent
Source: [object Object]
removeUserPasskey is an owner taking a passkey off somebody’s account: a lost laptop, a departed contractor’s key.
Owners only, on top of user:manage, because it changes how somebody else signs in.
The person’s sessions end and their remembered browsers are forgotten: the usual reason to do this is that the passkey is in the wrong hands, and a session it opened is in the same hands. An owner removing their own from this page keeps their own session; the account page is the ordinary route for that and asks for nothing more.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
passkeyId | path | string | Yes | |
userId | path | string | Yes |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
204 | None | Success, with no body. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold user:manage. |
404 | application/problem+json, ProblemDetails | No resource matches that id. |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.curl -X DELETE 'https://depot.example.com/api/v1/console/users/<userId>/passkeys/<passkeyId>' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -b 'outpost_console=<console-session>'# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$response = Invoke-RestMethod ` -Method Delete ` -Uri 'https://depot.example.com/api/v1/console/users/<userId>/passkeys/<passkeyId>' ` -Headers $headers
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
import requests
url = "https://depot.example.com/api/v1/console/users/<userId>/passkeys/<passkeyId>"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json",}cookies = { "outpost_console": "<console-session>",}
response = requests.delete(url, headers=headers, cookies=cookies, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.package main
import ( "fmt" "io" "log" "net/http")
func main() { req, err := http.NewRequest(http.MethodDelete, "https://depot.example.com/api/v1/console/users/<userId>/passkeys/<passkeyId>", nil) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/users/<userId>/passkeys/<passkeyId>";
const response = await fetch(url, { method: "DELETE", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", }, credentials: "include",});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.
using System;using System.Net.Http;
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Delete, "https://depot.example.com/api/v1/console/users/<userId>/passkeys/<passkeyId>");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());PUT /api/v1/console/users/{userId}/roles/{roleCode}
Section titled “PUT /api/v1/console/users/{userId}/roles/{roleCode}”PUTrole:manageshared facehosteditmspremoteIdempotent
Source: [object Object]
Grant role
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
roleCode | path | string | Yes | |
userId | path | string | Yes |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
204 | None | Success, with no body. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold role:manage. |
404 | application/problem+json, ProblemDetails | No resource matches that id. |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.curl -X PUT 'https://depot.example.com/api/v1/console/users/<userId>/roles/<roleCode>' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -b 'outpost_console=<console-session>'# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$response = Invoke-RestMethod ` -Method Put ` -Uri 'https://depot.example.com/api/v1/console/users/<userId>/roles/<roleCode>' ` -Headers $headers
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
import requests
url = "https://depot.example.com/api/v1/console/users/<userId>/roles/<roleCode>"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json",}cookies = { "outpost_console": "<console-session>",}
response = requests.put(url, headers=headers, cookies=cookies, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.package main
import ( "fmt" "io" "log" "net/http")
func main() { req, err := http.NewRequest(http.MethodPut, "https://depot.example.com/api/v1/console/users/<userId>/roles/<roleCode>", nil) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/users/<userId>/roles/<roleCode>";
const response = await fetch(url, { method: "PUT", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", }, credentials: "include",});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.
using System;using System.Net.Http;
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Put, "https://depot.example.com/api/v1/console/users/<userId>/roles/<roleCode>");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());DELETE /api/v1/console/users/{userId}/roles/{roleCode}
Section titled “DELETE /api/v1/console/users/{userId}/roles/{roleCode}”DELETErole:manageshared facehosteditmspremoteIdempotent
Source: [object Object]
Revoke role
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
roleCode | path | string | Yes | |
userId | path | string | Yes |
Responses
Section titled “Responses”| Status | Body | Description |
|---|---|---|
204 | None | Success, with no body. |
401 | application/problem+json, ProblemDetails | No signed-in identity. |
403 | application/problem+json, ProblemDetails | The identity does not hold role:manage. |
404 | application/problem+json, ProblemDetails | No resource matches that id. |
Request samples
Section titled “Request samples”# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.curl -X DELETE 'https://depot.example.com/api/v1/console/users/<userId>/roles/<roleCode>' \ -H 'X-CSRF-Token: <csrf-token>' \ -H 'Accept: application/json' \ -b 'outpost_console=<console-session>'# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
$headers = @{ 'X-CSRF-Token' = '<csrf-token>' 'Accept' = 'application/json' 'Cookie' = 'outpost_console=<console-session>'}
$response = Invoke-RestMethod ` -Method Delete ` -Uri 'https://depot.example.com/api/v1/console/users/<userId>/roles/<roleCode>' ` -Headers $headers
$response | ConvertTo-Json -Depth 10# Sign in first. outpost_console is a session cookie, so send it with every request.# This operation is idempotent. Repeating it does not repeat its effect.
import requests
url = "https://depot.example.com/api/v1/console/users/<userId>/roles/<roleCode>"headers = { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json",}cookies = { "outpost_console": "<console-session>",}
response = requests.delete(url, headers=headers, cookies=cookies, timeout=30)response.raise_for_status()print(response.json())// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.package main
import ( "fmt" "io" "log" "net/http")
func main() { req, err := http.NewRequest(http.MethodDelete, "https://depot.example.com/api/v1/console/users/<userId>/roles/<roleCode>", nil) if err != nil { log.Fatal(err) }
req.Header.Set("X-CSRF-Token", "<csrf-token>") req.Header.Set("Accept", "application/json") req.AddCookie(&http.Cookie{Name: "outpost_console", Value: "<console-session>"})
resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(resp.Status, string(out))}// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.// The session cookie is set by signing in. A script cannot set it itself.
const url = "https://depot.example.com/api/v1/console/users/<userId>/roles/<roleCode>";
const response = await fetch(url, { method: "DELETE", headers: { "X-CSRF-Token": "<csrf-token>", "Accept": "application/json", }, credentials: "include",});
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`);}
const data = await response.json();console.log(data);// Sign in first. outpost_console is a session cookie, so send it with every request.// This operation is idempotent. Repeating it does not repeat its effect.
using System;using System.Net.Http;
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Delete, "https://depot.example.com/api/v1/console/users/<userId>/roles/<roleCode>");request.Headers.TryAddWithoutValidation("X-CSRF-Token", "<csrf-token>");request.Headers.TryAddWithoutValidation("Accept", "application/json");request.Headers.TryAddWithoutValidation("Cookie", "outpost_console=<console-session>");
var response = await client.SendAsync(request);response.EnsureSuccessStatusCode();Console.WriteLine(await response.Content.ReadAsStringAsync());Content is licensed CC BY 4.0. Code samples are MIT. Outpost and the Outpost mark are trademarks of Outpost Business Solutions, PBC and are not covered by either license.