← Back to docs

AI Models Endpoint

Refactor: Move Models Endpoint to Primary OpenAI Section

Status

Implemented on 2026-07-27.

Objective

Move the models discovery endpoint from the Social Media Tools extension scope to a primary OpenAI section, while maintaining backward compatibility with the existing social-media-tools endpoint.

Implemented Endpoint State

  • Primary endpoint: GET /api/ai/models
  • Legacy alias endpoint: GET /api/social-media-tools/extension/models
  • Purpose: Returns backend-discovered model list for authenticated web sessions or Tools bearer tokens Lä

Current Response Structure

{
  "models": ["gpt-4", "gpt-4o", ...],
  "default_model": "gpt-4o",
  "source": "live_discovery|configured_fallback",
  "warning": "optional message"
}

Desired State

1. Primary Endpoint (implemented)

Primary endpoint:

GET /api/ai/models

Behavior:

  • Same functionality as current social-media-tools version
  • Accepts the same authentication methods (bearer token, web session)
  • Returns identical response structure
  • Lives in OpenAI section of documentation (after "API: Internal Tools OpenAI client gateway")

2. Maintain Backward Compatibility

Keep existing endpoint:

GET /api/social-media-tools/extension/models

Implementation pattern:

  • This endpoint should become a delegating alias to the new primary endpoint
  • No logic duplication
  • Same response contract
  • Document as "Legacy endpoint — use /api/ai/models instead"

Documentation Changes

In /docs/en/ai/openai.md:

  1. After the "API: Internal Tools OpenAI client gateway" section, add new section:
## API: List available AI models

Endpoint:

- `GET /api/ai/models`

Purpose:

- returns the backend-discovered model list for the authenticated user or token
- allows any AI client to get available models without calling OpenAI directly
- reuses the same provider key resolution rules as the rest of Tools (personal OpenAI key if present, otherwise global)

### Authentication

- JWT/web user session
- bearer token with any AI-capable scope (`ai.socialgpt`, `ai.internal`, `ai.copilot`, etc.)
- admin users are always allowed
- non-admin users require at least one active personal API token or approved OpenAI access

### Response

JSON response includes:

- `models` *(array)* — available model identifiers suitable for chat completions
- `default_model` *(string)* — effective default model for this user/context
- `source` *(string)* — whether the list came from `live_discovery` or `configured_fallback`
- `warning` *(string, optional)* — fallback/discovery status message if applicable

### Example Request

```bash
curl -X GET "https://tools.tornevall.net/api/ai/models" \
  -H "Authorization: Bearer YOUR_API_TOKEN"

Example Response

{
  "ok": true,
  "models": ["gpt-4", "gpt-4-turbo", "gpt-4o", "gpt-4o-mini"],
  "default_model": "gpt-4o",
  "source": "live_discovery",
  "warning": null
}

Fallback Behavior

If live provider discovery fails:

  • Tools returns the configured/default models
  • UI stays usable even when provider is temporarily unreachable
  • source field indicates configured_fallback
  • optional warning explains why fallback was used

2. **After adding the new section, add a "Legacy APIs" subsection** at the end of the OpenAI docs:

```markdown
## Legacy: Social Media Tools Model Catalog

The endpoint:

- `GET /api/social-media-tools/extension/models`

is now a **backward-compatible alias** to `GET /api/ai/models`.

For new integrations, use `/api/ai/models` instead.

This legacy route will continue to work indefinitely to avoid breaking existing Social Media Tools extensions.

Implementation Checklist

  • Create controller method (or route/handler)

    • Location: Near existing AiGatewayController or new ModelCatalogController
    • Method: GET /api/ai/models
    • Auth: Verify bearer token scope or web session
    • Logic: Fetch models from configured OpenAI provider (server-side)
    • Fallback: Return configured models if live discovery fails
    • Response: Return JSON with models, default_model, source, warning
  • Create or update route

    • Add route in routes/api.php: Route::get('/ai/models', ...)
    • Keep existing /api/social-media-tools/extension/models route
    • Have the old route delegate to the new controller method
  • Update documentation

    • Add new "API: List available AI models" section to /docs/en/ai/openai.md
    • Add synced Swedish section in /docs/sv/ai/openai.md
    • Add "Legacy: Social Media Tools Model Catalog" section at end
    • Remove or modify the old "API: Social Media extension model catalog" section (change to legacy reference)
  • Testing

    • Test with bearer token (various scopes: ai.socialgpt, ai.internal, etc.)
    • Test with web session
    • Test fallback when provider unavailable
    • Test that both /api/ai/models and /api/social-media-tools/extension/models return identical responses
    • Verify 401/403 responses match OpenAI error semantics
  • Backward compatibility verification

    • Existing Social Media Tools extensions continue to work
    • Old endpoint returns same response as new endpoint
    • No migration required for existing clients

Rationale

Why this change:

  1. Clarity: Models endpoint is a general AI feature, not exclusive to Social Media Tools
  2. Reusability: Other internal clients (Mail Support Assistant, DNSBL engine, etc.) can use the same endpoint
  3. Consistency: Follows the pattern of /api/ai/internal/respond (other core AI endpoints)
  4. Forward-compatible: Makes it easier to add variants like /api/ai/models?filter=chat in future
  5. Documentation clarity: Primary endpoint lives in the main OpenAI section, not buried in extensions

Why maintain backward compatibility:

  • Existing browser extensions should not break
  • No forced migration of installed Chrome extensions
  • Zero disruption to current users
  • Smooth deprecation path over time