# 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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://oten.gitbook.io/identity-support/integration/prerequisites/appendix/api-reference.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
