API Keys (unified key hub)
API Keys is the single Agent Tools sidebar row that holds everything key-related: the My API Keys tab for a personal gateway key, and the Stored Keys tab inventorying every key and secret Omniscio can see — names and metadata only, never the values.
What it is
API Keys is the single Agent Tools sidebar row that holds everything key-related, behind two tabs:
- My API Keys — your personal gateway key for your own automations (generate / copy /
regenerate a
jls_sk_key, see your pre-paid credit balance, the available APIs, and a copy-paste usage example). - Stored Keys — a read-only inventory of every API key and secret Omniscio can see, grouped by where it lives (names + metadata only, never the values).
The two used to be separate sidebar rows ("My API Keys" + "Stored Keys") with near-identical key icons stacked together, which read as a confusing duplicate. They merged into one API Keys row on 2026-06-21. Nothing about how keys are stored, shown, or secured changed — this was a navigation/layout cleanup. Each tab is the exact panel it always was, rendered verbatim.
Where to find it
Where it is
Agent Tools → API Keys in the sidebar — the last child row under the Agent Tools group, after CLI Tools, Skills, and MCP Servers. Opening it shows a tab strip; the My API Keys tab is active by default.
The My API Keys feature is also still reachable as its own Settings → My API Keys section (same component, unchanged) — only the duplicated sidebar rows were merged. There is no Settings section for Stored Keys (it left Settings → Maintenance for the sidebar on 2026-06-01).
How it behaves
Tab 1 — My API Keys (personal gateway key)
Gives each Omniscio user a personal API key so their own scripts/automations can call a pool of AI/LLM APIs through Omniscio's shared keys — without signing up for each provider. You use the pooled keys; usage is metered and billed to your pre-paid credit balance at a flat surcharge. A separate, opt-in surface — it does NOT change how Claude Code sessions, the active account, or any provider you've connected behave.
The panel has four parts:
- Credits remaining — your pre-paid balance (e.g.
$4.50). At$0.00— or when the balance can't be verified — pooled-key creation is blocked fail-closed (you can't mint a key that would immediately be declined), with a Refresh balance control to retry; calls are likewise declined until credits are added (granted manually in v1). - Your key — one of three states: not signed in → Sign in with Google; no key yet →
Generate API key — shown to any signed-in user with confirmed credits (the mint opened to
all signed-in users on 2026-08-24 — previously Pro-only); without credits, an add-credits /
use-your-own-OpenRouter-key recovery message, never a dead button that mints into a declined state
(an Upgrade to Pro prompt now appears only if the capability is ever re-gated); have a key →
the key's prefix (
jls_sk_abc…) plus Regenerate (disabled without confirmed credits) / Revoke. The full key is shown only once, right after you generate it ("copy now — you won't see it again"); after that only the prefix is shown. - Available APIs — what you can call through the key. LLMs today: Claude, GPT, Groq, DeepSeek. Plus read-only Twitter / X (search + tweet/user lookups, billed per tweet returned). And the first two non-LLM APIs on the config-driven REST engine — Firecrawl (web scraping + crawling) and Apify (run scraper actors) — billed at the provider's reported usage with a per-job spend cap. Each non-default API is live once its gateway secret is deployed.
- How to use it — the gateway base URL and a copy-paste
curlexample.
Point any OpenAI-compatible client at <gateway base URL>/v1/<api> with
Authorization: Bearer <your key>. The gateway swaps in the real provider key, forwards the
request, and bills your credits at cost + a flat surcharge. The key is long-lived (unlike your
hourly sign-in token), so an unattended automation (e.g. a 3am job) can use it. Shown once,
never stored in the clear (the gateway keeps only a one-way fingerprint); lost it → Regenerate.
Scoped + safe — a key spends only your balance and is revocable instantly. One active key
per user in v1.
Tab 2 — Stored Keys (key/secret inventory)
A searchable, read-only inventory of every key/secret Omniscio can see, grouped into four sources:
Windows DPAPI vault (~/.claude/secrets/*.enc, by filename), Omniscio provider API keys (xAI,
Groq, Deepgram, ElevenLabs, Speechify, Pika, OpenAI, Fish Audio, Picovoice, Pushbullet), Claude accounts, and
automation credentials. Each row shows the name, a type label, and a last-updated
date where one is recorded. A source with nothing in it is omitted.
Every row can be removed (confirmation-gated); "change the value" routes per source — vault
secrets get inline add/replace (re-encrypted with DPAPI) + a reversible move-to-trash delete with
Undo; provider keys clear-only; Claude accounts / automation credentials delete inline or
Manage → their Settings editor. Deleting an Omniscio-critical vault secret (e.g. amc-cli)
requires typing its name.
The safety rule (never-decrypt)
The panel can never expose a stored secret value — structural, not a convention:
KeyInventoryEntryhas novalue/secret/ciphertextfield — onlyid,name,source,typeLabel,lastUpdated.- The vault reader lists
.encfilenames only; deleting moves the encrypted file without opening it. Provider keys are reported present-or-not; clearing only blanks the field. Accounts / automation creds come from already-credential-stripped metadata. - Editing only ever sends a NEW value you type (renderer → main); a stored value is never read back to the screen.
For agents
For AI agents
- Sidebar surface: the
api-keysintegration manifest (integrations/api-keys.ts,parentGroupId: 'agent-tools') + theAPI_KEYS_PROJECT_ID(__api_keys__) virtual project. The panel KeysView.tsx is a thin tab shell (panelOwnsLayout, NON-spawnable) that renders the two EXISTING panels verbatim — neither feature's logic is touched by the merge. It sorts last among the Agent Tools children via theamcDisplayOrderKeyoverride ('API Keys' → 'Skills~') — see agent-tools-contract.md. - My API Keys tab → MyApiKeysPanel.tsx
wraps the reused ApiKeysSettings.tsx
(ONE component, two mount points: this tab + Settings → My API Keys). Main: the
bundled-api:key-mint/key-list/key-revoke/balanceIPC handlers in bundled-api-handlers.ts call the gateway with the user's Firebase ID token, Zod-validate the reply, and humanize errors. Gateway source now lives in this repo atgateway/(a self-contained Cloud Run service, deployed in the shares project) —/v1/keys,/v1/balance,/v1/<provider>.- Gateway authorization (the allowlist) — Omniscio is the sole populator. After the Firebase
token verifies, every gateway request (even just listing keys) must clear a Firestore
authorizedUsers/{email}allowlist (authorized: true) in the shares project.globalAuthProfile.getOrCreateProfile(admin-functions.ts) upserts the caller on every sign-in (gated on!disabled), so a signed-in user is auto-authorized — do not remove that write or a valid login 401s ("could not be verified") on this screen even though the login is fine. - Truthful 401s. On a gateway 401/403, bundled-api-handlers.ts
re-verifies the token LOCALLY first: a still-valid token ⇒ server-side fault ⇒ "couldn't
authorize your account … try again shortly", NOT "sign out and back in" (shown only when the
token genuinely fails to verify). The status probe treats any non-5xx gateway response as
reachable (the gateway has no
/healthroute, so it 404s — still proof it is up).
- Gateway authorization (the allowlist) — Omniscio is the sole populator. After the Firebase
token verifies, every gateway request (even just listing keys) must clear a Firestore
- Non-LLM APIs (Firecrawl / Apify) ride a config-driven REST engine. Beyond the pooled LLMs + X,
the gateway serves plain REST APIs from a per-provider CONFIG object — no new code per API.
rest-providers.ts declares the base URL, auth style, a
default-deny
(method, path)allow-list, and a per-route billing rule; ONE generic forwarder (rest-provider.ts) serves them all. It handles sync calls AND async job lifecycles (start → poll → fetch) with usage pass-through billing: a hold reserved on start, settled once by job id on a terminal poll, every charge clamped to a per-job spend ceiling. Each provider is secret-gated (noFIRECRAWL_API_KEY/APIFY_API_TOKEN→ the row 404s). Adding a non-LLM API is one entry in the credit-vendor registry plus its secret — the gateway's config and its registration are both derived from that entry, and a key field appears only if the user supplies the secret. READ gateway-rest-provider-contract.md before touching it or adding a provider. - Stored Keys tab → StoredKeysPanel.tsx.
Read:
secrets:key-inventory-list(returnsKeyInventoryEntry[]). Write (all write-only — never return a stored value):secrets:vault-set/secrets:vault-delete(returns atrashIdfor undo) /secrets:vault-restore, andsecrets:provider-key-clear(clear-only). Account / automation deletes reuseaccount:remove/automation:credential-delete. Invariant + enforcing tests: key-inventory-contract.md. - Existing installs that had the two old rows get the orphan
__stored_keys__+__my_api_keys__virtual-project rows soft-deleted by a one-time migration (the startup seeder only ever ADDS rows, never prunes).
Related
See also
- INDEX.md
- agent-tools.md — the parent sidebar group
- model-vendors.md — coding sessions on DeepSeek, GLM, Kimi, MiniMax, Meta, Qwen and OpenRouter can ALSO draw down this prepaid balance: the Omniscio credits row of each family's supply list (Settings → Accounts → Who pays & who serves) runs them on the company key through the gateway, no personal key needed
- glm-provider.md — GLM's credits row (Pro plan)
- openrouter-provider.md — OpenRouter's credits row — ungated (any signed-in user, no Pro tier), covering every model OpenRouter serves (~400), priced live through the gateway at a 10% markup
Last verified 2026-09-29