Bulk-check 113 API key formats against real provider auth endpoints.
Your browser · your GitHub Actions runner · zero third-party backend.
You rotated a batch of keys. Or inherited a .env graveyard. Or need a pre-deploy sanity check across OpenAI, Anthropic, Gemini, Stripe, Supabase, and thirty other services.
Most "key checkers" want your secrets on their server.
akv does not.
your keys --> your browser --> your fork's Actions runner --> provider APIs
| |
+---- localStorage PAT --+
(never our backend -- there isn't one)
| Auto-detect | 113 regex-backed formats: sk-proj-..., sk-ant-..., AIza..., xai-..., gsk_... |
| Real auth pings | Cheap authenticated endpoints (models list, whoami, credits) -- not fake format checks |
| Clear verdicts | valid · invalid · rate_limited · error + HTTP status + latency + response snippet |
| Masked everywhere | UI and results store sk-proj...abcd only -- full keys never written back |
| CSV export | One click after a run |
| Hard ceiling | Up to 500 keys per run, parallelized on the runner |
| Zero backend | Static SPA on GitHub Pages + one workflow on your fork |
1. Open api-key-validator.bossincrypto.dev
3. Create a fine-grained PAT limited to that fork:
| Permission | Access |
|---|---|
| Actions | Read and write |
| Contents | Read and write |
| Metadata | Read (automatic) |
4. In the app: paste owner / repo / token → Connect
(stored only in localStorage)
5. Paste keys → Validate
Cold starts usually land in 15–40s.
Tip: for production-grade keys, use a short-lived PAT on a private fork.
sequenceDiagram
participant U as Browser
participant G as GitHub API
participant R as Actions runner
participant P as Provider APIs
U->>U: parse · dedupe · detect
U->>G: repository_dispatch (PAT)
G->>R: validate-keys workflow
R->>P: auth ping per key
P-->>R: 2xx / 401 / 429 / ...
R->>G: commit masked JSON on results
U->>G: poll results/run_id.json
G-->>U: verdicts + latency
- SPA parses the paste, dedupes lines, matches each key to a provider.
- Your PAT fires
repository_dispatch→validate-keysworkflow. - Runner (
scripts/validate.mjs) batches requests (15s timeout each). - Masked JSON lands on the orphan
resultsbranch (files older than 24h pruned). - SPA polls the Contents API until the run file appears.
Deploy path is separate: every push to main rebuilds the SPA and ships it to Pages automatically.
Requires Bun.
bun install
bun dev # http://localhost:8080
bun run build # → dist/
bun run preview # serve production buildNo VITE_* secrets for the Actions validation path.
| Script | Purpose |
|---|---|
bun dev |
Vite dev server |
bun run build |
Production bundle |
bun run preview |
Local prod preview |
bun run lint |
ESLint |
OpenAI · Anthropic · Google Gemini · xAI (Grok) · Groq · Mistral · DeepSeek · OpenRouter · Perplexity · Cohere · Together · Fireworks · Cerebras · Novita · Anyscale · Hugging Face · Replicate · NVIDIA · GitHub Models · Hyperbolic · SambaNova · AI21 · Friendli · GLHF · Zhipu
ElevenLabs · AssemblyAI · Deepgram · Cartesia · Stability · Runway · Luma · Twelve Labs
Voyage · Jina · Nomic · Pinecone · Exa · Tavily · Brave Search · Firecrawl
Supabase · Neon · Netlify · Render · Sentry · New Relic · Databricks · Snyk · Modal · Baseten · Runpod · Fal · Segmind · DataStax · Trigger.dev · Xata · Buildkite · CircleCI · Docker Hub · npm · GitLab · Bitbucket · LaunchDarkly · Statsig · Honeybadger
Resend · SendGrid · Brevo · MailerSend · Courier · Notion · Linear · Airtable · HubSpot · Stripe · Discord · Intercom · Klaviyo · Contentful · Cal.com · Asana · ClickUp · Figma · Dropbox · Typeform · Twitter/X · Pushbullet · Modrinth
DeepL · PostHog · LangSmith · Langfuse · Helicone · Portkey · Browserbase · Apify · OpenPipe · PromptLayer · ScrapingBee · Scrapfly · Mem0 · Tinybird · CoinGecko · AbuseIPDB · Pexels · Pixabay · WolframAlpha · IPinfo · CurrencyAPI · Duffel · Leonardo
Registries (keep in sync when adding providers):
| File | Role |
|---|---|
src/lib/providers.ts |
UI detection (keyPattern) + labels |
scripts/providers.mjs |
Runner HTTP specs |
Two files. Distinctive prefix. Cheapest auth-looking endpoint that returns 2xx vs 401/403.
// src/lib/providers.ts — detection + UI
{
id: "acme",
name: "Acme",
keyPattern: /^acm_[A-Za-z0-9]{32,}$/,
// ...
}// scripts/providers.mjs — runner call
acme: { m: "GET", u: "https://api.acme.com/v1/me", h: "Authorization" },Open an issue with Request provider if you want something added for you.
| Surface | Behavior |
|---|---|
| SPA | Full keys only live in memory for the run; display is masked |
| PAT | Browser localStorage only — never sent to us (no us) |
| Runner | Keys used for outbound provider calls; results store masked keys |
results branch |
Auto-pruned after 24h |
| Analytics | None |
Treat this as a diagnostic tool, not a vault. Rotate anything you validated on infra you do not fully control. Prefer a short-lived fine-grained PAT on a private fork for production keys.
| Layer | Tech |
|---|---|
| UI | React 19 · TypeScript 5 · Tailwind 4 |
| Build | Vite 7 · Bun |
| Runtime | GitHub Actions (validate-keys) |
| Hosting | GitHub Pages · custom domain |
| Workflow | Trigger | What it does |
|---|---|---|
deploy.yml |
push main / manual |
Build SPA → Pages |
validate-keys.yml |
repository_dispatch |
Validate keys → results branch |
https://api-key-validator.bossincrypto.dev
| Type | Host | Answer |
|---|---|---|
CNAME |
api-key-validator |
bossincrypto.github.io |
Fallback: https://bossincrypto.github.io/api-key-validator/
.
├── .github/workflows/ # Pages deploy + key validation
├── scripts/ # Runner: validate.mjs + providers.mjs
├── src/
│ ├── components/ # Setup, Validator, Results, provider list
│ └── lib/ # detect, dispatch, mask, providers
├── public/
│ ├── CNAME
│ ├── favicon.svg
│ └── favicon.ico
└── package.json
MIT — use it, fork it, audit it.
Built for operators who rotate keys faster than they inventory them.