Canonical model & provider catalog

Use a single HTTP catalog instead of hardcoding model IDs in your product. Restormel publishes providers, models, per-provider variants (vendor model strings), and validation metadata (native vs openai_compatible, optional defaultApiBaseUrl). The feed is public read — no Gateway Key required.

Canonical reference (maintainers): Catalog governance in the repo describes CI drift checks and the dashboard seed. This page is the integration recipe you can share with partners.

Stable contract — Check contractVersion in every response (e.g. 2026-03-26.catalog.v6). If it changes, re-validate your parser. Each model may include deprecationDate, retirementDate (ISO 8601), and replacementModelId when set. The catalog only exposes models that match @restormel/keys defaultProviders (current, maintained lists). Use skipDefaultAllowlist=1 only for operator debugging.

Global catalog vs project model index

This page describes the public GET …/api/catalog feed (full tenant-wide model directory, no Gateway Key). When you need the per-project allowlist Restormel stores for pickers and host merges (canonical providerType + modelId rows, optional enabled), use the Dashboard API with a Gateway Key: GET /keys/dashboard/api/projects/{projectId}/models — response bindings are in JSON data (not data.bindings). Prefer GET …/api/models for the legacy “global list” shape; avoid ?source=catalog on the project path for new code. Full matrix, curl examples, and validation errors (project_models_validation_failed): Cloud API. Maintainer-facing contract summary: docs/restormel-integration/keys-catalog-sync.md in the repo.

Step 1 — Pick a base URL

  • Hosted: https://restormel.dev (or your own deployment hostname).
  • Catalog path is always /keys/dashboard/api/catalog on that host.

Step 2 — Call the catalog (GET, no auth)

Example probe (first few rows):

bash
curl -sS "https://restormel.dev/keys/dashboard/api/catalog?limit=5" | jq '.contractVersion, .generatedAt, (.providers|length), (.data|length)'

Successful JSON includes:

  • contractVersion — schema / semantics version
  • compatibility — minimum recommended versions for CLI / @restormel/keys dashboard client, plus docs URL
  • externalSignals — credential-free runtime signals (OpenAI/Anthropic status snapshots, OpenRouter public endpoint health summaries, plus freshness / allFresh for staleness SLO)
  • generatedAt — ISO timestamp for this payload
  • providers[]id, displayName, modelCount, validation (mode, requiresBaseUrl, requiresModel, optional defaultApiBaseUrl)
  • data[] — models with id, canonicalName, lifecycleState, providerTypes, variants[] (providerModelId is what you send to the vendor API)
  • paginglimit, offset, count for this page

Step 3 — Page through large catalogs

bash
# Default page size is 500 models per response (max 1000). Use offset for the next page.
curl -sS "https://restormel.dev/keys/dashboard/api/catalog?limit=500&offset=0" -o page0.json
curl -sS "https://restormel.dev/keys/dashboard/api/catalog?limit=500&offset=500" -o page1.json

Step 4 — Cache and refresh

  • Store the JSON (or your derived lists) in your backend cache, object store, or build artifact.
  • Refresh on a schedule (e.g. hourly/daily) and on deploy; compare generatedAt, track contractVersion, and monitor compatibility for min-client upgrades.
  • Keep a last-known-good snapshot if Restormel is unreachable — but treat the network result as authoritative when available.

Step 5 — Map to your UI and API calls

  1. Build provider pickers from providers[] (use validation.mode to choose native vs OpenAI-compatible client code).
  2. Build model pickers from data[]; scope models by providerTypes and selected provider.
  3. When calling a vendor, use the variant’s providerModelId for that provider.
  4. If validation.defaultApiBaseUrl is present, prefer it over hardcoding vendor base URLs.

Step 6 — Optional: npm helper (server-side only)

Install @restormel/keys and import from @restormel/keys/dashboard. Use only on the server — do not expose catalog fetch from the browser if you later add authenticated options.

bash
pnpm add @restormel/keys
typescript
import { fetchCanonicalCatalog, filterCanonicalCatalogForViability } from "@restormel/keys/dashboard";

const catalog = await fetchCanonicalCatalog({
  baseUrl: "https://restormel.dev", // or process.env.RESTORMEL_KEYS_BASE
  limit: 500,
  offset: 0,
});

// Optional: extra client-side filtering if you cached an older payload
const viable = filterCanonicalCatalogForViability(catalog);

console.log(viable.contractVersion, viable.providers.length, viable.data.length);

For resilience, fetchCanonicalCatalogWithFallback() tries the network first, then your local snapshot — see the @restormel/keys README.

Step 7 — Verify from CI or a laptop

Use the CLI to confirm reachability and contract version:

bash
npx @restormel/keys-cli catalog fetch
bash
export RESTORMEL_KEYS_BASE=https://restormel.dev
npx @restormel/keys-cli catalog fetch

Full JSON:

bash
npx @restormel/keys-cli catalog fetch --json | jq .

Operator query parameters

  • lifecycleState, family — filter rows (optional).
  • includeUnhealthy=1 — include deprecated/retired models and non-available variants (for debugging, not default product UIs).
bash
# Operator / debugging only — includes deprecated models and non-available variants
curl -sS "https://restormel.dev/keys/dashboard/api/catalog?includeUnhealthy=1&limit=20" | jq .

Related