---
title: "Depot portalapi"
description: "Every portalapi operation in the Depot API, with parameters, responses and code samples in six languages."
url: "https://support.outpostplatform.com/api/generated/depot/portalapi/"
product: "depot"
type: "reference"
status: "reviewed"
last_reviewed: 2026-11-06
source: "https://gitlab.com/outpostplatform/docs/-/edit/main/src/content/docs/api/generated/depot/portalapi.mdx"
license: "CC BY 4.0"
---

# Depot portalapi

Is Mount under a name of its own, so tools/apispec can tell it from the console's API.Mount.

This page is generated from the Depot route table. Every operation carries the permission it needs and the anchor an agent can link to.

### GET `/api/portal/v1/auth/invites/{token}` {#depot.portalapi.inviteRead}

**inviteRead shows the accept page what it needs.**

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `token` | path | string | Yes |  |

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `200` | `application/json`, object | Success. |
| `404` | `application/problem+json`, ProblemDetails | No resource matches that id. |

#### Request samples

```bash
# This operation is public. It takes no credentials.
# This operation is idempotent. Repeating it does not repeat its effect.
curl -X GET 'https://depot.example.com/api/portal/v1/auth/invites/<token>' \
  -H 'Accept: application/json'
```

```powershell
# This operation is public. It takes no credentials.
# This operation is idempotent. Repeating it does not repeat its effect.

$headers = @{
    'Accept' = 'application/json'
}

$response = Invoke-RestMethod `
    -Method Get `
    -Uri 'https://depot.example.com/api/portal/v1/auth/invites/<token>' `
    -Headers $headers

$response | ConvertTo-Json -Depth 10
```

```python
# This operation is public. It takes no credentials.
# This operation is idempotent. Repeating it does not repeat its effect.

import requests

url = "https://depot.example.com/api/portal/v1/auth/invites/<token>"
headers = {
    "Accept": "application/json",
}

response = requests.get(url, headers=headers, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// This operation is public. It takes no credentials.
// 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/portal/v1/auth/invites/<token>", nil)
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("Accept", "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))
}
```

```ts
// This operation is public. It takes no credentials.
// This operation is idempotent. Repeating it does not repeat its effect.

const url = "https://depot.example.com/api/portal/v1/auth/invites/<token>";

const response = await fetch(url, {
	method: "GET",
	headers: {
		"Accept": "application/json",
	},
});

if (!response.ok) {
	throw new Error(`Request failed with status ${response.status}`);
}

const data = await response.json();
console.log(data);
```

```csharp
// This operation is public. It takes no credentials.
// 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/portal/v1/auth/invites/<token>");
request.Headers.TryAddWithoutValidation("Accept", "application/json");

var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

### POST `/api/portal/v1/auth/invites/{token}/accept` {#depot.portalapi.inviteAccept}

**inviteAccept accepts an invitation.**

Someone already signed in with the invited address accepts as they are; an existing identity proves itself with its password; a new one sets a password here. The membership becomes active, and the person still owes (or, the first time, enrols) a second factor before the session is active.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `token` | path | string | Yes |  |

#### Request body

Required, sent as `application/json`.

The body is `any`.

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `200` | `application/json`, Me | Success. |
| `400` | None | The request was refused. |
| `404` | `application/problem+json`, ProblemDetails | No resource matches that id. |

#### Request samples

```bash
# This operation is public. It takes no credentials.
curl -X POST 'https://depot.example.com/api/portal/v1/auth/invites/<token>/accept' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  --data '"string"'
```

```powershell
# This operation is public. It takes no credentials.

$headers = @{
    'Accept' = 'application/json'
    'Content-Type' = 'application/json'
}

$body = @'
"string"
'@

$response = Invoke-RestMethod `
    -Method Post `
    -Uri 'https://depot.example.com/api/portal/v1/auth/invites/<token>/accept' `
    -Headers $headers `
    -ContentType 'application/json' `
    -Body $body

$response | ConvertTo-Json -Depth 10
```

```python
# This operation is public. It takes no credentials.

import requests

url = "https://depot.example.com/api/portal/v1/auth/invites/<token>/accept"
headers = {
    "Accept": "application/json",
    "Content-Type": "application/json",
}
payload = "string"

response = requests.post(url, headers=headers, json=payload, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// This operation is public. It takes no credentials.
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	body := []byte(`"string"`)

	req, err := http.NewRequest(http.MethodPost, "https://depot.example.com/api/portal/v1/auth/invites/<token>/accept", bytes.NewReader(body))
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("Accept", "application/json")
	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))
}
```

```ts
// This operation is public. It takes no credentials.

const url = "https://depot.example.com/api/portal/v1/auth/invites/<token>/accept";

const response = await fetch(url, {
	method: "POST",
	headers: {
		"Accept": "application/json",
		"Content-Type": "application/json",
	},
	body: JSON.stringify("string"),
});

if (!response.ok) {
	throw new Error(`Request failed with status ${response.status}`);
}

const data = await response.json();
console.log(data);
```

```csharp
// 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 = """
"string"
""";

var request = new HttpRequestMessage(HttpMethod.Post, "https://depot.example.com/api/portal/v1/auth/invites/<token>/accept");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
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/portal/v1/auth/login` {#depot.portalapi.login}

**login verifies an email address and password and starts a session that still owes its second factor (pending_mfa).**

Every failure is the same 401 invalid_credentials, whether the address is
unknown, the identity is locked or disabled, or the password is wrong, and
the unknown-address path burns the same PBKDF2 work: telling them apart
would make the sign-in form a membership oracle for the MSP's customers.

#### Request body

Required, sent as `application/json`.

The body is `any`.

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `200` | `application/json`, Me | Success. |
| `400` | `application/problem+json`, ProblemDetails | The request body is not acceptable. |

#### Request samples

```bash
# This operation is public. It takes no credentials.
curl -X POST 'https://depot.example.com/api/portal/v1/auth/login' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  --data '"string"'
```

```powershell
# This operation is public. It takes no credentials.

$headers = @{
    'Accept' = 'application/json'
    'Content-Type' = 'application/json'
}

$body = @'
"string"
'@

$response = Invoke-RestMethod `
    -Method Post `
    -Uri 'https://depot.example.com/api/portal/v1/auth/login' `
    -Headers $headers `
    -ContentType 'application/json' `
    -Body $body

$response | ConvertTo-Json -Depth 10
```

```python
# This operation is public. It takes no credentials.

import requests

url = "https://depot.example.com/api/portal/v1/auth/login"
headers = {
    "Accept": "application/json",
    "Content-Type": "application/json",
}
payload = "string"

response = requests.post(url, headers=headers, json=payload, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// This operation is public. It takes no credentials.
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	body := []byte(`"string"`)

	req, err := http.NewRequest(http.MethodPost, "https://depot.example.com/api/portal/v1/auth/login", bytes.NewReader(body))
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("Accept", "application/json")
	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))
}
```

```ts
// This operation is public. It takes no credentials.

const url = "https://depot.example.com/api/portal/v1/auth/login";

const response = await fetch(url, {
	method: "POST",
	headers: {
		"Accept": "application/json",
		"Content-Type": "application/json",
	},
	body: JSON.stringify("string"),
});

if (!response.ok) {
	throw new Error(`Request failed with status ${response.status}`);
}

const data = await response.json();
console.log(data);
```

```csharp
// 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 = """
"string"
""";

var request = new HttpRequestMessage(HttpMethod.Post, "https://depot.example.com/api/portal/v1/auth/login");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
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/portal/v1/auth/logout` {#depot.portalapi.logout}

**logout revokes the current session.**

Idempotent: always 204.

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `204` | None | Success, with no body. |

#### Request samples

```bash
# This operation is public. It takes no credentials.
curl -X POST 'https://depot.example.com/api/portal/v1/auth/logout'
```

```powershell
# This operation is public. It takes no credentials.

$response = Invoke-RestMethod `
    -Method Post `
    -Uri 'https://depot.example.com/api/portal/v1/auth/logout'

$response | ConvertTo-Json -Depth 10
```

```python
# This operation is public. It takes no credentials.

import requests

url = "https://depot.example.com/api/portal/v1/auth/logout"

response = requests.post(url, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// This operation is public. It takes no credentials.
package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	req, err := http.NewRequest(http.MethodPost, "https://depot.example.com/api/portal/v1/auth/logout", nil)
	if err != nil {
		log.Fatal(err)
	}

	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))
}
```

```ts
// This operation is public. It takes no credentials.

const url = "https://depot.example.com/api/portal/v1/auth/logout";

const response = await fetch(url, {
	method: "POST",
});

if (!response.ok) {
	throw new Error(`Request failed with status ${response.status}`);
}

const data = await response.json();
console.log(data);
```

```csharp
// This operation is public. It takes no credentials.

using System;
using System.Net.Http;

using var client = new HttpClient();

var request = new HttpRequestMessage(HttpMethod.Post, "https://depot.example.com/api/portal/v1/auth/logout");

var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

### POST `/api/portal/v1/auth/mfa/recovery` {#depot.portalapi.mfaRecovery}

**mfaRecovery completes a pending sign-in with a recovery code.**

#### Request body

Required, sent as `application/json`.

The body is `any`.

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `200` | `application/json`, Me | Success. |
| `400` | `application/problem+json`, ProblemDetails | The request body is not acceptable. |

#### Request samples

```bash
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.
curl -X POST 'https://depot.example.com/api/portal/v1/auth/mfa/recovery' \
  -H 'X-Csrf-Token: <portal-csrf>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -b '__Host-portal_session=<portal-session>' \
  --data '"string"'
```

```powershell
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

$headers = @{
    'X-Csrf-Token' = '<portal-csrf>'
    'Accept' = 'application/json'
    'Content-Type' = 'application/json'
    'Cookie' = '__Host-portal_session=<portal-session>'
}

$body = @'
"string"
'@

$response = Invoke-RestMethod `
    -Method Post `
    -Uri 'https://depot.example.com/api/portal/v1/auth/mfa/recovery' `
    -Headers $headers `
    -ContentType 'application/json' `
    -Body $body

$response | ConvertTo-Json -Depth 10
```

```python
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

import requests

url = "https://depot.example.com/api/portal/v1/auth/mfa/recovery"
headers = {
    "X-Csrf-Token": "<portal-csrf>",
    "Accept": "application/json",
    "Content-Type": "application/json",
}
cookies = {
    "__Host-portal_session": "<portal-session>",
}
payload = "string"

response = requests.post(url, headers=headers, cookies=cookies, json=payload, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// Sign in first. __Host-portal_session is a session cookie, so send it with every request.
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	body := []byte(`"string"`)

	req, err := http.NewRequest(http.MethodPost, "https://depot.example.com/api/portal/v1/auth/mfa/recovery", bytes.NewReader(body))
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("X-Csrf-Token", "<portal-csrf>")
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	req.AddCookie(&http.Cookie{Name: "__Host-portal_session", Value: "<portal-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))
}
```

```ts
// Sign in first. __Host-portal_session 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/portal/v1/auth/mfa/recovery";

const response = await fetch(url, {
	method: "POST",
	headers: {
		"X-Csrf-Token": "<portal-csrf>",
		"Accept": "application/json",
		"Content-Type": "application/json",
	},
	credentials: "include",
	body: JSON.stringify("string"),
});

if (!response.ok) {
	throw new Error(`Request failed with status ${response.status}`);
}

const data = await response.json();
console.log(data);
```

```csharp
// Sign in first. __Host-portal_session 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 = """
"string"
""";

var request = new HttpRequestMessage(HttpMethod.Post, "https://depot.example.com/api/portal/v1/auth/mfa/recovery");
request.Headers.TryAddWithoutValidation("X-Csrf-Token", "<portal-csrf>");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Cookie", "__Host-portal_session=<portal-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/portal/v1/auth/mfa/totp` {#depot.portalapi.mfaTotp}

**mfaTotp completes a pending sign-in with a TOTP code.**

#### Request body

Required, sent as `application/json`.

The body is `any`.

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `200` | `application/json`, Me | Success. |
| `400` | `application/problem+json`, ProblemDetails | The request body is not acceptable. |

#### Request samples

```bash
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.
curl -X POST 'https://depot.example.com/api/portal/v1/auth/mfa/totp' \
  -H 'X-Csrf-Token: <portal-csrf>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -b '__Host-portal_session=<portal-session>' \
  --data '"string"'
```

```powershell
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

$headers = @{
    'X-Csrf-Token' = '<portal-csrf>'
    'Accept' = 'application/json'
    'Content-Type' = 'application/json'
    'Cookie' = '__Host-portal_session=<portal-session>'
}

$body = @'
"string"
'@

$response = Invoke-RestMethod `
    -Method Post `
    -Uri 'https://depot.example.com/api/portal/v1/auth/mfa/totp' `
    -Headers $headers `
    -ContentType 'application/json' `
    -Body $body

$response | ConvertTo-Json -Depth 10
```

```python
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

import requests

url = "https://depot.example.com/api/portal/v1/auth/mfa/totp"
headers = {
    "X-Csrf-Token": "<portal-csrf>",
    "Accept": "application/json",
    "Content-Type": "application/json",
}
cookies = {
    "__Host-portal_session": "<portal-session>",
}
payload = "string"

response = requests.post(url, headers=headers, cookies=cookies, json=payload, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// Sign in first. __Host-portal_session is a session cookie, so send it with every request.
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	body := []byte(`"string"`)

	req, err := http.NewRequest(http.MethodPost, "https://depot.example.com/api/portal/v1/auth/mfa/totp", bytes.NewReader(body))
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("X-Csrf-Token", "<portal-csrf>")
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	req.AddCookie(&http.Cookie{Name: "__Host-portal_session", Value: "<portal-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))
}
```

```ts
// Sign in first. __Host-portal_session 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/portal/v1/auth/mfa/totp";

const response = await fetch(url, {
	method: "POST",
	headers: {
		"X-Csrf-Token": "<portal-csrf>",
		"Accept": "application/json",
		"Content-Type": "application/json",
	},
	credentials: "include",
	body: JSON.stringify("string"),
});

if (!response.ok) {
	throw new Error(`Request failed with status ${response.status}`);
}

const data = await response.json();
console.log(data);
```

```csharp
// Sign in first. __Host-portal_session 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 = """
"string"
""";

var request = new HttpRequestMessage(HttpMethod.Post, "https://depot.example.com/api/portal/v1/auth/mfa/totp");
request.Headers.TryAddWithoutValidation("X-Csrf-Token", "<portal-csrf>");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Cookie", "__Host-portal_session=<portal-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/portal/v1/auth/passkey/begin` {#depot.portalapi.passkeyBegin}

**passkeyBegin starts a ceremony: "login" (a discoverable sign-in, both factors at once), "mfa" (the second factor of a pending sign-in), "register" (add a passkey) or "reauth" (re-authenticate for sensitive pages).**

The browser gets flowId and the PublicKeyCredential options.

#### Request body

Required, sent as `application/json`.

The body is `any`.

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `200` | `application/json`, object | Success. |
| `400` | None | The request was refused. |

#### Request samples

```bash
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.
curl -X POST 'https://depot.example.com/api/portal/v1/auth/passkey/begin' \
  -H 'X-Csrf-Token: <portal-csrf>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -b '__Host-portal_session=<portal-session>' \
  --data '"string"'
```

```powershell
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

$headers = @{
    'X-Csrf-Token' = '<portal-csrf>'
    'Accept' = 'application/json'
    'Content-Type' = 'application/json'
    'Cookie' = '__Host-portal_session=<portal-session>'
}

$body = @'
"string"
'@

$response = Invoke-RestMethod `
    -Method Post `
    -Uri 'https://depot.example.com/api/portal/v1/auth/passkey/begin' `
    -Headers $headers `
    -ContentType 'application/json' `
    -Body $body

$response | ConvertTo-Json -Depth 10
```

```python
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

import requests

url = "https://depot.example.com/api/portal/v1/auth/passkey/begin"
headers = {
    "X-Csrf-Token": "<portal-csrf>",
    "Accept": "application/json",
    "Content-Type": "application/json",
}
cookies = {
    "__Host-portal_session": "<portal-session>",
}
payload = "string"

response = requests.post(url, headers=headers, cookies=cookies, json=payload, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// Sign in first. __Host-portal_session is a session cookie, so send it with every request.
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	body := []byte(`"string"`)

	req, err := http.NewRequest(http.MethodPost, "https://depot.example.com/api/portal/v1/auth/passkey/begin", bytes.NewReader(body))
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("X-Csrf-Token", "<portal-csrf>")
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	req.AddCookie(&http.Cookie{Name: "__Host-portal_session", Value: "<portal-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))
}
```

```ts
// Sign in first. __Host-portal_session 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/portal/v1/auth/passkey/begin";

const response = await fetch(url, {
	method: "POST",
	headers: {
		"X-Csrf-Token": "<portal-csrf>",
		"Accept": "application/json",
		"Content-Type": "application/json",
	},
	credentials: "include",
	body: JSON.stringify("string"),
});

if (!response.ok) {
	throw new Error(`Request failed with status ${response.status}`);
}

const data = await response.json();
console.log(data);
```

```csharp
// Sign in first. __Host-portal_session 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 = """
"string"
""";

var request = new HttpRequestMessage(HttpMethod.Post, "https://depot.example.com/api/portal/v1/auth/passkey/begin");
request.Headers.TryAddWithoutValidation("X-Csrf-Token", "<portal-csrf>");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Cookie", "__Host-portal_session=<portal-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/portal/v1/auth/passkey/finish` {#depot.portalapi.passkeyFinish}

**passkeyFinish completes a ceremony begun by passkeyBegin.**

The flow is spent whatever the outcome, and must finish on the host and (except a login) the session that began it.

#### Request body

Required, sent as `application/json`.

The body is `any`.

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `200` | `application/json`, Me | Success. |
| `400` | None | The request was refused. |

#### Request samples

```bash
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.
curl -X POST 'https://depot.example.com/api/portal/v1/auth/passkey/finish' \
  -H 'X-Csrf-Token: <portal-csrf>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -b '__Host-portal_session=<portal-session>' \
  --data '"string"'
```

```powershell
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

$headers = @{
    'X-Csrf-Token' = '<portal-csrf>'
    'Accept' = 'application/json'
    'Content-Type' = 'application/json'
    'Cookie' = '__Host-portal_session=<portal-session>'
}

$body = @'
"string"
'@

$response = Invoke-RestMethod `
    -Method Post `
    -Uri 'https://depot.example.com/api/portal/v1/auth/passkey/finish' `
    -Headers $headers `
    -ContentType 'application/json' `
    -Body $body

$response | ConvertTo-Json -Depth 10
```

```python
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

import requests

url = "https://depot.example.com/api/portal/v1/auth/passkey/finish"
headers = {
    "X-Csrf-Token": "<portal-csrf>",
    "Accept": "application/json",
    "Content-Type": "application/json",
}
cookies = {
    "__Host-portal_session": "<portal-session>",
}
payload = "string"

response = requests.post(url, headers=headers, cookies=cookies, json=payload, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// Sign in first. __Host-portal_session is a session cookie, so send it with every request.
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	body := []byte(`"string"`)

	req, err := http.NewRequest(http.MethodPost, "https://depot.example.com/api/portal/v1/auth/passkey/finish", bytes.NewReader(body))
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("X-Csrf-Token", "<portal-csrf>")
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	req.AddCookie(&http.Cookie{Name: "__Host-portal_session", Value: "<portal-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))
}
```

```ts
// Sign in first. __Host-portal_session 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/portal/v1/auth/passkey/finish";

const response = await fetch(url, {
	method: "POST",
	headers: {
		"X-Csrf-Token": "<portal-csrf>",
		"Accept": "application/json",
		"Content-Type": "application/json",
	},
	credentials: "include",
	body: JSON.stringify("string"),
});

if (!response.ok) {
	throw new Error(`Request failed with status ${response.status}`);
}

const data = await response.json();
console.log(data);
```

```csharp
// Sign in first. __Host-portal_session 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 = """
"string"
""";

var request = new HttpRequestMessage(HttpMethod.Post, "https://depot.example.com/api/portal/v1/auth/passkey/finish");
request.Headers.TryAddWithoutValidation("X-Csrf-Token", "<portal-csrf>");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Cookie", "__Host-portal_session=<portal-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/portal/v1/auth/password/forgot` {#depot.portalapi.passwordForgot}

**passwordForgot mails a reset link when the address has an active identity.**

It answers 204 whatever happened, and sends after answering, so neither the status nor the timing says whether the address is known.

#### Request body

Required, sent as `application/json`.

The body is `any`.

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `204` | None | Success, with no body. |
| `400` | `application/problem+json`, ProblemDetails | The request body is not acceptable. |

#### Request samples

```bash
# This operation is public. It takes no credentials.
curl -X POST 'https://depot.example.com/api/portal/v1/auth/password/forgot' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  --data '"string"'
```

```powershell
# This operation is public. It takes no credentials.

$headers = @{
    'Accept' = 'application/json'
    'Content-Type' = 'application/json'
}

$body = @'
"string"
'@

$response = Invoke-RestMethod `
    -Method Post `
    -Uri 'https://depot.example.com/api/portal/v1/auth/password/forgot' `
    -Headers $headers `
    -ContentType 'application/json' `
    -Body $body

$response | ConvertTo-Json -Depth 10
```

```python
# This operation is public. It takes no credentials.

import requests

url = "https://depot.example.com/api/portal/v1/auth/password/forgot"
headers = {
    "Accept": "application/json",
    "Content-Type": "application/json",
}
payload = "string"

response = requests.post(url, headers=headers, json=payload, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// This operation is public. It takes no credentials.
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	body := []byte(`"string"`)

	req, err := http.NewRequest(http.MethodPost, "https://depot.example.com/api/portal/v1/auth/password/forgot", bytes.NewReader(body))
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("Accept", "application/json")
	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))
}
```

```ts
// This operation is public. It takes no credentials.

const url = "https://depot.example.com/api/portal/v1/auth/password/forgot";

const response = await fetch(url, {
	method: "POST",
	headers: {
		"Accept": "application/json",
		"Content-Type": "application/json",
	},
	body: JSON.stringify("string"),
});

if (!response.ok) {
	throw new Error(`Request failed with status ${response.status}`);
}

const data = await response.json();
console.log(data);
```

```csharp
// 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 = """
"string"
""";

var request = new HttpRequestMessage(HttpMethod.Post, "https://depot.example.com/api/portal/v1/auth/password/forgot");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
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/portal/v1/auth/password/reset` {#depot.portalapi.passwordReset}

**passwordReset sets a new password from an emailed link.**

The link is spent once; a password the policy refuses comes back with a retryToken (a fresh link with the time the old one had left) so the person can try another without asking for a new email. A reset signs every session out and clears the lockout; it does not sign in, because the second factor is still owed.

#### Request body

Required, sent as `application/json`.

The body is `any`.

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `204` | None | Success, with no body. |
| `400` | None | The request was refused. |

#### Request samples

```bash
# This operation is public. It takes no credentials.
curl -X POST 'https://depot.example.com/api/portal/v1/auth/password/reset' \
  -H 'Content-Type: application/json' \
  --data '"string"'
```

```powershell
# This operation is public. It takes no credentials.

$headers = @{
    'Content-Type' = 'application/json'
}

$body = @'
"string"
'@

$response = Invoke-RestMethod `
    -Method Post `
    -Uri 'https://depot.example.com/api/portal/v1/auth/password/reset' `
    -Headers $headers `
    -ContentType 'application/json' `
    -Body $body

$response | ConvertTo-Json -Depth 10
```

```python
# This operation is public. It takes no credentials.

import requests

url = "https://depot.example.com/api/portal/v1/auth/password/reset"
headers = {
    "Content-Type": "application/json",
}
payload = "string"

response = requests.post(url, headers=headers, json=payload, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// This operation is public. It takes no credentials.
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	body := []byte(`"string"`)

	req, err := http.NewRequest(http.MethodPost, "https://depot.example.com/api/portal/v1/auth/password/reset", 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))
}
```

```ts
// This operation is public. It takes no credentials.

const url = "https://depot.example.com/api/portal/v1/auth/password/reset";

const response = await fetch(url, {
	method: "POST",
	headers: {
		"Content-Type": "application/json",
	},
	body: JSON.stringify("string"),
});

if (!response.ok) {
	throw new Error(`Request failed with status ${response.status}`);
}

const data = await response.json();
console.log(data);
```

```csharp
// 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 = """
"string"
""";

var request = new HttpRequestMessage(HttpMethod.Post, "https://depot.example.com/api/portal/v1/auth/password/reset");
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/portal/v1/auth/reauth` {#depot.portalapi.reauth}

**reauth re-authenticates the signed-in session for sensitive pages: the password (when the identity has one) plus a TOTP or recovery code.**

A passkey re-authenticates through /auth/passkey with purpose "reauth", and a session whose MFA came from the IdP through /auth/sso/discover with reauth true.

#### Request body

Required, sent as `application/json`.

The body is `any`.

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `204` | None | Success, with no body. |
| `400` | `application/problem+json`, ProblemDetails | The request body is not acceptable. |

#### Request samples

```bash
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.
curl -X POST 'https://depot.example.com/api/portal/v1/auth/reauth' \
  -H 'X-Csrf-Token: <portal-csrf>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -b '__Host-portal_session=<portal-session>' \
  --data '"string"'
```

```powershell
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

$headers = @{
    'X-Csrf-Token' = '<portal-csrf>'
    'Accept' = 'application/json'
    'Content-Type' = 'application/json'
    'Cookie' = '__Host-portal_session=<portal-session>'
}

$body = @'
"string"
'@

$response = Invoke-RestMethod `
    -Method Post `
    -Uri 'https://depot.example.com/api/portal/v1/auth/reauth' `
    -Headers $headers `
    -ContentType 'application/json' `
    -Body $body

$response | ConvertTo-Json -Depth 10
```

```python
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

import requests

url = "https://depot.example.com/api/portal/v1/auth/reauth"
headers = {
    "X-Csrf-Token": "<portal-csrf>",
    "Accept": "application/json",
    "Content-Type": "application/json",
}
cookies = {
    "__Host-portal_session": "<portal-session>",
}
payload = "string"

response = requests.post(url, headers=headers, cookies=cookies, json=payload, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// Sign in first. __Host-portal_session is a session cookie, so send it with every request.
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	body := []byte(`"string"`)

	req, err := http.NewRequest(http.MethodPost, "https://depot.example.com/api/portal/v1/auth/reauth", bytes.NewReader(body))
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("X-Csrf-Token", "<portal-csrf>")
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	req.AddCookie(&http.Cookie{Name: "__Host-portal_session", Value: "<portal-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))
}
```

```ts
// Sign in first. __Host-portal_session 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/portal/v1/auth/reauth";

const response = await fetch(url, {
	method: "POST",
	headers: {
		"X-Csrf-Token": "<portal-csrf>",
		"Accept": "application/json",
		"Content-Type": "application/json",
	},
	credentials: "include",
	body: JSON.stringify("string"),
});

if (!response.ok) {
	throw new Error(`Request failed with status ${response.status}`);
}

const data = await response.json();
console.log(data);
```

```csharp
// Sign in first. __Host-portal_session 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 = """
"string"
""";

var request = new HttpRequestMessage(HttpMethod.Post, "https://depot.example.com/api/portal/v1/auth/reauth");
request.Headers.TryAddWithoutValidation("X-Csrf-Token", "<portal-csrf>");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Cookie", "__Host-portal_session=<portal-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/portal/v1/auth/sso/broker` {#depot.portalapi.ssoBroker}

**ssoBroker is the broker's landing: Core form-posts the signed assertion from a cross-site page, which the SameSite=None flow cookie rides.**

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `assertion` | query | string | No |  |
| `error` | query | string | No |  |
| `flow` | query | string | No |  |

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `200` | None | Success. The body shape was not resolved; see x-outpost-unresolved. |

#### Request samples

```bash
# This operation is public. It takes no credentials.
curl -X POST 'https://depot.example.com/api/portal/v1/auth/sso/broker?assertion=<assertion>&error=<error>&flow=<flow>'
```

```powershell
# This operation is public. It takes no credentials.

$response = Invoke-RestMethod `
    -Method Post `
    -Uri 'https://depot.example.com/api/portal/v1/auth/sso/broker?assertion=<assertion>&error=<error>&flow=<flow>'

$response | ConvertTo-Json -Depth 10
```

```python
# This operation is public. It takes no credentials.

import requests

url = "https://depot.example.com/api/portal/v1/auth/sso/broker"
params = {
    "assertion": "<assertion>",
    "error": "<error>",
    "flow": "<flow>",
}

response = requests.post(url, params=params, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// This operation is public. It takes no credentials.
package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	req, err := http.NewRequest(http.MethodPost, "https://depot.example.com/api/portal/v1/auth/sso/broker?assertion=<assertion>&error=<error>&flow=<flow>", nil)
	if err != nil {
		log.Fatal(err)
	}

	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))
}
```

```ts
// This operation is public. It takes no credentials.

const url = new URL("https://depot.example.com/api/portal/v1/auth/sso/broker");
url.searchParams.set("assertion", "<assertion>");
url.searchParams.set("error", "<error>");
url.searchParams.set("flow", "<flow>");

const response = await fetch(url, {
	method: "POST",
});

if (!response.ok) {
	throw new Error(`Request failed with status ${response.status}`);
}

const data = await response.json();
console.log(data);
```

```csharp
// This operation is public. It takes no credentials.

using System;
using System.Net.Http;

using var client = new HttpClient();

var request = new HttpRequestMessage(HttpMethod.Post, "https://depot.example.com/api/portal/v1/auth/sso/broker?assertion=<assertion>&error=<error>&flow=<flow>");

var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

### GET `/api/portal/v1/auth/sso/callback` {#depot.portalapi.ssoCallback}

**ssoCallback is the BYO OIDC callback.**

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `code` | query | string | No |  |
| `error` | query | string | No |  |
| `state` | query | string | No |  |

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `200` | None | Success. The body shape was not resolved; see x-outpost-unresolved. |

#### Request samples

```bash
# This operation is public. It takes no credentials.
# This operation is idempotent. Repeating it does not repeat its effect.
curl -X GET 'https://depot.example.com/api/portal/v1/auth/sso/callback?code=<code>&error=<error>&state=<state>'
```

```powershell
# This operation is public. It takes no credentials.
# This operation is idempotent. Repeating it does not repeat its effect.

$response = Invoke-RestMethod `
    -Method Get `
    -Uri 'https://depot.example.com/api/portal/v1/auth/sso/callback?code=<code>&error=<error>&state=<state>'

$response | ConvertTo-Json -Depth 10
```

```python
# This operation is public. It takes no credentials.
# This operation is idempotent. Repeating it does not repeat its effect.

import requests

url = "https://depot.example.com/api/portal/v1/auth/sso/callback"
params = {
    "code": "<code>",
    "error": "<error>",
    "state": "<state>",
}

response = requests.get(url, params=params, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// This operation is public. It takes no credentials.
// 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/portal/v1/auth/sso/callback?code=<code>&error=<error>&state=<state>", nil)
	if err != nil {
		log.Fatal(err)
	}

	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))
}
```

```ts
// This operation is public. It takes no credentials.
// This operation is idempotent. Repeating it does not repeat its effect.

const url = new URL("https://depot.example.com/api/portal/v1/auth/sso/callback");
url.searchParams.set("code", "<code>");
url.searchParams.set("error", "<error>");
url.searchParams.set("state", "<state>");

const response = await fetch(url, {
	method: "GET",
});

if (!response.ok) {
	throw new Error(`Request failed with status ${response.status}`);
}

const data = await response.json();
console.log(data);
```

```csharp
// This operation is public. It takes no credentials.
// 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/portal/v1/auth/sso/callback?code=<code>&error=<error>&state=<state>");

var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

### POST `/api/portal/v1/auth/sso/discover` {#depot.portalapi.ssoDiscover}

**ssoDiscover is home-realm discovery: where an address signs in, as a URL for the browser to go to.**

404 no_sso means "use a password".

#### Request body

Required, sent as `application/json`.

The body is `any`.

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `200` | `application/json`, object | Success. |
| `400` | `application/problem+json`, ProblemDetails | The request body is not acceptable. |

#### Request samples

```bash
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.
curl -X POST 'https://depot.example.com/api/portal/v1/auth/sso/discover' \
  -H 'X-Csrf-Token: <portal-csrf>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -b '__Host-portal_session=<portal-session>' \
  --data '"string"'
```

```powershell
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

$headers = @{
    'X-Csrf-Token' = '<portal-csrf>'
    'Accept' = 'application/json'
    'Content-Type' = 'application/json'
    'Cookie' = '__Host-portal_session=<portal-session>'
}

$body = @'
"string"
'@

$response = Invoke-RestMethod `
    -Method Post `
    -Uri 'https://depot.example.com/api/portal/v1/auth/sso/discover' `
    -Headers $headers `
    -ContentType 'application/json' `
    -Body $body

$response | ConvertTo-Json -Depth 10
```

```python
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

import requests

url = "https://depot.example.com/api/portal/v1/auth/sso/discover"
headers = {
    "X-Csrf-Token": "<portal-csrf>",
    "Accept": "application/json",
    "Content-Type": "application/json",
}
cookies = {
    "__Host-portal_session": "<portal-session>",
}
payload = "string"

response = requests.post(url, headers=headers, cookies=cookies, json=payload, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// Sign in first. __Host-portal_session is a session cookie, so send it with every request.
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	body := []byte(`"string"`)

	req, err := http.NewRequest(http.MethodPost, "https://depot.example.com/api/portal/v1/auth/sso/discover", bytes.NewReader(body))
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("X-Csrf-Token", "<portal-csrf>")
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	req.AddCookie(&http.Cookie{Name: "__Host-portal_session", Value: "<portal-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))
}
```

```ts
// Sign in first. __Host-portal_session 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/portal/v1/auth/sso/discover";

const response = await fetch(url, {
	method: "POST",
	headers: {
		"X-Csrf-Token": "<portal-csrf>",
		"Accept": "application/json",
		"Content-Type": "application/json",
	},
	credentials: "include",
	body: JSON.stringify("string"),
});

if (!response.ok) {
	throw new Error(`Request failed with status ${response.status}`);
}

const data = await response.json();
console.log(data);
```

```csharp
// Sign in first. __Host-portal_session 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 = """
"string"
""";

var request = new HttpRequestMessage(HttpMethod.Post, "https://depot.example.com/api/portal/v1/auth/sso/discover");
request.Headers.TryAddWithoutValidation("X-Csrf-Token", "<portal-csrf>");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Cookie", "__Host-portal_session=<portal-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/portal/v1/auth/teams` {#depot.portalapi.teamsLogin}

**teamsLogin exchanges a Teams SSO token for a bearer session.**

#### Request body

Required, sent as `application/json`.

The body is `any`.

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `200` | `application/json`, object | Success. |
| `400` | `application/problem+json`, ProblemDetails | The request body is not acceptable. |

#### Request samples

```bash
# This operation is public. It takes no credentials.
curl -X POST 'https://depot.example.com/api/portal/v1/auth/teams' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  --data '"string"'
```

```powershell
# This operation is public. It takes no credentials.

$headers = @{
    'Accept' = 'application/json'
    'Content-Type' = 'application/json'
}

$body = @'
"string"
'@

$response = Invoke-RestMethod `
    -Method Post `
    -Uri 'https://depot.example.com/api/portal/v1/auth/teams' `
    -Headers $headers `
    -ContentType 'application/json' `
    -Body $body

$response | ConvertTo-Json -Depth 10
```

```python
# This operation is public. It takes no credentials.

import requests

url = "https://depot.example.com/api/portal/v1/auth/teams"
headers = {
    "Accept": "application/json",
    "Content-Type": "application/json",
}
payload = "string"

response = requests.post(url, headers=headers, json=payload, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// This operation is public. It takes no credentials.
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	body := []byte(`"string"`)

	req, err := http.NewRequest(http.MethodPost, "https://depot.example.com/api/portal/v1/auth/teams", bytes.NewReader(body))
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("Accept", "application/json")
	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))
}
```

```ts
// This operation is public. It takes no credentials.

const url = "https://depot.example.com/api/portal/v1/auth/teams";

const response = await fetch(url, {
	method: "POST",
	headers: {
		"Accept": "application/json",
		"Content-Type": "application/json",
	},
	body: JSON.stringify("string"),
});

if (!response.ok) {
	throw new Error(`Request failed with status ${response.status}`);
}

const data = await response.json();
console.log(data);
```

```csharp
// 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 = """
"string"
""";

var request = new HttpRequestMessage(HttpMethod.Post, "https://depot.example.com/api/portal/v1/auth/teams");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
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/portal/v1/auth/teams/flow` {#depot.portalapi.teamsFlow}

**teamsFlow is broker mode's hand-off (ruling R3): the authenticate() popup, signed in normally with a cookie session, mints a single-use teams flow and ends at /portal/teams/auth-end?flow=`&lt;id>`; the tab, which has no cookies, exchanges that id at POST /auth/teams for its bearer.**

#### Request body

Required, sent as `application/json`.

The body is `any`.

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `200` | `application/json`, object | Success. |
| `400` | `application/problem+json`, ProblemDetails | The request body is not acceptable. |

#### Request samples

```bash
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.
curl -X POST 'https://depot.example.com/api/portal/v1/auth/teams/flow' \
  -H 'X-Csrf-Token: <portal-csrf>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -b '__Host-portal_session=<portal-session>' \
  --data '"string"'
```

```powershell
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

$headers = @{
    'X-Csrf-Token' = '<portal-csrf>'
    'Accept' = 'application/json'
    'Content-Type' = 'application/json'
    'Cookie' = '__Host-portal_session=<portal-session>'
}

$body = @'
"string"
'@

$response = Invoke-RestMethod `
    -Method Post `
    -Uri 'https://depot.example.com/api/portal/v1/auth/teams/flow' `
    -Headers $headers `
    -ContentType 'application/json' `
    -Body $body

$response | ConvertTo-Json -Depth 10
```

```python
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

import requests

url = "https://depot.example.com/api/portal/v1/auth/teams/flow"
headers = {
    "X-Csrf-Token": "<portal-csrf>",
    "Accept": "application/json",
    "Content-Type": "application/json",
}
cookies = {
    "__Host-portal_session": "<portal-session>",
}
payload = "string"

response = requests.post(url, headers=headers, cookies=cookies, json=payload, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// Sign in first. __Host-portal_session is a session cookie, so send it with every request.
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	body := []byte(`"string"`)

	req, err := http.NewRequest(http.MethodPost, "https://depot.example.com/api/portal/v1/auth/teams/flow", bytes.NewReader(body))
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("X-Csrf-Token", "<portal-csrf>")
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	req.AddCookie(&http.Cookie{Name: "__Host-portal_session", Value: "<portal-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))
}
```

```ts
// Sign in first. __Host-portal_session 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/portal/v1/auth/teams/flow";

const response = await fetch(url, {
	method: "POST",
	headers: {
		"X-Csrf-Token": "<portal-csrf>",
		"Accept": "application/json",
		"Content-Type": "application/json",
	},
	credentials: "include",
	body: JSON.stringify("string"),
});

if (!response.ok) {
	throw new Error(`Request failed with status ${response.status}`);
}

const data = await response.json();
console.log(data);
```

```csharp
// Sign in first. __Host-portal_session 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 = """
"string"
""";

var request = new HttpRequestMessage(HttpMethod.Post, "https://depot.example.com/api/portal/v1/auth/teams/flow");
request.Headers.TryAddWithoutValidation("X-Csrf-Token", "<portal-csrf>");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Cookie", "__Host-portal_session=<portal-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/portal/v1/me` {#depot.portalapi.me}

**me reports the signed-in identity.**

A pending session gets it too, with mfaRequired true, so the sign-in page knows which factor to ask for.

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `200` | `application/json`, Me | Success. |

#### Request samples

```bash
# Sign in first. __Host-portal_session 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/portal/v1/me' \
  -H 'X-Csrf-Token: <portal-csrf>' \
  -H 'Accept: application/json' \
  -b '__Host-portal_session=<portal-session>'
```

```powershell
# Sign in first. __Host-portal_session 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' = '<portal-csrf>'
    'Accept' = 'application/json'
    'Cookie' = '__Host-portal_session=<portal-session>'
}

$response = Invoke-RestMethod `
    -Method Get `
    -Uri 'https://depot.example.com/api/portal/v1/me' `
    -Headers $headers

$response | ConvertTo-Json -Depth 10
```

```python
# Sign in first. __Host-portal_session 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/portal/v1/me"
headers = {
    "X-Csrf-Token": "<portal-csrf>",
    "Accept": "application/json",
}
cookies = {
    "__Host-portal_session": "<portal-session>",
}

response = requests.get(url, headers=headers, cookies=cookies, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// Sign in first. __Host-portal_session 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/portal/v1/me", nil)
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("X-Csrf-Token", "<portal-csrf>")
	req.Header.Set("Accept", "application/json")
	req.AddCookie(&http.Cookie{Name: "__Host-portal_session", Value: "<portal-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))
}
```

```ts
// Sign in first. __Host-portal_session 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/portal/v1/me";

const response = await fetch(url, {
	method: "GET",
	headers: {
		"X-Csrf-Token": "<portal-csrf>",
		"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);
```

```csharp
// Sign in first. __Host-portal_session 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/portal/v1/me");
request.Headers.TryAddWithoutValidation("X-Csrf-Token", "<portal-csrf>");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Cookie", "__Host-portal_session=<portal-session>");

var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

### PATCH `/api/portal/v1/me` {#depot.portalapi.updateMe}

**updateMe changes the caller's own name, locale or timezone.**

#### Request body

Required, sent as `application/json`.

The body is `any`.

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `200` | `application/json`, Me | Success. |
| `400` | None | The request was refused. |

#### Request samples

```bash
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.
curl -X PATCH 'https://depot.example.com/api/portal/v1/me' \
  -H 'X-Csrf-Token: <portal-csrf>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -b '__Host-portal_session=<portal-session>' \
  --data '"string"'
```

```powershell
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

$headers = @{
    'X-Csrf-Token' = '<portal-csrf>'
    'Accept' = 'application/json'
    'Content-Type' = 'application/json'
    'Cookie' = '__Host-portal_session=<portal-session>'
}

$body = @'
"string"
'@

$response = Invoke-RestMethod `
    -Method Patch `
    -Uri 'https://depot.example.com/api/portal/v1/me' `
    -Headers $headers `
    -ContentType 'application/json' `
    -Body $body

$response | ConvertTo-Json -Depth 10
```

```python
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

import requests

url = "https://depot.example.com/api/portal/v1/me"
headers = {
    "X-Csrf-Token": "<portal-csrf>",
    "Accept": "application/json",
    "Content-Type": "application/json",
}
cookies = {
    "__Host-portal_session": "<portal-session>",
}
payload = "string"

response = requests.patch(url, headers=headers, cookies=cookies, json=payload, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// Sign in first. __Host-portal_session is a session cookie, so send it with every request.
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	body := []byte(`"string"`)

	req, err := http.NewRequest(http.MethodPatch, "https://depot.example.com/api/portal/v1/me", bytes.NewReader(body))
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("X-Csrf-Token", "<portal-csrf>")
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	req.AddCookie(&http.Cookie{Name: "__Host-portal_session", Value: "<portal-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))
}
```

```ts
// Sign in first. __Host-portal_session 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/portal/v1/me";

const response = await fetch(url, {
	method: "PATCH",
	headers: {
		"X-Csrf-Token": "<portal-csrf>",
		"Accept": "application/json",
		"Content-Type": "application/json",
	},
	credentials: "include",
	body: JSON.stringify("string"),
});

if (!response.ok) {
	throw new Error(`Request failed with status ${response.status}`);
}

const data = await response.json();
console.log(data);
```

```csharp
// Sign in first. __Host-portal_session 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 = """
"string"
""";

var request = new HttpRequestMessage(HttpMethod.Patch, "https://depot.example.com/api/portal/v1/me");
request.Headers.TryAddWithoutValidation("X-Csrf-Token", "<portal-csrf>");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Cookie", "__Host-portal_session=<portal-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/portal/v1/me/invites` {#depot.portalapi.myInvites}

**myInvites lists the invitations addressed to the signed-in identity's own address, with the organization, the roles it would hold and who invited.**

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `200` | `application/json`, array of MyInvite | Success. |

#### Request samples

```bash
# Sign in first. __Host-portal_session 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/portal/v1/me/invites' \
  -H 'X-Csrf-Token: <portal-csrf>' \
  -H 'Accept: application/json' \
  -b '__Host-portal_session=<portal-session>'
```

```powershell
# Sign in first. __Host-portal_session 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' = '<portal-csrf>'
    'Accept' = 'application/json'
    'Cookie' = '__Host-portal_session=<portal-session>'
}

$response = Invoke-RestMethod `
    -Method Get `
    -Uri 'https://depot.example.com/api/portal/v1/me/invites' `
    -Headers $headers

$response | ConvertTo-Json -Depth 10
```

```python
# Sign in first. __Host-portal_session 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/portal/v1/me/invites"
headers = {
    "X-Csrf-Token": "<portal-csrf>",
    "Accept": "application/json",
}
cookies = {
    "__Host-portal_session": "<portal-session>",
}

response = requests.get(url, headers=headers, cookies=cookies, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// Sign in first. __Host-portal_session 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/portal/v1/me/invites", nil)
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("X-Csrf-Token", "<portal-csrf>")
	req.Header.Set("Accept", "application/json")
	req.AddCookie(&http.Cookie{Name: "__Host-portal_session", Value: "<portal-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))
}
```

```ts
// Sign in first. __Host-portal_session 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/portal/v1/me/invites";

const response = await fetch(url, {
	method: "GET",
	headers: {
		"X-Csrf-Token": "<portal-csrf>",
		"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);
```

```csharp
// Sign in first. __Host-portal_session 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/portal/v1/me/invites");
request.Headers.TryAddWithoutValidation("X-Csrf-Token", "<portal-csrf>");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Cookie", "__Host-portal_session=<portal-session>");

var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

### POST `/api/portal/v1/me/invites/{inviteID}/accept` {#depot.portalapi.acceptMyInvite}

**acceptMyInvite accepts an invitation to the signed-in identity's own address: the identity proved itself at sign-in, so this links it to the organization with no token and no password (the safe path F1 points existing identities to).**

Audited in the organization's chain.

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `inviteID` | path | string | Yes |  |

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `200` | `application/json`, OrgSummary | Success. |
| `404` | `application/problem+json`, ProblemDetails | No resource matches that id. |

#### Request samples

```bash
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.
curl -X POST 'https://depot.example.com/api/portal/v1/me/invites/<inviteID>/accept' \
  -H 'X-Csrf-Token: <portal-csrf>' \
  -H 'Accept: application/json' \
  -b '__Host-portal_session=<portal-session>'
```

```powershell
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

$headers = @{
    'X-Csrf-Token' = '<portal-csrf>'
    'Accept' = 'application/json'
    'Cookie' = '__Host-portal_session=<portal-session>'
}

$response = Invoke-RestMethod `
    -Method Post `
    -Uri 'https://depot.example.com/api/portal/v1/me/invites/<inviteID>/accept' `
    -Headers $headers

$response | ConvertTo-Json -Depth 10
```

```python
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

import requests

url = "https://depot.example.com/api/portal/v1/me/invites/<inviteID>/accept"
headers = {
    "X-Csrf-Token": "<portal-csrf>",
    "Accept": "application/json",
}
cookies = {
    "__Host-portal_session": "<portal-session>",
}

response = requests.post(url, headers=headers, cookies=cookies, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// Sign in first. __Host-portal_session 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/portal/v1/me/invites/<inviteID>/accept", nil)
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("X-Csrf-Token", "<portal-csrf>")
	req.Header.Set("Accept", "application/json")
	req.AddCookie(&http.Cookie{Name: "__Host-portal_session", Value: "<portal-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))
}
```

```ts
// Sign in first. __Host-portal_session 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/portal/v1/me/invites/<inviteID>/accept";

const response = await fetch(url, {
	method: "POST",
	headers: {
		"X-Csrf-Token": "<portal-csrf>",
		"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);
```

```csharp
// Sign in first. __Host-portal_session 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/portal/v1/me/invites/<inviteID>/accept");
request.Headers.TryAddWithoutValidation("X-Csrf-Token", "<portal-csrf>");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Cookie", "__Host-portal_session=<portal-session>");

var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

### POST `/api/portal/v1/me/mfa/recovery-codes` {#depot.portalapi.recoveryRegenerate}

**recoveryRegenerate replaces the recovery codes.**

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `200` | `application/json`, object | Success. |

#### Request samples

```bash
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.
curl -X POST 'https://depot.example.com/api/portal/v1/me/mfa/recovery-codes' \
  -H 'X-Csrf-Token: <portal-csrf>' \
  -H 'Accept: application/json' \
  -b '__Host-portal_session=<portal-session>'
```

```powershell
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

$headers = @{
    'X-Csrf-Token' = '<portal-csrf>'
    'Accept' = 'application/json'
    'Cookie' = '__Host-portal_session=<portal-session>'
}

$response = Invoke-RestMethod `
    -Method Post `
    -Uri 'https://depot.example.com/api/portal/v1/me/mfa/recovery-codes' `
    -Headers $headers

$response | ConvertTo-Json -Depth 10
```

```python
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

import requests

url = "https://depot.example.com/api/portal/v1/me/mfa/recovery-codes"
headers = {
    "X-Csrf-Token": "<portal-csrf>",
    "Accept": "application/json",
}
cookies = {
    "__Host-portal_session": "<portal-session>",
}

response = requests.post(url, headers=headers, cookies=cookies, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// Sign in first. __Host-portal_session 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/portal/v1/me/mfa/recovery-codes", nil)
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("X-Csrf-Token", "<portal-csrf>")
	req.Header.Set("Accept", "application/json")
	req.AddCookie(&http.Cookie{Name: "__Host-portal_session", Value: "<portal-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))
}
```

```ts
// Sign in first. __Host-portal_session 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/portal/v1/me/mfa/recovery-codes";

const response = await fetch(url, {
	method: "POST",
	headers: {
		"X-Csrf-Token": "<portal-csrf>",
		"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);
```

```csharp
// Sign in first. __Host-portal_session 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/portal/v1/me/mfa/recovery-codes");
request.Headers.TryAddWithoutValidation("X-Csrf-Token", "<portal-csrf>");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Cookie", "__Host-portal_session=<portal-session>");

var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

### GET `/api/portal/v1/me/mfa/totp` {#depot.portalapi.totpEnrol}

**totpEnrol starts TOTP enrolment: a new secret and its otpauth URL.**

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `200` | `application/json`, object | Success. |

#### Request samples

```bash
# Sign in first. __Host-portal_session 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/portal/v1/me/mfa/totp' \
  -H 'X-Csrf-Token: <portal-csrf>' \
  -H 'Accept: application/json' \
  -b '__Host-portal_session=<portal-session>'
```

```powershell
# Sign in first. __Host-portal_session 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' = '<portal-csrf>'
    'Accept' = 'application/json'
    'Cookie' = '__Host-portal_session=<portal-session>'
}

$response = Invoke-RestMethod `
    -Method Get `
    -Uri 'https://depot.example.com/api/portal/v1/me/mfa/totp' `
    -Headers $headers

$response | ConvertTo-Json -Depth 10
```

```python
# Sign in first. __Host-portal_session 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/portal/v1/me/mfa/totp"
headers = {
    "X-Csrf-Token": "<portal-csrf>",
    "Accept": "application/json",
}
cookies = {
    "__Host-portal_session": "<portal-session>",
}

response = requests.get(url, headers=headers, cookies=cookies, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// Sign in first. __Host-portal_session 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/portal/v1/me/mfa/totp", nil)
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("X-Csrf-Token", "<portal-csrf>")
	req.Header.Set("Accept", "application/json")
	req.AddCookie(&http.Cookie{Name: "__Host-portal_session", Value: "<portal-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))
}
```

```ts
// Sign in first. __Host-portal_session 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/portal/v1/me/mfa/totp";

const response = await fetch(url, {
	method: "GET",
	headers: {
		"X-Csrf-Token": "<portal-csrf>",
		"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);
```

```csharp
// Sign in first. __Host-portal_session 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/portal/v1/me/mfa/totp");
request.Headers.TryAddWithoutValidation("X-Csrf-Token", "<portal-csrf>");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Cookie", "__Host-portal_session=<portal-session>");

var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

### POST `/api/portal/v1/me/mfa/totp` {#depot.portalapi.totpConfirm}

**totpConfirm confirms enrolment with a first code and returns recovery codes.**

On a pending session it also completes the sign-in.

#### Request body

Required, sent as `application/json`.

The body is `any`.

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `200` | `application/json`, object | Success. |
| `400` | `application/problem+json`, ProblemDetails | The request body is not acceptable. |

#### Request samples

```bash
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.
curl -X POST 'https://depot.example.com/api/portal/v1/me/mfa/totp' \
  -H 'X-Csrf-Token: <portal-csrf>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -b '__Host-portal_session=<portal-session>' \
  --data '"string"'
```

```powershell
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

$headers = @{
    'X-Csrf-Token' = '<portal-csrf>'
    'Accept' = 'application/json'
    'Content-Type' = 'application/json'
    'Cookie' = '__Host-portal_session=<portal-session>'
}

$body = @'
"string"
'@

$response = Invoke-RestMethod `
    -Method Post `
    -Uri 'https://depot.example.com/api/portal/v1/me/mfa/totp' `
    -Headers $headers `
    -ContentType 'application/json' `
    -Body $body

$response | ConvertTo-Json -Depth 10
```

```python
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

import requests

url = "https://depot.example.com/api/portal/v1/me/mfa/totp"
headers = {
    "X-Csrf-Token": "<portal-csrf>",
    "Accept": "application/json",
    "Content-Type": "application/json",
}
cookies = {
    "__Host-portal_session": "<portal-session>",
}
payload = "string"

response = requests.post(url, headers=headers, cookies=cookies, json=payload, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// Sign in first. __Host-portal_session is a session cookie, so send it with every request.
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	body := []byte(`"string"`)

	req, err := http.NewRequest(http.MethodPost, "https://depot.example.com/api/portal/v1/me/mfa/totp", bytes.NewReader(body))
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("X-Csrf-Token", "<portal-csrf>")
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	req.AddCookie(&http.Cookie{Name: "__Host-portal_session", Value: "<portal-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))
}
```

```ts
// Sign in first. __Host-portal_session 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/portal/v1/me/mfa/totp";

const response = await fetch(url, {
	method: "POST",
	headers: {
		"X-Csrf-Token": "<portal-csrf>",
		"Accept": "application/json",
		"Content-Type": "application/json",
	},
	credentials: "include",
	body: JSON.stringify("string"),
});

if (!response.ok) {
	throw new Error(`Request failed with status ${response.status}`);
}

const data = await response.json();
console.log(data);
```

```csharp
// Sign in first. __Host-portal_session 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 = """
"string"
""";

var request = new HttpRequestMessage(HttpMethod.Post, "https://depot.example.com/api/portal/v1/me/mfa/totp");
request.Headers.TryAddWithoutValidation("X-Csrf-Token", "<portal-csrf>");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Cookie", "__Host-portal_session=<portal-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/portal/v1/me/mfa/totp` {#depot.portalapi.totpRemove}

**totpRemove turns TOTP off and spends the recovery codes with it.**

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `204` | None | Success, with no body. |

#### Request samples

```bash
# Sign in first. __Host-portal_session 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/portal/v1/me/mfa/totp' \
  -H 'X-Csrf-Token: <portal-csrf>' \
  -b '__Host-portal_session=<portal-session>'
```

```powershell
# Sign in first. __Host-portal_session 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' = '<portal-csrf>'
    'Cookie' = '__Host-portal_session=<portal-session>'
}

$response = Invoke-RestMethod `
    -Method Delete `
    -Uri 'https://depot.example.com/api/portal/v1/me/mfa/totp' `
    -Headers $headers

$response | ConvertTo-Json -Depth 10
```

```python
# Sign in first. __Host-portal_session 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/portal/v1/me/mfa/totp"
headers = {
    "X-Csrf-Token": "<portal-csrf>",
}
cookies = {
    "__Host-portal_session": "<portal-session>",
}

response = requests.delete(url, headers=headers, cookies=cookies, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// Sign in first. __Host-portal_session 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/portal/v1/me/mfa/totp", nil)
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("X-Csrf-Token", "<portal-csrf>")
	req.AddCookie(&http.Cookie{Name: "__Host-portal_session", Value: "<portal-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))
}
```

```ts
// Sign in first. __Host-portal_session 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/portal/v1/me/mfa/totp";

const response = await fetch(url, {
	method: "DELETE",
	headers: {
		"X-Csrf-Token": "<portal-csrf>",
	},
	credentials: "include",
});

if (!response.ok) {
	throw new Error(`Request failed with status ${response.status}`);
}

const data = await response.json();
console.log(data);
```

```csharp
// Sign in first. __Host-portal_session 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/portal/v1/me/mfa/totp");
request.Headers.TryAddWithoutValidation("X-Csrf-Token", "<portal-csrf>");
request.Headers.TryAddWithoutValidation("Cookie", "__Host-portal_session=<portal-session>");

var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

### GET `/api/portal/v1/me/passkeys` {#depot.portalapi.passkeyList}

**passkeyList lists the caller's passkeys on every address.**

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `200` | `application/json`, array of Passkey | Success. |

#### Request samples

```bash
# Sign in first. __Host-portal_session 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/portal/v1/me/passkeys' \
  -H 'X-Csrf-Token: <portal-csrf>' \
  -H 'Accept: application/json' \
  -b '__Host-portal_session=<portal-session>'
```

```powershell
# Sign in first. __Host-portal_session 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' = '<portal-csrf>'
    'Accept' = 'application/json'
    'Cookie' = '__Host-portal_session=<portal-session>'
}

$response = Invoke-RestMethod `
    -Method Get `
    -Uri 'https://depot.example.com/api/portal/v1/me/passkeys' `
    -Headers $headers

$response | ConvertTo-Json -Depth 10
```

```python
# Sign in first. __Host-portal_session 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/portal/v1/me/passkeys"
headers = {
    "X-Csrf-Token": "<portal-csrf>",
    "Accept": "application/json",
}
cookies = {
    "__Host-portal_session": "<portal-session>",
}

response = requests.get(url, headers=headers, cookies=cookies, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// Sign in first. __Host-portal_session 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/portal/v1/me/passkeys", nil)
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("X-Csrf-Token", "<portal-csrf>")
	req.Header.Set("Accept", "application/json")
	req.AddCookie(&http.Cookie{Name: "__Host-portal_session", Value: "<portal-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))
}
```

```ts
// Sign in first. __Host-portal_session 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/portal/v1/me/passkeys";

const response = await fetch(url, {
	method: "GET",
	headers: {
		"X-Csrf-Token": "<portal-csrf>",
		"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);
```

```csharp
// Sign in first. __Host-portal_session 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/portal/v1/me/passkeys");
request.Headers.TryAddWithoutValidation("X-Csrf-Token", "<portal-csrf>");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Cookie", "__Host-portal_session=<portal-session>");

var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

### DELETE `/api/portal/v1/me/passkeys/{passkeyID}` {#depot.portalapi.passkeyRemove}

**passkeyRemove deletes one of the caller's passkeys.**

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `passkeyID` | path | string | Yes |  |

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `204` | None | Success, with no body. |
| `404` | `application/problem+json`, ProblemDetails | No resource matches that id. |

#### Request samples

```bash
# Sign in first. __Host-portal_session 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/portal/v1/me/passkeys/<passkeyID>' \
  -H 'X-Csrf-Token: <portal-csrf>' \
  -H 'Accept: application/json' \
  -b '__Host-portal_session=<portal-session>'
```

```powershell
# Sign in first. __Host-portal_session 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' = '<portal-csrf>'
    'Accept' = 'application/json'
    'Cookie' = '__Host-portal_session=<portal-session>'
}

$response = Invoke-RestMethod `
    -Method Delete `
    -Uri 'https://depot.example.com/api/portal/v1/me/passkeys/<passkeyID>' `
    -Headers $headers

$response | ConvertTo-Json -Depth 10
```

```python
# Sign in first. __Host-portal_session 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/portal/v1/me/passkeys/<passkeyID>"
headers = {
    "X-Csrf-Token": "<portal-csrf>",
    "Accept": "application/json",
}
cookies = {
    "__Host-portal_session": "<portal-session>",
}

response = requests.delete(url, headers=headers, cookies=cookies, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// Sign in first. __Host-portal_session 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/portal/v1/me/passkeys/<passkeyID>", nil)
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("X-Csrf-Token", "<portal-csrf>")
	req.Header.Set("Accept", "application/json")
	req.AddCookie(&http.Cookie{Name: "__Host-portal_session", Value: "<portal-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))
}
```

```ts
// Sign in first. __Host-portal_session 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/portal/v1/me/passkeys/<passkeyID>";

const response = await fetch(url, {
	method: "DELETE",
	headers: {
		"X-Csrf-Token": "<portal-csrf>",
		"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);
```

```csharp
// Sign in first. __Host-portal_session 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/portal/v1/me/passkeys/<passkeyID>");
request.Headers.TryAddWithoutValidation("X-Csrf-Token", "<portal-csrf>");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Cookie", "__Host-portal_session=<portal-session>");

var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

### POST `/api/portal/v1/me/password` {#depot.portalapi.passwordChange}

**passwordChange changes the caller's password and signs their other sessions out.**

#### Request body

Required, sent as `application/json`.

The body is `any`.

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `204` | None | Success, with no body. |
| `400` | None | The request was refused. |

#### Request samples

```bash
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.
curl -X POST 'https://depot.example.com/api/portal/v1/me/password' \
  -H 'X-Csrf-Token: <portal-csrf>' \
  -H 'Content-Type: application/json' \
  -b '__Host-portal_session=<portal-session>' \
  --data '"string"'
```

```powershell
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

$headers = @{
    'X-Csrf-Token' = '<portal-csrf>'
    'Content-Type' = 'application/json'
    'Cookie' = '__Host-portal_session=<portal-session>'
}

$body = @'
"string"
'@

$response = Invoke-RestMethod `
    -Method Post `
    -Uri 'https://depot.example.com/api/portal/v1/me/password' `
    -Headers $headers `
    -ContentType 'application/json' `
    -Body $body

$response | ConvertTo-Json -Depth 10
```

```python
# Sign in first. __Host-portal_session is a session cookie, so send it with every request.

import requests

url = "https://depot.example.com/api/portal/v1/me/password"
headers = {
    "X-Csrf-Token": "<portal-csrf>",
    "Content-Type": "application/json",
}
cookies = {
    "__Host-portal_session": "<portal-session>",
}
payload = "string"

response = requests.post(url, headers=headers, cookies=cookies, json=payload, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// Sign in first. __Host-portal_session is a session cookie, so send it with every request.
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	body := []byte(`"string"`)

	req, err := http.NewRequest(http.MethodPost, "https://depot.example.com/api/portal/v1/me/password", bytes.NewReader(body))
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("X-Csrf-Token", "<portal-csrf>")
	req.Header.Set("Content-Type", "application/json")
	req.AddCookie(&http.Cookie{Name: "__Host-portal_session", Value: "<portal-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))
}
```

```ts
// Sign in first. __Host-portal_session 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/portal/v1/me/password";

const response = await fetch(url, {
	method: "POST",
	headers: {
		"X-Csrf-Token": "<portal-csrf>",
		"Content-Type": "application/json",
	},
	credentials: "include",
	body: JSON.stringify("string"),
});

if (!response.ok) {
	throw new Error(`Request failed with status ${response.status}`);
}

const data = await response.json();
console.log(data);
```

```csharp
// Sign in first. __Host-portal_session 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 = """
"string"
""";

var request = new HttpRequestMessage(HttpMethod.Post, "https://depot.example.com/api/portal/v1/me/password");
request.Headers.TryAddWithoutValidation("X-Csrf-Token", "<portal-csrf>");
request.Headers.TryAddWithoutValidation("Cookie", "__Host-portal_session=<portal-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/portal/v1/me/sessions` {#depot.portalapi.sessionList}

**sessionList lists the caller's open sessions.**

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `200` | `application/json`, array of SessionSummary | Success. |

#### Request samples

```bash
# Sign in first. __Host-portal_session 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/portal/v1/me/sessions' \
  -H 'X-Csrf-Token: <portal-csrf>' \
  -H 'Accept: application/json' \
  -b '__Host-portal_session=<portal-session>'
```

```powershell
# Sign in first. __Host-portal_session 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' = '<portal-csrf>'
    'Accept' = 'application/json'
    'Cookie' = '__Host-portal_session=<portal-session>'
}

$response = Invoke-RestMethod `
    -Method Get `
    -Uri 'https://depot.example.com/api/portal/v1/me/sessions' `
    -Headers $headers

$response | ConvertTo-Json -Depth 10
```

```python
# Sign in first. __Host-portal_session 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/portal/v1/me/sessions"
headers = {
    "X-Csrf-Token": "<portal-csrf>",
    "Accept": "application/json",
}
cookies = {
    "__Host-portal_session": "<portal-session>",
}

response = requests.get(url, headers=headers, cookies=cookies, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// Sign in first. __Host-portal_session 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/portal/v1/me/sessions", nil)
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("X-Csrf-Token", "<portal-csrf>")
	req.Header.Set("Accept", "application/json")
	req.AddCookie(&http.Cookie{Name: "__Host-portal_session", Value: "<portal-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))
}
```

```ts
// Sign in first. __Host-portal_session 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/portal/v1/me/sessions";

const response = await fetch(url, {
	method: "GET",
	headers: {
		"X-Csrf-Token": "<portal-csrf>",
		"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);
```

```csharp
// Sign in first. __Host-portal_session 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/portal/v1/me/sessions");
request.Headers.TryAddWithoutValidation("X-Csrf-Token", "<portal-csrf>");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Cookie", "__Host-portal_session=<portal-session>");

var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

### DELETE `/api/portal/v1/me/sessions/{sessionID}` {#depot.portalapi.sessionRevoke}

**sessionRevoke signs one of the caller's own sessions out.**

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `sessionID` | path | string | Yes |  |

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `204` | None | Success, with no body. |
| `404` | `application/problem+json`, ProblemDetails | No resource matches that id. |

#### Request samples

```bash
# Sign in first. __Host-portal_session 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/portal/v1/me/sessions/<sessionID>' \
  -H 'X-Csrf-Token: <portal-csrf>' \
  -H 'Accept: application/json' \
  -b '__Host-portal_session=<portal-session>'
```

```powershell
# Sign in first. __Host-portal_session 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' = '<portal-csrf>'
    'Accept' = 'application/json'
    'Cookie' = '__Host-portal_session=<portal-session>'
}

$response = Invoke-RestMethod `
    -Method Delete `
    -Uri 'https://depot.example.com/api/portal/v1/me/sessions/<sessionID>' `
    -Headers $headers

$response | ConvertTo-Json -Depth 10
```

```python
# Sign in first. __Host-portal_session 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/portal/v1/me/sessions/<sessionID>"
headers = {
    "X-Csrf-Token": "<portal-csrf>",
    "Accept": "application/json",
}
cookies = {
    "__Host-portal_session": "<portal-session>",
}

response = requests.delete(url, headers=headers, cookies=cookies, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// Sign in first. __Host-portal_session 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/portal/v1/me/sessions/<sessionID>", nil)
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("X-Csrf-Token", "<portal-csrf>")
	req.Header.Set("Accept", "application/json")
	req.AddCookie(&http.Cookie{Name: "__Host-portal_session", Value: "<portal-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))
}
```

```ts
// Sign in first. __Host-portal_session 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/portal/v1/me/sessions/<sessionID>";

const response = await fetch(url, {
	method: "DELETE",
	headers: {
		"X-Csrf-Token": "<portal-csrf>",
		"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);
```

```csharp
// Sign in first. __Host-portal_session 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/portal/v1/me/sessions/<sessionID>");
request.Headers.TryAddWithoutValidation("X-Csrf-Token", "<portal-csrf>");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Cookie", "__Host-portal_session=<portal-session>");

var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

### GET `/api/portal/v1/orgs` {#depot.portalapi.orgs}

**orgs lists the organizations the caller can switch to: the membership index (derived, may lag), each entry re-checked for an enabled portal.**

The org middleware still re-reads the member row on every org request.

#### Responses

| Status | Body | Description |
| --- | --- | --- |
| `200` | `application/json`, array of OrgSummary | Success. |

#### Request samples

```bash
# Sign in first. __Host-portal_session 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/portal/v1/orgs' \
  -H 'X-Csrf-Token: <portal-csrf>' \
  -H 'Accept: application/json' \
  -b '__Host-portal_session=<portal-session>'
```

```powershell
# Sign in first. __Host-portal_session 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' = '<portal-csrf>'
    'Accept' = 'application/json'
    'Cookie' = '__Host-portal_session=<portal-session>'
}

$response = Invoke-RestMethod `
    -Method Get `
    -Uri 'https://depot.example.com/api/portal/v1/orgs' `
    -Headers $headers

$response | ConvertTo-Json -Depth 10
```

```python
# Sign in first. __Host-portal_session 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/portal/v1/orgs"
headers = {
    "X-Csrf-Token": "<portal-csrf>",
    "Accept": "application/json",
}
cookies = {
    "__Host-portal_session": "<portal-session>",
}

response = requests.get(url, headers=headers, cookies=cookies, timeout=30)
response.raise_for_status()
print(response.json())
```

```go
// Sign in first. __Host-portal_session 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/portal/v1/orgs", nil)
	if err != nil {
		log.Fatal(err)
	}

	req.Header.Set("X-Csrf-Token", "<portal-csrf>")
	req.Header.Set("Accept", "application/json")
	req.AddCookie(&http.Cookie{Name: "__Host-portal_session", Value: "<portal-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))
}
```

```ts
// Sign in first. __Host-portal_session 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/portal/v1/orgs";

const response = await fetch(url, {
	method: "GET",
	headers: {
		"X-Csrf-Token": "<portal-csrf>",
		"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);
```

```csharp
// Sign in first. __Host-portal_session 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/portal/v1/orgs");
request.Headers.TryAddWithoutValidation("X-Csrf-Token", "<portal-csrf>");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Cookie", "__Host-portal_session=<portal-session>");

var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
```
