---
title: Authentication Reference
path: reference/authentication
status: published
---

# Authentication Reference

All authentication-related endpoints. For conceptual background, see [Authentication](../concepts/authentication.md).

**Base path:** `/api/v1/auth/`

## GET /api/v1/auth/config

Returns OAuth 2.0 configuration for frontends to initiate the authorization code flow. No authentication required.

**Response:**

```json
{
  "authorization_endpoint": "https://scaikey.scailabs.ai/oauth/authorize",
  "token_endpoint": "https://scaikey.scailabs.ai/oauth/token",
  "userinfo_endpoint": "https://scaidns.scailabs.ai/api/v1/auth/me",
  "end_session_endpoint": "https://scaikey.scailabs.ai/oauth/logout",
  "jwks_uri": "https://scaikey.scailabs.ai/.well-known/jwks.json",
  "issuer": "https://scaikey.scailabs.ai",
  "client_id": "app_evbil48popvdezyb",
  "scopes": ["openid", "profile", "email"]
}
```

## POST /api/v1/auth/token

Exchanges an OAuth authorization code for access and refresh tokens. Used after the user completes the ScaiKey auth flow and returns with a `code` parameter.

**Request:**

| Field | Type | Required |
|-------|------|---------|
| `code` | string | Yes |
| `code_verifier` | string | Yes (PKCE) |
| `redirect_uri` | string | Yes (must match what was sent to authorize endpoint) |

**Response:**

```json
{
  "access_token": "eyJhbGc...",
  "refresh_token": "eyJhbGc...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "id_token": "eyJhbGc..."
}
```

## POST /api/v1/auth/refresh

Exchanges a refresh token for a new access token.

**Request:**

```json
{"refresh_token": "eyJhbGc..."}
```

**Response:** Same shape as `/token`. The refresh token is typically rotated — save the new `refresh_token` and discard the old one.

## GET /api/v1/auth/me

Returns the current authenticated user. Merges JWT claims with local database state (role assignments, tenant info).

**Auth:** JWT or API key.

**Response:**

```json
{
  "data": {
    "id": "usr_qurwd4vkzh0w2z9v",
    "email": "service@scailabs.ai",
    "name": "Service Account",
    "tenant_id": "1d0763ae-...",
    "tenant_slug": "bbinfra-nl",
    "permissions": ["domains:read", "records:write", ...],
    "is_platform_admin": true,
    "is_tenant_admin": true
  }
}
```

## POST /api/v1/auth/logout

Revokes the current token at ScaiKey (if supported by the provider) and clears any server-side session.

**Auth:** JWT.

**Response:** `{"status": "ok"}`

## POST /api/v1/auth/validate

Validates a JWT without the caller needing to fetch JWKS. Useful for services that want to delegate token verification to ScaiDNS.

**Request:**

```json
{"token": "eyJhbGc..."}
```

**Response:**

```json
{
  "valid": true,
  "user_id": "usr_...",
  "tenant_id": "tnt_...",
  "expires_at": "2026-04-23T11:42:00Z"
}
```

On invalid tokens, returns `{"valid": false, "reason": "..."}`.

## /api/v1/me (alternate)

For convenience, ScaiDNS exposes a thin `/me` router in addition to `/auth/me`:

- `GET /api/v1/me/` — user info (same as `/auth/me`)
- `GET /api/v1/me/context` — user + full tenant context
- `POST /api/v1/me/permissions/check` — check if the caller has a specific permission

### POST /api/v1/me/permissions/check

**Request:**

```json
{
  "category": "records",
  "action": "write",
  "resource_id": "d_abc123"
}
```

**Response:**

```json
{"allowed": true, "reason": null}
```

Or:

```json
{"allowed": false, "reason": "No role grants records:write on this domain"}
```

## Related

- [Authentication guide](../concepts/authentication.md) — OAuth flow walkthrough.
- [Permissions and Access](../concepts/permissions-and-access.md) — how authorization resolves.
- [API Keys](./api-keys.md) — alternative auth method for machine clients.
