diff --git a/apps/docs/app/global.css b/apps/docs/app/global.css index 6373ec36d75..6414f5797e3 100644 --- a/apps/docs/app/global.css +++ b/apps/docs/app/global.css @@ -42,6 +42,13 @@ body { --text-small: 13px; --text-base: 15px; --text-md: 16px; + + /* Code-token size for the API reference — a deliberate sixth step, between + --text-caption and --text-small, because the mono face reads small at 12px. */ + --text-code: 0.78125rem; + + --font-mono-stack: var(--font-geist-mono), ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, + "Liberation Mono", "Courier New", monospace; } /* Pure white light mode background */ @@ -134,7 +141,6 @@ body { --selection-dark: #264f78; --highlight-search-active: #f6ad55; --scrollbar-thumb-color: #c0c0c0; - --scrollbar-thumb-hover-color: #a8a8a8; --shadow-subtle: 0 2px 4px 0 rgba(0, 0, 0, 0.08); --shadow-medium: 0 4px 12px rgba(0, 0, 0, 0.1); --shadow-overlay: 0 10px 30px rgba(0, 0, 0, 0.11); @@ -216,34 +222,18 @@ body { --code-line-number: #a8a8a8; --selection-bg: #264f78; --scrollbar-thumb-color: #5a5a5a; - --scrollbar-thumb-hover-color: #6a6a6a; --shadow-overlay: 0 10px 30px rgba(0, 0, 0, 0.3); } -/* Scrollbars — platform thumb tokens, transparent track */ +/* Scrollbars — platform thumb tokens, transparent track. A non-auto + `scrollbar-width`/`scrollbar-color` makes Chromium ignore every + `::-webkit-scrollbar*` rule on the element, so no webkit block here. Hover + shading is not expressible through the standard properties. */ * { scrollbar-width: thin; scrollbar-color: var(--scrollbar-thumb-color) transparent; } -*::-webkit-scrollbar { - width: 8px; - height: 8px; -} - -*::-webkit-scrollbar-track { - background: transparent; -} - -*::-webkit-scrollbar-thumb { - background-color: var(--scrollbar-thumb-color); - border-radius: 9999px; -} - -*::-webkit-scrollbar-thumb:hover { - background-color: var(--scrollbar-thumb-hover-color); -} - /* Font family utilities */ .font-sans { font-family: var(--font-geist-sans), ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, @@ -251,8 +241,7 @@ body { } .font-mono { - font-family: var(--font-geist-mono), ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, - "Liberation Mono", "Courier New", monospace; + font-family: var(--font-mono-stack); } /* Platform UI font — Season Sans, used by the chip chrome to match the main app */ @@ -672,8 +661,7 @@ aside[data-sidebar], code, pre, pre code { - font-family: var(--font-geist-mono), ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, - "Liberation Mono", "Courier New", monospace; + font-family: var(--font-mono-stack); } /* Inline code — neutral colors aligned with sim design system */ @@ -912,16 +900,18 @@ video { display: none !important; } -/* Ensure API reference pages use the same font as the rest of the docs */ +/* Ensure API reference pages use the same font as the rest of the docs. + `.font-mono` is excluded: this selector (id + element) outranks the + `.font-mono` class rule, so without it every code identifier renders sans. */ #nd-page:has(.api-page-header), #nd-page:has(.api-page-header) h2, #nd-page:has(.api-page-header) h3, #nd-page:has(.api-page-header) h4, -#nd-page:has(.api-page-header) p, -#nd-page:has(.api-page-header) span, -#nd-page:has(.api-page-header) div, -#nd-page:has(.api-page-header) label, -#nd-page:has(.api-page-header) button { +#nd-page:has(.api-page-header) p:not(.font-mono), +#nd-page:has(.api-page-header) span:not(.font-mono), +#nd-page:has(.api-page-header) div:not(.font-mono), +#nd-page:has(.api-page-header) label:not(.font-mono), +#nd-page:has(.api-page-header) button:not(.font-mono) { font-family: var(--font-geist-sans), ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; } @@ -1162,23 +1152,45 @@ div.flex.flex-row.items-start.bg-fd-secondary.border.rounded-lg.text-xs { position: relative; } +/* API-reference metadata face — the status trigger, the content-type label, the + `required` / `header` markers, and the status-code tabs. Defined once; each + consumer below adds only its own colour, content, and order. The `code.text-xs` + label further down needs `!important` to beat fumadocs and stays separate. */ +#nd-page:has(.api-page-header) button.response-section-dropdown-trigger, +.response-section-dropdown-trigger, +#nd-page:has(.api-page-header) span.response-section-content-type, +.response-section-content-type, +#nd-page:has(.api-page-header) + .flex.flex-wrap.items-center.gap-3.not-prose:has(span.text-red-400)::after, +#nd-page:has(.api-page-header) div.my-4 > .flex.flex-wrap.items-center.gap-3.not-prose::before, +#nd-page:has(.api-page-header) div.my-4 > .flex.flex-wrap.items-center.gap-3.not-prose::after, +#nd-page:has(.api-page-header) .flex.gap-3\.5.overflow-x-auto.not-prose > button { + font-size: var(--text-code); + line-height: 1.25rem; + font-weight: 400; + font-family: var(--font-mono-stack); +} + +/* Status-code trigger — matches the content-type label beside it. */ +#nd-page:has(.api-page-header) button.response-section-dropdown-trigger, .response-section-dropdown-trigger { display: flex; align-items: center; gap: 0.25rem; - padding: 0.125rem 0.25rem; - font-size: 0.875rem; - font-weight: 500; - color: var(--color-fd-muted-foreground); + height: 1.25rem; + padding: 0 0.25rem; + color: var(--text-secondary); background: none; border: none; cursor: pointer; border-radius: 0.375rem; transition: color 0.15s; - font-family: var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif; } +/* Carries the same id-qualified prefix as the base rule above; without it the + base rule outranks this one and the trigger never changes colour on hover. */ +#nd-page:has(.api-page-header) button.response-section-dropdown-trigger:hover, .response-section-dropdown-trigger:hover { - color: var(--color-fd-foreground); + color: var(--text-primary); } .response-section-chevron { @@ -1226,7 +1238,7 @@ div.flex.flex-row.items-start.bg-fd-secondary.border.rounded-lg.text-xs { color: var(--text-primary); } .response-section-dropdown-item-selected { - color: var(--color-fd-foreground); + color: var(--text-primary); } .response-section-check { @@ -1234,10 +1246,15 @@ div.flex.flex-row.items-start.bg-fd-secondary.border.rounded-lg.text-xs { height: 0.875rem; } +/* Content-type label. The Response header renders this class; the Request Body + header renders a fumadocs `code.text-xs`. Keep the two in sync — the same + string at different weights reads as one being lighter than the other. */ +#nd-page:has(.api-page-header) span.response-section-content-type, .response-section-content-type { - font-size: 0.875rem; - color: var(--color-fd-muted-foreground); - font-family: var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif; + color: var(--text-secondary); + background: none; + border: none; + padding: 0; } /* Response schema container — remove border to match Path Parameters style */ @@ -1262,25 +1279,80 @@ div.flex.flex-row.items-start.bg-fd-secondary.border.rounded-lg.text-xs { order: 1; } -/* Type badge — order 2, grey pill */ +/* Type token — order 2. Covers every shape the slot takes: scalar span, union + wrapper, schema-reference button, and the auth row's `::after` label. Reuses + the docs inline-code recipe, so a type reads as code wherever it appears; the + explicit 20px height keeps a union level with a scalar, which its nested + links would otherwise push to 26px. */ #nd-page:has(.api-page-header) .flex.flex-wrap.items-center.gap-3.not-prose - > span.text-sm.font-mono.text-fd-muted-foreground { + > span.text-sm.font-mono.text-fd-muted-foreground, +#nd-page:has(.api-page-header) .flex.flex-wrap.items-center.gap-3.not-prose > button, +#nd-page:has(.api-page-header) .flex.flex-wrap.items-center.gap-3.not-prose > span:has(> button), +#nd-page:has(.api-page-header) + div.my-4 + > .flex.flex-wrap.items-center.gap-3.not-prose + > span.text-sm.font-mono.text-fd-muted-foreground::after { order: 2; - background-color: var(--surface-5); - color: var(--text-secondary); - padding: 0.1875rem 0.5rem; + display: inline-flex; + align-items: center; + height: 1.25rem; + /* No gap: an `array` slot holds its brackets as bare text nodes, which + become anonymous flex items, so any gap here would prise `array<` and `>` + away from the type they wrap. The union separator spaces itself instead. */ + gap: 0; + background-color: var(--surface-4); + border: 1px solid var(--border-1); + color: var(--text-body); + padding: 0 0.3125rem; border-radius: 0.375rem; - font-size: var(--text-xs); - line-height: 1.125rem; - font-weight: 500; - font-family: var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif; + font-size: var(--text-code); + line-height: 1; + font-weight: 400; + font-family: var(--font-mono-stack); +} + +/* Everything inside a type token inherits the token's own face, size, and ink. + Applied to every descendant, not just the links: a union's `|` separator is a + classless `span`, so the page-wide `span:not(.font-mono)` rule assigned it the + body sans face and one chip rendered in two faces. Anything fumadocs nests in + here later is covered by the same reset. + Underline is deferred to hover so links don't read heavier than a plain scalar + in the same box. The button that *is* the slot needs its own rule below: it + cannot `inherit`, which would pull the row's 14px sans back in. */ +#nd-page:has(.api-page-header) + .flex.flex-wrap.items-center.gap-3.not-prose + > span.text-sm.font-mono.text-fd-muted-foreground + * { + text-decoration: none; + color: inherit; + font-size: inherit; + font-family: inherit; } -html.dark - #nd-page:has(.api-page-header) +#nd-page:has(.api-page-header) .flex.flex-wrap.items-center.gap-3.not-prose - > span.text-sm.font-mono.text-fd-muted-foreground { - background-color: var(--surface-4); + > button.text-sm.font-mono.text-fd-muted-foreground { + text-decoration: none; +} +#nd-page:has(.api-page-header) + .flex.flex-wrap.items-center.gap-3.not-prose + > span.text-sm.font-mono.text-fd-muted-foreground + :is(a, button):hover, +#nd-page:has(.api-page-header) + .flex.flex-wrap.items-center.gap-3.not-prose + > button.text-sm.font-mono.text-fd-muted-foreground:hover { + text-decoration: underline; + text-underline-offset: 2px; +} + +/* Union separator — dimmed one step, no further: `string | null` started + reading as `string null` on the chip fill. Own margin; the slot has no gap. */ +#nd-page:has(.api-page-header) + .flex.flex-wrap.items-center.gap-3.not-prose + > span.text-sm.font-mono.text-fd-muted-foreground + > span { + margin: 0 0.375rem; + color: var(--text-muted); } /* Hide the "*" inside the name span — we'll add "required" as a ::after on the flex row */ @@ -1288,21 +1360,15 @@ html.dark display: none; } -/* Required badge — order 3, red pill */ +/* Required marker — order 3. Error text colour but no fill: eight required + params on one page should not read as eight alarms. */ #nd-page:has(.api-page-header) .flex.flex-wrap.items-center.gap-3.not-prose:has(span.text-red-400)::after { content: "required"; order: 3; display: inline-flex; align-items: center; - background-color: var(--badge-error-bg); color: var(--badge-error-text); - padding: 0.1875rem 0.5rem; - border-radius: 0.375rem; - font-size: var(--text-xs); - line-height: 1.125rem; - font-weight: 500; - font-family: var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif; } /* Optional "?" indicator — hide it */ #nd-page:has(.api-page-header) @@ -1326,79 +1392,52 @@ html.dark > span.font-medium.font-mono.text-fd-primary { order: 1; } +/* Auth rows collapse the real `` text to zero and draw the chip in the + `::after` below, so this span is a bare wrapper: it must drop the type-token + box it matches, or the chip renders inside a second, empty bordered box. */ #nd-page:has(.api-page-header) div.my-4 > .flex.flex-wrap.items-center.gap-3.not-prose > span.text-sm.font-mono.text-fd-muted-foreground { order: 2; font-size: 0; - padding: 0 !important; - background: none !important; + padding: 0; + background: none; + border: none; + height: auto; line-height: 0; } +/* Only the label — the box comes from the shared type-token rule above, which + this pseudo-element is a member of. */ #nd-page:has(.api-page-header) div.my-4 > .flex.flex-wrap.items-center.gap-3.not-prose > span.text-sm.font-mono.text-fd-muted-foreground::after { content: "string"; - font-size: var(--text-xs); - line-height: 1.125rem; - font-weight: 500; - font-family: var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif; - background-color: var(--surface-5); - color: var(--text-secondary); - padding: 0.1875rem 0.5rem; - border-radius: 0.375rem; - display: inline-flex; - align-items: center; -} -html.dark - #nd-page:has(.api-page-header) - div.my-4 - > .flex.flex-wrap.items-center.gap-3.not-prose - > span.text-sm.font-mono.text-fd-muted-foreground::after { - background-color: var(--surface-4); } -/* "header" badge via ::before on the auth flex row */ +/* "header" location via ::before on the auth flex row — uncontained metadata, + matching the `required` marker rather than the type token. */ #nd-page:has(.api-page-header) div.my-4 > .flex.flex-wrap.items-center.gap-3.not-prose::before { content: "header"; order: 3; display: inline-flex; align-items: center; - background-color: var(--surface-5); color: var(--text-secondary); - padding: 0.1875rem 0.5rem; - border-radius: 0.375rem; - font-size: var(--text-xs); - line-height: 1.125rem; - font-weight: 500; - font-family: var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif; -} -html.dark - #nd-page:has(.api-page-header) - div.my-4 - > .flex.flex-wrap.items-center.gap-3.not-prose::before { - background-color: var(--surface-4); } -/* "required" badge via ::after on the auth flex row — red pill */ +/* "required" marker via ::after on the auth flex row */ #nd-page:has(.api-page-header) div.my-4 > .flex.flex-wrap.items-center.gap-3.not-prose::after { content: "required"; order: 4; display: inline-flex; align-items: center; - background-color: var(--badge-error-bg); color: var(--badge-error-text); - padding: 0.1875rem 0.5rem; - border-radius: 0.375rem; - font-size: var(--text-xs); - line-height: 1.125rem; - font-weight: 500; - font-family: var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif; } -/* Hide "In: header" text below auth property — redundant with the header badge */ -#nd-page:has(.api-page-header) div.my-4 .prose-no-margin p:has(> code) { +/* Hide the trailing "In: header" line — redundant with the header marker. + Matched by position, not shape: descriptions contain a `code` too (status + codes), so a bare `p:has(> code)` also hid the API-key description. */ +#nd-page:has(.api-page-header) div.my-4 .prose-no-margin > p:last-child:has(> code) { display: none !important; } @@ -1425,36 +1464,18 @@ html.dark border-color: var(--surface-active); } -/* Body/Callback section "application/json" label — remove inline code styling */ +/* Body/Callback "application/json" label — strip inline-code chrome and keep in + sync with `.response-section-content-type`; same string, two headers. */ #nd-page:has(.api-page-header) .flex.gap-2.items-center.justify-between p.not-prose code.text-xs, #nd-page:has(.api-page-header) .flex.justify-between.gap-2.items-end p.not-prose code.text-xs { background: none !important; border: none !important; padding: 0 !important; - color: var(--color-fd-muted-foreground) !important; - font-size: 0.875rem !important; - font-family: var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif !important; -} - -/* Object/array type triggers in property rows — order 2 + badge chip styling */ -#nd-page:has(.api-page-header) .flex.flex-wrap.items-center.gap-3.not-prose > button, -#nd-page:has(.api-page-header) .flex.flex-wrap.items-center.gap-3.not-prose > span:has(> button) { - order: 2; - background-color: var(--surface-5); - color: var(--text-secondary); - padding: 0.1875rem 0.5rem; - border-radius: 0.375rem; - font-size: var(--text-xs); - line-height: 1.125rem; - font-weight: 500; - font-family: var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif; -} -html.dark #nd-page:has(.api-page-header) .flex.flex-wrap.items-center.gap-3.not-prose > button, -html.dark - #nd-page:has(.api-page-header) - .flex.flex-wrap.items-center.gap-3.not-prose - > span:has(> button) { - background-color: var(--surface-4); + color: var(--text-secondary) !important; + font-size: var(--text-code) !important; + line-height: 1.25rem !important; + font-weight: 400 !important; + font-family: var(--font-mono-stack) !important; } /* Section headings (Authorization, Path Parameters, etc.) — consistent top spacing */ @@ -1463,15 +1484,15 @@ html.dark margin-bottom: 0.25rem !important; } -/* Code examples in right column — wrap long lines instead of horizontal scroll */ -#nd-page:has(.api-page-header) pre { - white-space: pre-wrap !important; - word-break: break-all !important; -} -#nd-page:has(.api-page-header) pre code { - width: 100% !important; - word-break: break-all !important; - overflow-wrap: break-word !important; +/* Example-panel code overflows rather than wraps: a wrapped line restarts at + column zero and misreports the JSON nesting depth. */ + +/* fumadocs' own lucide glyphs (heading anchor, copy button) ship at stroke-width + 2 while emcn strokes at 1.55, so they read heavier than everything near them. + Layout-wide on purpose: one icon weight across the docs. Retired once + createAPIPage is given renderHeading/renderCodeBlock. */ +#nd-docs-layout svg[class*="lucide"] { + stroke-width: 1.55; } /* Callout/alert — transparent background, no shadow, hide colored bar, add padding */ @@ -1497,7 +1518,7 @@ div.not-prose.rounded-md.border.bg-fd-card.p-2 { div.rounded-xl.border.bg-fd-card.shadow-md:has(> [role="none"]) > svg { fill: none !important; color: var(--color-fd-foreground) !important; - stroke-width: 1.75 !important; + stroke-width: 1.55 !important; flex-shrink: 0; width: 1rem !important; height: 1rem !important; diff --git a/apps/docs/openapi-v2-billing.json b/apps/docs/openapi-v2-billing.json index ecf30cabc96..f611771391b 100644 --- a/apps/docs/openapi-v2-billing.json +++ b/apps/docs/openapi-v2-billing.json @@ -248,7 +248,7 @@ "type": "apiKey", "in": "header", "name": "X-API-Key", - "description": "Your Sim API key, personal or workspace-scoped. Generate one from the Sim dashboard under Settings > API Keys. A workspace API key is not accepted everywhere: operations that act on behalf of a specific human — administrative reads, secret access, and irreversible or governance-affecting writes — always reject it, whatever role the key carries. Each such operation says so in its own description, and the rejection surfaces as `403` unless the operation conceals unauthorized resources, in which case it is reported as `404`. Use a personal API key for those." + "description": "Your Sim API key, personal or workspace-scoped. Generate one under Settings > API Keys. Operations that reject workspace keys say so in their own description." } }, "headers": { diff --git a/apps/docs/openapi-v2-files-audit.json b/apps/docs/openapi-v2-files-audit.json index 54432ad9883..7e981126eeb 100644 --- a/apps/docs/openapi-v2-files-audit.json +++ b/apps/docs/openapi-v2-files-audit.json @@ -1952,7 +1952,7 @@ "type": "apiKey", "in": "header", "name": "X-API-Key", - "description": "Your Sim API key, personal or workspace-scoped. Generate one from the Sim dashboard under Settings > API Keys. A workspace API key is not accepted everywhere: operations that act on behalf of a specific human — administrative reads, secret access, and irreversible or governance-affecting writes — always reject it, whatever role the key carries. Each such operation says so in its own description, and the rejection surfaces as `403` unless the operation conceals unauthorized resources, in which case it is reported as `404`. Use a personal API key for those." + "description": "Your Sim API key, personal or workspace-scoped. Generate one under Settings > API Keys. Operations that reject workspace keys say so in their own description." } }, "headers": { diff --git a/apps/docs/openapi-v2-knowledge.json b/apps/docs/openapi-v2-knowledge.json index 754dc3ade5c..01ae9282ec0 100644 --- a/apps/docs/openapi-v2-knowledge.json +++ b/apps/docs/openapi-v2-knowledge.json @@ -1954,7 +1954,7 @@ "type": "apiKey", "in": "header", "name": "X-API-Key", - "description": "Your Sim API key, personal or workspace-scoped. Generate one from the Sim dashboard under Settings > API Keys. A workspace API key is not accepted everywhere: operations that act on behalf of a specific human — administrative reads, secret access, and irreversible or governance-affecting writes — always reject it, whatever role the key carries. Each such operation says so in its own description, and the rejection surfaces as `403` unless the operation conceals unauthorized resources, in which case it is reported as `404`. Use a personal API key for those." + "description": "Your Sim API key, personal or workspace-scoped. Generate one under Settings > API Keys. Operations that reject workspace keys say so in their own description." } }, "headers": { diff --git a/apps/docs/openapi-v2-logs.json b/apps/docs/openapi-v2-logs.json index f25b32e5dbb..9ca4c9cb168 100644 --- a/apps/docs/openapi-v2-logs.json +++ b/apps/docs/openapi-v2-logs.json @@ -363,7 +363,7 @@ "type": "apiKey", "in": "header", "name": "X-API-Key", - "description": "Your Sim API key, personal or workspace-scoped. Generate one from the Sim dashboard under Settings > API Keys. A workspace API key is not accepted everywhere: operations that act on behalf of a specific human — administrative reads, secret access, and irreversible or governance-affecting writes — always reject it, whatever role the key carries. Each such operation says so in its own description, and the rejection surfaces as `403` unless the operation conceals unauthorized resources, in which case it is reported as `404`. Use a personal API key for those." + "description": "Your Sim API key, personal or workspace-scoped. Generate one under Settings > API Keys. Operations that reject workspace keys say so in their own description." } }, "headers": { diff --git a/apps/docs/openapi-v2-resources.json b/apps/docs/openapi-v2-resources.json index a1186dc1054..2f03ec3e899 100644 --- a/apps/docs/openapi-v2-resources.json +++ b/apps/docs/openapi-v2-resources.json @@ -2016,7 +2016,7 @@ "type": "apiKey", "in": "header", "name": "X-API-Key", - "description": "Your Sim API key, personal or workspace-scoped. Generate one from the Sim dashboard under Settings > API Keys. A workspace API key is not accepted everywhere: operations that act on behalf of a specific human — administrative reads, secret access, and irreversible or governance-affecting writes — always reject it, whatever role the key carries. Each such operation says so in its own description, and the rejection surfaces as `403` unless the operation conceals unauthorized resources, in which case it is reported as `404`. Use a personal API key for those." + "description": "Your Sim API key, personal or workspace-scoped. Generate one under Settings > API Keys. Operations that reject workspace keys say so in their own description." } }, "headers": { diff --git a/apps/docs/openapi-v2-tables.json b/apps/docs/openapi-v2-tables.json index 809446dc7b9..64093eeed92 100644 --- a/apps/docs/openapi-v2-tables.json +++ b/apps/docs/openapi-v2-tables.json @@ -3666,7 +3666,7 @@ "type": "apiKey", "in": "header", "name": "X-API-Key", - "description": "Your Sim API key, personal or workspace-scoped. Generate one from the Sim dashboard under Settings > API Keys. A workspace API key is not accepted everywhere: operations that act on behalf of a specific human — administrative reads, secret access, and irreversible or governance-affecting writes — always reject it, whatever role the key carries. Each such operation says so in its own description, and the rejection surfaces as `403` unless the operation conceals unauthorized resources, in which case it is reported as `404`. Use a personal API key for those." + "description": "Your Sim API key, personal or workspace-scoped. Generate one under Settings > API Keys. Operations that reject workspace keys say so in their own description." } }, "headers": { diff --git a/apps/docs/openapi-v2-workflows.json b/apps/docs/openapi-v2-workflows.json index e71582276f2..1d9df284ce8 100644 --- a/apps/docs/openapi-v2-workflows.json +++ b/apps/docs/openapi-v2-workflows.json @@ -2048,7 +2048,7 @@ "type": "apiKey", "in": "header", "name": "X-API-Key", - "description": "Your Sim API key, personal or workspace-scoped. Generate one from the Sim dashboard under Settings > API Keys. A workspace API key is not accepted everywhere: operations that act on behalf of a specific human — administrative reads, secret access, and irreversible or governance-affecting writes — always reject it, whatever role the key carries. Each such operation says so in its own description, and the rejection surfaces as `403` unless the operation conceals unauthorized resources, in which case it is reported as `404`. Use a personal API key for those." + "description": "Your Sim API key, personal or workspace-scoped. Generate one under Settings > API Keys. Operations that reject workspace keys say so in their own description." } }, "headers": { diff --git a/apps/sim/lib/api/contracts/v2/openapi/shared.ts b/apps/sim/lib/api/contracts/v2/openapi/shared.ts index a2de98da422..cb376ef7039 100644 --- a/apps/sim/lib/api/contracts/v2/openapi/shared.ts +++ b/apps/sim/lib/api/contracts/v2/openapi/shared.ts @@ -144,7 +144,7 @@ export const V2_API_KEY_SECURITY_SCHEMES = { in: 'header', name: 'X-API-Key', description: - 'Your Sim API key, personal or workspace-scoped. Generate one from the Sim dashboard under Settings > API Keys. A workspace API key is not accepted everywhere: operations that act on behalf of a specific human — administrative reads, secret access, and irreversible or governance-affecting writes — always reject it, whatever role the key carries. Each such operation says so in its own description, and the rejection surfaces as `403` unless the operation conceals unauthorized resources, in which case it is reported as `404`. Use a personal API key for those.', + 'Your Sim API key, personal or workspace-scoped. Generate one under Settings > API Keys. Operations that reject workspace keys say so in their own description.', }, } as const satisfies Readonly>