Several APIs, one installation.
openapi.specs turns one installation into a portal: a selector in the header, one schema active at a time, and everything the reader accumulates kept separate per spec. The feature page makes the case; this guide covers the mechanics.
Declare the specs
{
"openapi": {
"specs": [
{ "id": "payments", "title": "Payments API", "url": "https://example.com/payments.json" },
{ "id": "accounts", "title": "Accounts API", "url": "https://example.com/accounts.yaml" }
],
"default": "payments"
}
}id— required, a stable slug ([a-z0-9-]), unique in the array. It is both a route segment (#/s/{id}/…) and a storage prefix. A duplicate or invalid id is a config error at boot.title— the selector label. It is needed because inactive specs are never downloaded, so theirinfo.titleis unknown. Falls back toid.- Each entry takes
urlor an inlinespec. Only the active spec is downloaded, parsed and indexed, so an installation with twelve APIs costs the reader one. defaultpicks the spec shown on arrival. Without it, the first entry is used.
A single-spec openapi.url config behaves exactly as before: no selector, unprefixed routes, same storage keys.
Override per spec
The root config carries what the installation shares, and an entry redeclares what is specific to it. The merge rules are the ones in the configuration reference: settings objects merge key by key with the spec winning, named lists merge by identifier, hide and overlays accumulate with the root first, and environmentsLocked is replaced.
tryIt.requestCredentials is the clearest case: the right value depends on the target API, so it belongs on the entry.
{
"openapi": {
"specs": [
{ "id": "payments", "title": "Payments API", "url": "https://example.com/payments.json",
"branding": { "productName": "Payments" },
"theme": { "default": "corporate", "available": ["corporate", "dark"] } },
{ "id": "accounts", "title": "Accounts API", "url": "https://example.com/accounts.yaml",
"tryIt": { "requestCredentials": "include" },
"environmentsLocked": true,
"features": { "scenarios": false } }
]
}
}Three keys do not travel:
historyis root-only — retention is one browser storage cap for all specs.theme.customis root-only — themes are injected once at boot.scenariosare entry-only — a scenario references operations of one specific spec.
Each case is named in the console when a config misplaces it.
What isolation covers
Environments, request history, OAuth tokens, try-it header memory, scenarios, search and a reader’s local schema patch are all namespaced by spec id.
Two specs declaring a same-named scheme — bearerAuth is everywhere — never share a variable, so a token obtained on Payments cannot be injected into a request against Accounts. Deep links carry the prefix (#/s/payments/op/…), so a shared link lands on the right API; a prefix-less link opens on the active spec.
The id is the storage key
Because id prefixes every stored key, changing a spec’s id resets that spec’s local data — environments, history, local scenarios. Choose ids that are stable and never recycled.