# Authentication

Login, refresh, tenant selection, password reset, and email verification for first-party (JWT) callers.

Generated from `apps/api/openapi.json`. HTML version: https://docs.institflow.com/en/reference/auth

16 operations.

## POST /api/v1/auth/change-password

Change your own password. Verifies the current one, then revokes every OTHER session (this one stays signed in).

- Operation id: `AuthController_changePassword_v1`
- Permission: —
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `currentPassword` | string | yes | ≥1 chars |
| `newPassword` | string | yes | ≥10 chars |

```json
{
  "currentPassword": "string",
  "newPassword": "string"
}
```

### Responses

**200** — The password was changed and every other session revoked.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `ok` | enum: true | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/auth/change-password" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "currentPassword": "string",
    "newPassword": "string"
  }'
```

## POST /api/v1/auth/forgot-password

Request a password-reset email (always responds 200, whether or not the email exists).

- Operation id: `AuthController_forgotPassword_v1`
- Permission: —
- Auth: public (no credential)
- `Idempotency-Key`: not required

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `email` | string (email) | yes |  |

```json
{
  "email": "ada.lovelace@example.com"
}
```

### Responses

**200** — A reset email was sent, if the account exists.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `ok` | enum: true | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/auth/forgot-password" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "email": "ada.lovelace@example.com"
  }'
```

## GET /api/v1/auth/institflow/callback

Completes sign-in with the code the issuer redirected back with (§2.5 steps 2-3). self_hosted only.

- Operation id: `InstitflowSignInController_callback_v1`
- Permission: —
- Auth: public (no credential)
- `Idempotency-Key`: not required

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `code` | query | string | no | 1–4096 chars |
| `state` | query | string | no | 1–512 chars |
| `error` | query | string | no | 1–200 chars |

### Responses

**302** — Redirect to /auth/institflow/complete, or to /login with ?error=.

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X GET "https://your-institute.example/api/v1/auth/institflow/callback" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## GET /api/v1/auth/institflow/start

Redirects to the Institflow-account issuer to begin sign-in (§2.5 step 1). self_hosted only.

- Operation id: `InstitflowSignInController_start_v1`
- Permission: —
- Auth: public (no credential)
- `Idempotency-Key`: not required

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `next` | query | string | no | 1–2048 chars |
| `login_hint` | query | string | no | 1–320 chars |
| `join` | query | string | no |  |

### Responses

**302** — Redirect to the issuer’s /oauth/authorize.

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X GET "https://your-institute.example/api/v1/auth/institflow/start" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## POST /api/v1/auth/login

Log in with email + password. A platform admin never gets tokens directly — the response is a `mfaRequired` challenge instead (docs/specs/phase11-vendor-console.md §2.4).

- Operation id: `AuthController_login_v1`
- Permission: —
- Auth: public (no credential)
- `Idempotency-Key`: not required

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `email` | string (email) | yes |  |
| `password` | string | yes | ≥1 chars |
| `client` | enum: "web" \| "mobile" | no | default: "web" |

```json
{
  "email": "ada.lovelace@example.com",
  "password": "string",
  "client": "web"
}
```

### Responses

**200** — Either tokens + the user + their memberships, or an MFA challenge.

```json
{
  "mfaRequired": true,
  "mfaEnrollmentRequired": true,
  "mfaToken": "string"
}
```

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/auth/login" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "email": "ada.lovelace@example.com",
    "password": "string",
    "client": "web"
  }'
```

## POST /api/v1/auth/logout

Revoke the current session (refresh-token family).

- Operation id: `AuthController_logout_v1`
- Permission: —
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Responses

**200** — The session was revoked.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `ok` | enum: true | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/auth/logout" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## POST /api/v1/auth/logout-all

Revoke every session (every device) for the current user.

- Operation id: `AuthController_logoutAll_v1`
- Permission: —
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Responses

**200** — Every session was revoked.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `ok` | enum: true | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/auth/logout-all" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## GET /api/v1/auth/me

The current user, their memberships, and effective permissions.

- Operation id: `AuthController_me_v1`
- Permission: —
- Auth: credential required
- `Idempotency-Key`: not required

### Responses

**200** — The current user profile.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `user` | object | yes |  |
| `memberships` | array<MembershipSummary> | yes |  |
| `activeTenantId` | string (uuid) \| null | yes |  |
| `permissions` | array<string> | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X GET "https://your-institute.example/api/v1/auth/me" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY"
```

## POST /api/v1/auth/mfa/step-up

Re-prove the current TOTP code on an already-authenticated platform session, refreshing mfa_at for @RequireRecentMfa routes.

- Operation id: `AuthController_mfaStepUp_v1`
- Permission: —
- Auth: credential required
- `Idempotency-Key`: not required

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `code` | string | yes |  |

```json
{
  "code": "string"
}
```

### Responses

**200** — A fresh access token with a new mfa_at.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `accessToken` | string | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/auth/mfa/step-up" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "code": "string"
  }'
```

## POST /api/v1/auth/mfa/verify

Complete a platform admin login started by POST /auth/login with a TOTP or recovery code.

- Operation id: `AuthController_mfaVerify_v1`
- Permission: —
- Auth: public (no credential)
- `Idempotency-Key`: not required

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `mfaToken` | string | yes | ≥1 chars |
| `code` | string | no |  |
| `recoveryCode` | string | no | ≥1 chars |
| `client` | enum: "web" \| "mobile" | no | default: "web" |

```json
{
  "mfaToken": "string",
  "code": "string",
  "recoveryCode": "string",
  "client": "web"
}
```

### Responses

**200** — Tokens, the user, and their memberships (a platform admin has no memberships).

```json
{
  "mfaRequired": true,
  "mfaEnrollmentRequired": true,
  "mfaToken": "string"
}
```

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/auth/mfa/verify" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "mfaToken": "string",
    "code": "string",
    "recoveryCode": "string",
    "client": "web"
  }'
```

## POST /api/v1/auth/platform-invitations/accept

Accept a platform-admin invitation. Creates the user if new (or attaches an already-verified existing account), then requires TOTP enrolment before any session is issued.

- Operation id: `PlatformAdminInvitationAcceptController_accept_v1`
- Permission: —
- Auth: public (no credential)
- `Idempotency-Key`: not required

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `token` | string | yes | ≥1 chars |
| `fullName` | string | no | 1–200 chars |
| `password` | string | no | ≥10 chars |
| `locale` | enum: "ar" \| "en" \| "he" | no |  |

```json
{
  "token": "string",
  "fullName": "Ada Lovelace",
  "password": "string",
  "locale": "ar"
}
```

### Responses

**200** — Always an MFA-enrollment challenge — never tokens directly.

```json
{
  "mfaRequired": true,
  "mfaEnrollmentRequired": true,
  "mfaToken": "string"
}
```

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/auth/platform-invitations/accept" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "token": "string",
    "fullName": "Ada Lovelace",
    "password": "string",
    "locale": "ar"
  }'
```

## POST /api/v1/auth/refresh

Rotate the refresh token and issue a new access token.

- Operation id: `AuthController_refresh_v1`
- Permission: —
- Auth: public (no credential)
- `Idempotency-Key`: not required

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `refreshToken` | string | no | ≥1 chars |

```json
{
  "refreshToken": "string"
}
```

### Responses

**200** — A new access token (and refresh token/cookie).

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `accessToken` | string | yes |  |
| `refreshToken` | string | no |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/auth/refresh" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "refreshToken": "string"
  }'
```

## POST /api/v1/auth/register

Self-register a new user (gated by AUTH_SELF_REGISTRATION).

- Operation id: `AuthController_register_v1`
- Permission: —
- Auth: public (no credential)
- `Idempotency-Key`: not required

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `email` | string (email) | yes |  |
| `password` | string | yes | ≥10 chars |
| `fullName` | string | yes | 1–200 chars |
| `locale` | enum: "ar" \| "en" \| "he" | no |  |

```json
{
  "email": "ada.lovelace@example.com",
  "password": "string",
  "fullName": "Ada Lovelace",
  "locale": "ar"
}
```

### Responses

**201** — The newly created user (no tenant membership yet).

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `email` | string (email) | yes |  |
| `fullName` | string | yes |  |
| `locale` | enum: "ar" \| "en" \| "he" | yes |  |
| `status` | enum: "active" \| "disabled" | yes |  |
| `emailVerified` | boolean | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/auth/register" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "email": "ada.lovelace@example.com",
    "password": "string",
    "fullName": "Ada Lovelace",
    "locale": "ar"
  }'
```

## POST /api/v1/auth/reset-password

Reset a password using a token from the forgot-password email.

- Operation id: `AuthController_resetPassword_v1`
- Permission: —
- Auth: public (no credential)
- `Idempotency-Key`: not required

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `token` | string | yes | ≥1 chars |
| `password` | string | yes | ≥10 chars |

```json
{
  "token": "string",
  "password": "string"
}
```

### Responses

**200** — The password was reset.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `ok` | enum: true | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/auth/reset-password" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "token": "string",
    "password": "string"
  }'
```

## POST /api/v1/auth/select-tenant

Switch the active tenant for a new access token.

- Operation id: `AuthController_selectTenant_v1`
- Permission: —
- Auth: credential required
- `Idempotency-Key`: required for API-key callers

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `tenantId` | string (uuid) | yes |  |

```json
{
  "tenantId": "4332af8b-4332-7332-832a-4332af8b4332"
}
```

### Responses

**200** — A new access token scoped to the selected tenant.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `accessToken` | string | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/auth/select-tenant" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "tenantId": "4332af8b-4332-7332-832a-4332af8b4332"
  }'
```

## POST /api/v1/auth/verify-email

Verify an email address using a token from the verification email.

- Operation id: `AuthController_verifyEmail_v1`
- Permission: —
- Auth: public (no credential)
- `Idempotency-Key`: not required

### Request body

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `token` | string | yes | ≥1 chars |

```json
{
  "token": "string"
}
```

### Responses

**200** — The email address was verified.

| Property | Type | Required | Constraints |
| --- | --- | --- | --- |
| `ok` | enum: true | yes |  |

Every other status answers with the shared `ErrorEnvelope` — see
https://docs.institflow.com/md/en/error-codes.md

### Example request

```bash
curl -X POST "https://your-institute.example/api/v1/auth/verify-email" \
  -H "Authorization: Bearer $INSTITFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "token": "string"
  }'
```
