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.
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/catalogon that host.
Step 2 — Call the catalog (GET, no auth)
Example probe (first few rows):
curl -sS "https://restormel.dev/keys/dashboard/api/catalog?limit=5" | jq '.contractVersion, .generatedAt, (.providers|length), (.data|length)'Successful JSON includes:
contractVersion— schema / semantics versioncompatibility— minimum recommended versions for CLI /@restormel/keysdashboard client, plus docs URLexternalSignals— credential-free runtime signals (OpenAI/Anthropic status snapshots, OpenRouter public endpoint health summaries, plusfreshness/allFreshfor staleness SLO)generatedAt— ISO timestamp for this payloadproviders[]—id,displayName,modelCount,validation(mode,requiresBaseUrl,requiresModel, optionaldefaultApiBaseUrl)data[]— models withid,canonicalName,lifecycleState,providerTypes,variants[](providerModelIdis what you send to the vendor API)paging—limit,offset,countfor this page
Step 3 — Page through large catalogs
# 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.jsonStep 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, trackcontractVersion, and monitorcompatibilityfor 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
- Build provider pickers from
providers[](usevalidation.modeto choose native vs OpenAI-compatible client code). - Build model pickers from
data[]; scope models byproviderTypesand selected provider. - When calling a vendor, use the variant’s
providerModelIdfor that provider. - If
validation.defaultApiBaseUrlis 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.
pnpm add @restormel/keysimport { 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:
npx @restormel/keys-cli catalog fetchexport RESTORMEL_KEYS_BASE=https://restormel.dev
npx @restormel/keys-cli catalog fetchFull JSON:
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).
# 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
- Cloud API — Resolve and other authenticated dashboard APIs
- CLI integration —
keys patchalso probes this catalog endpoint - Framework compatibility — UI packages and demos that consume the catalog