> For the complete documentation index, see [llms.txt](https://oten.gitbook.io/identity-support/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://oten.gitbook.io/identity-support/integration/prerequisites/appendix/api-reference.md).

# API Reference

## Base URLs

### Production

```
Base URL: https://account.oten.com
```

### Sandbox

```
Base URL: https://account.sbx.oten.dev
```

## Authentication Endpoints

### 1. Authorization Endpoint

**Endpoint**: `GET /v1/oauth/authorize`

**Description**: Initiates the OAuth 2.0 authorization flow. **REQUIRES JAR (JWT-Secured Authorization Request)**.

**URL**: `{base_url}/v1/oauth/authorize`

#### Parameters

| Parameter   | Type   | Required | Description                                   |
| ----------- | ------ | -------- | --------------------------------------------- |
| `client_id` | string | ✅        | Your application's client ID                  |
| `request`   | string | ✅        | **JAR token containing all OAuth parameters** |

#### JAR Token Requirements

The `request` parameter must contain a signed JWT with these claims:

**Required JWT Claims:**

```json
{
  "iss": "your_client_id",
  "aud": "https://account.oten.com",
  "iat": 1640995200,
  "exp": 1640995500,
  "jti": "unique-request-id",
  
  "client_id": "your_client_id",
  "redirect_uri": "https://yourapp.com/callback",
  "response_type": "code",
  "scope": "openid profile email",
  "state": "random_state_string",
  "code_challenge": "base64url_encoded_challenge",
  "code_challenge_method": "S256"
}
```

**Optional Claims:**

```json
{
  "nonce": "random_nonce_string",
  "max_age": 3600,
  "prompt": "login",
  "ui_locales": "en-US"
}
```

#### Example Request

```bash
GET /v1/oauth/authorize?client_id=your_client_id&request=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Host: account.oten.com
```

#### Success Response

**Status**: `302 Found` **Location**: `https://yourapp.com/callback?code=abc123&state=xyz789`

#### Error Responses

Authorization endpoint errors are returned as URL parameters in the redirect URI (if valid) or as an error page.

> 📖 **Complete Error Reference**: See [Error Codes Reference](broken://pages/bJ3yHAB6ah0s2qAer3PL) for comprehensive error documentation.

**Error Response Format:**

```
HTTP/1.1 302 Found
Location: https://yourapp.com/callback?
  error=invalid_request&
  error_description=The%20request%20is%20missing%20a%20required%20parameter&
  state=xyz789
```

**Common Error Codes:**

| Error Code               | Description                                            | HTTP Status | Retryable |
| ------------------------ | ------------------------------------------------------ | ----------- | --------- |
| `invalid_request`        | Missing request parameter or other required parameters | 400         | No\*      |
| `invalid_request_object` | Invalid JAR token                                      | 400         | No        |
| `invalid_client`         | Client auth failed or IP not whitelisted               | 401         | No        |
| `unauthorized_client`    | Client not authorized for grant type                   | 403         | No        |
| `access_denied`          | User denied authorization                              | 400         | Yes       |
| `server_error`           | Internal server error                                  | 500         | Yes       |

\*Note: `invalid_request` is retryable only for JAR expiration scenarios

**Error Response Examples:**

```bash
# Missing Request Parameter
GET /v1/oauth/authorize?client_id=123&response_type=code&redirect_uri=https://app.com/callback

Response:
HTTP/1.1 302 Found
Location: https://app.com/callback?error=invalid_request&error_description=Request%20parameter%20is%20required

# Invalid JAR Signature
GET /v1/oauth/authorize?client_id=123&request=invalid.jwt.token

Response:
HTTP/1.1 302 Found
Location: https://app.com/callback?error=invalid_request_object&error_description=Invalid%20JAR%20signature

# JAR Token Expired
GET /v1/oauth/authorize?client_id=123&request=expired.jwt.token

Response:
HTTP/1.1 302 Found
Location: https://app.com/callback?error=invalid_request&error_description=JAR%20token%20has%20expired

# Missing JAR Request Parameter
GET /v1/oauth/authorize?client_id=123&redirect_uri=https://app.com/callback

Response:
HTTP/1.1 302 Found
Location: https://app.com/callback?error=invalid_request&error_description=Request%20parameter%20is%20required

# Both request and request_uri provided (Invalid)
GET /v1/oauth/authorize?client_id=123&request=jwt.token&request_uri=https://example.com/request.jwt

Response:
HTTP/1.1 302 Found
Location: https://app.com/callback?error=invalid_request&error_description=Only%20one%20of%20request%20or%20request_uri%20parameters%20is%20allowed
```

### 2. Token Endpoint

**Endpoint**: `POST /v1/oauth/token`

**Description**: Exchanges authorization code for access tokens.

**URL**: `{base_url}/v1/oauth/token`

#### Headers

```
Content-Type: application/x-www-form-urlencoded
```

#### Parameters

**For Authorization Code Grant:**

| Parameter       | Type   | Required | Description                       |
| --------------- | ------ | -------- | --------------------------------- |
| `grant_type`    | string | ✅        | Must be `authorization_code`      |
| `code`          | string | ✅        | Authorization code from callback  |
| `redirect_uri`  | string | ✅        | Must match authorization request  |
| `client_id`     | string | ✅        | Your application's client ID      |
| `code_verifier` | string | ✅        | PKCE code verifier                |
| `client_secret` | string | ⚠️       | Required for confidential clients |

**For Refresh Token Grant:**

| Parameter       | Type   | Required | Description                       |
| --------------- | ------ | -------- | --------------------------------- |
| `grant_type`    | string | ✅        | Must be `refresh_token`           |
| `refresh_token` | string | ✅        | Valid refresh token               |
| `client_id`     | string | ✅        | Your application's client ID      |
| `client_secret` | string | ⚠️       | Required for confidential clients |

#### Example Request

```bash
POST /v1/oauth/token
Host: account.oten.com
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=abc123&redirect_uri=https://yourapp.com/callback&client_id=your_client_id&code_verifier=xyz789
```

#### Success Response

**Status**: `200 OK` **Content-Type**: `application/json`

```json
{
  "status": "OK",
  "data": [{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
    "token_type": "Bearer",
    "expires_in": 3600,
    "refresh_token": "def456...",
    "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
    "scope": "openid profile email"
  }],
  "message": "Tokens issued successfully"
}
```

#### Error Responses

Token endpoint errors are returned as JSON in the response body.

> 📖 **Complete Error Reference**: See [Error Codes Reference](broken://pages/bJ3yHAB6ah0s2qAer3PL) for comprehensive error documentation.

**Error Response Format:**

```json
HTTP/1.1 400 Bad Request
Content-Type: application/json

{
  "error": "invalid_grant",
  "error_description": "The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client"
}
```

**Common Error Codes:**

| Error Code               | Description                              | HTTP Status | Retryable |
| ------------------------ | ---------------------------------------- | ----------- | --------- |
| `invalid_request`        | Missing required parameter               | 400         | No        |
| `invalid_client`         | Client authentication failed             | 401         | No        |
| `invalid_grant`          | Authorization code/refresh token invalid | 400         | No        |
| `unauthorized_client`    | Client not authorized for grant type     | 403         | No        |
| `unsupported_grant_type` | Grant type not supported                 | 400         | No        |
| `server_error`           | Internal server error                    | 500         | Yes       |

**Error Response Examples:**

```bash
# Invalid Authorization Code
POST /v1/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=invalid_code&client_id=123&client_secret=secret

Response:
HTTP/1.1 400 Bad Request
{
  "error": "invalid_grant",
  "error_description": "Invalid authorization code: code not found"
}

# PKCE Verification Failed
POST /v1/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=valid_code&client_id=123&code_verifier=wrong_verifier

Response:
HTTP/1.1 400 Bad Request
{
  "error": "invalid_grant",
  "error_description": "Invalid code verifier"
}

# IP Address Not Whitelisted (Client Credentials)
POST /v1/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=123&client_secret=secret

Response:
HTTP/1.1 401 Unauthorized
{
  "error": "invalid_client",
  "error_description": "Invalid client IP: 192.168.1.100 is not in whitelist"
}

# Public Client Using Client Credentials
POST /v1/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=public_client_123

Response:
HTTP/1.1 403 Forbidden
{
  "error": "unauthorized_client",
  "error_description": "Public clients are not authorized for client credentials grant"
}

# Client Not Confidential
POST /v1/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=123&client_secret=secret

Response:
HTTP/1.1 401 Unauthorized
{
  "error": "invalid_client",
  "error_description": "Client is not confidential"
}

# Missing IP Address in Client Credentials Request
POST /v1/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=123&client_secret=secret

Response:
HTTP/1.1 401 Unauthorized
{
  "error": "invalid_client",
  "error_description": "Missing IP address in client credentials request"
}
```

### 3. Token Validation Endpoint

**Endpoint**: `POST /v1/token/validate`

**Description**: Validates an access token and returns token information.

**URL**: `{base_url}/v1/token/validate`

#### Headers

```
Content-Type: application/json
```

#### Parameters

| Parameter | Type   | Required | Description              |
| --------- | ------ | -------- | ------------------------ |
| `token`   | string | ✅        | Access token to validate |

#### Example Request

```bash
POST /v1/token/validate
Host: account.oten.com
Content-Type: application/json

{
  "token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}
```

#### Success Response

**Status**: `200 OK` **Content-Type**: `application/json`

```json
{
  "status": "OK",
  "data": [{
    "active": true,
    "client_id": "your_client_id",
    "username": "user@example.com",
    "scope": "openid profile email",
    "exp": 1640998800,
    "iat": 1640995200,
    "sub": "user-uuid-123",
    "aud": "your_client_id"
  }],
  "message": "Token is valid"
}
```

#### Error Responses

| Error             | Description                 | HTTP Status |
| ----------------- | --------------------------- | ----------- |
| `invalid_token`   | Token is invalid or expired | 401         |
| `invalid_request` | Missing token parameter     | 400         |

### 4. User Info Endpoint

**Endpoint**: `GET /v1/userinfo`

**Description**: Returns user information for a valid access token.

**URL**: `{base_url}/v1/userinfo`

#### Headers

```
Authorization: Bearer {access_token}
```

#### Example Request

```bash
GET /v1/userinfo
Host: account.oten.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
```

#### Success Response

**Status**: `200 OK` **Content-Type**: `application/json`

```json
{
  "sub": "user-uuid-123",
  "email": "user@example.com",
  "email_verified": true,
  "name": "John Doe",
  "given_name": "John",
  "family_name": "Doe",
  "picture": "https://example.com/avatar.jpg",
  "locale": "en-US",
  "updated_at": 1640995200
}
```

#### Error Responses

| Error                | Description                 | HTTP Status |
| -------------------- | --------------------------- | ----------- |
| `invalid_token`      | Token is invalid or expired | 401         |
| `insufficient_scope` | Token lacks required scope  | 403         |

## Discovery Endpoints

### 5. OpenID Connect Discovery

**Endpoint**: `GET /.well-known/openid_configuration`

**Description**: Returns OpenID Connect configuration metadata.

**URL**: `{base_url}/.well-known/openid_configuration`

#### Example Request

```bash
GET /.well-known/openid_configuration
Host: account.oten.com
```

#### Success Response

**Status**: `200 OK` **Content-Type**: `application/json`

```json
{
  "issuer": "https://account.oten.com",
  "authorization_endpoint": "https://account.oten.com/v1/oauth/authorize",
  "token_endpoint": "https://account.oten.com/v1/oauth/token",
  "userinfo_endpoint": "https://account.oten.com/v1/userinfo",
  "jwks_uri": "https://account.oten.com/.well-known/jwks.json",
  "scopes_supported": ["openid", "profile", "email", "phone", "offline_access"],
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code", "refresh_token"],
  "subject_types_supported": ["public"],
  "id_token_signing_alg_values_supported": ["RS256", "EdDSA"],
  "request_object_signing_alg_values_supported": ["HS256", "EdDSA"],
  "token_endpoint_auth_methods_supported": ["client_secret_post", "private_key_jwt"],
  "claims_supported": ["sub", "email", "email_verified", "name", "given_name", "family_name", "picture", "locale"]
}
```

### 6. JWKS Endpoint

**Endpoint**: `GET /.well-known/jwks.json`

**Description**: Returns JSON Web Key Set for token verification.

**URL**: `{base_url}/.well-known/jwks.json`

#### Example Request

```bash
GET /.well-known/jwks.json
Host: account.oten.com
```

#### Success Response

**Status**: `200 OK` **Content-Type**: `application/json`

```json
{
  "keys": [
    {
      "kty": "RSA",
      "use": "sig",
      "kid": "key-1",
      "alg": "RS256",
      "n": "base64url_encoded_modulus",
      "e": "AQAB"
    },
    {
      "kty": "OKP",
      "use": "sig",
      "kid": "key-2",
      "alg": "EdDSA",
      "crv": "Ed25519",
      "x": "base64url_encoded_public_key"
    }
  ]
}
```

## Rate Limits

All endpoints are subject to rate limiting:

### Production Environment

| Endpoint              | Rate Limit    | Window                |
| --------------------- | ------------- | --------------------- |
| `/v1/oauth/authorize` | 10 requests   | per minute per IP     |
| `/v1/oauth/token`     | 60 requests   | per minute per client |
| `/v1/token/validate`  | 1000 requests | per minute per client |
| `/v1/userinfo`        | 100 requests  | per minute per token  |
| Discovery endpoints   | 100 requests  | per minute per IP     |

### Development Environment

| Endpoint              | Rate Limit    | Window                |
| --------------------- | ------------- | --------------------- |
| `/v1/oauth/authorize` | 20 requests   | per minute per IP     |
| `/v1/oauth/token`     | 120 requests  | per minute per client |
| `/v1/token/validate`  | 2000 requests | per minute per client |
| `/v1/userinfo`        | 200 requests  | per minute per token  |
| Discovery endpoints   | 200 requests  | per minute per IP     |

### Rate Limit Headers

When rate limits are exceeded, the following headers are returned:

```
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1640995260
Retry-After: 60

{
  "status": "ERROR",
  "message": "Rate limit exceeded",
  "error_code": "rate_limit_exceeded"
}
```

## Error Response Format

All error responses follow this standard format:

```json
{
  "status": "ERROR",
  "message": "Human-readable error description",
  "error_code": "machine_readable_error_code",
  "data": null
}
```

### Common Error Codes

| Error Code                | Description                                         | HTTP Status |
| ------------------------- | --------------------------------------------------- | ----------- |
| `invalid_request`         | Request is missing required parameters or malformed | 400         |
| `invalid_client`          | Client authentication failed                        | 401         |
| `invalid_grant`           | Authorization grant is invalid, expired, or revoked | 400         |
| `unauthorized_client`     | Client is not authorized for this grant type        | 400         |
| `unsupported_grant_type`  | Grant type is not supported                         | 400         |
| `invalid_scope`           | Requested scope is invalid or unknown               | 400         |
| `access_denied`           | User denied the authorization request               | 400         |
| `server_error`            | Internal server error                               | 500         |
| `temporarily_unavailable` | Service temporarily unavailable                     | 503         |
| `invalid_request`         | JAR required, JAR expired, or missing parameters    | 400         |
| `invalid_request_object`  | JAR signature verification failed                   | 400         |
| `rate_limit_exceeded`     | Rate limit exceeded                                 | 429         |

**Note**: Oten IDP uses standard OAuth 2.0 error codes. Specific scenarios like JAR requirements, workspace selection, or MFA requirements are indicated through the `error_description` parameter.

## Supported Scopes

### OpenID Connect Scopes

| Scope     | Description               | Claims Returned                                                        |
| --------- | ------------------------- | ---------------------------------------------------------------------- |
| `openid`  | Required for OIDC flow    | `sub`                                                                  |
| `profile` | Basic profile information | `name`, `given_name`, `family_name`, `picture`, `locale`, `updated_at` |
| `email`   | Email address             | `email`, `email_verified`                                              |
| `phone`   | Phone number              | `phone_number`, `phone_number_verified`                                |

### OAuth 2.0 Scopes

| Scope            | Description               |
| ---------------- | ------------------------- |
| `offline_access` | Request refresh token     |
| `read`           | Read access to resources  |
| `write`          | Write access to resources |

### Custom Scopes

Custom scopes can be defined per application. Contact support for custom scope configuration.

## Token Formats

### Access Token

Access tokens are JWTs signed with RS256 or EdDSA:

```json
{
  "iss": "https://account.oten.com",
  "sub": "user-uuid-123",
  "aud": "your_client_id",
  "exp": 1640998800,
  "iat": 1640995200,
  "scope": "openid profile email",
  "client_id": "your_client_id"
}
```

### ID Token

ID tokens are JWTs signed with RS256:

```json
{
  "iss": "https://account.oten.com",
  "sub": "user-uuid-123",
  "aud": "your_client_id",
  "exp": 1640998800,
  "iat": 1640995200,
  "nonce": "random_nonce_string",
  "email": "user@example.com",
  "email_verified": true,
  "name": "John Doe",
  "given_name": "John",
  "family_name": "Doe",
  "picture": "https://example.com/avatar.jpg",
  "locale": "en-US"
}
```

### Refresh Token

Refresh tokens are opaque strings that can be used to obtain new access tokens.

## Security Considerations

### HTTPS Required

All endpoints **MUST** be accessed over HTTPS. HTTP requests will be rejected.

### JAR Requirement

All authorization requests **MUST** use JAR (JWT-Secured Authorization Request). Traditional OAuth query parameters will be rejected.

### PKCE Required

PKCE (Proof Key for Code Exchange) is **required** for all public clients and **recommended** for confidential clients.

### Token Validation

Always validate tokens before use:

1. Verify signature using JWKS
2. Check expiration (`exp` claim)
3. Verify audience (`aud` claim)
4. Verify issuer (`iss` claim)

## SDK and Libraries

### Official Libraries

* **Go**: `gitlab.oten.com/go-sdk/go-oauth/client`
* **JavaScript/Node.js**: Coming soon
* **Python**: Coming soon

### Community Libraries

See [Step 1: Choose OAuth Library](broken://pages/zUXQja7FaXnHWIpBFAl5) for recommended third-party libraries.

## Support

For API support and questions:

* **Technical Support**: <support@oten.live>

## Related Documentation

* [Configuration Reference](broken://pages/XsyPoCRDPUpz0vcP6KkD) - Endpoints and settings
* [JAR Complete Implementation Guide](broken://pages/TTsI7h4QqrFoRyKuF1Di) - JAR implementation examples
* [Developer Integration Guide](broken://pages/Uq8Tw3CxGITFUaAZvo1U) - Complete integration process
