Skip to main content

CleanLibrary API Key Onboarding

Audience: Early-access customers

1. Quick start​

CleanLibrary's customer-verdict endpoint at https://cleanapp.clnstrt.dev authenticates requests with a Bearer token issued to your organization by CleanStart. Set it as an environment variable and pass it on each request:

curl -sH "Authorization: Bearer $CLEANLIB_API_KEY" \
https://cleanapp.clnstrt.dev/v1/customer/verdicts/npm/cors/2.8.4 | jq

To request an early-access token, contact CleanStart at cto.office@cleanstart.com.

1.5 Install the tooling​

The customer surfaces are published to standard registries — no sideload or git-clone required.

SurfaceInstall
VS Code extensionSearch "CleanLibrary" in the VS Code Extensions view (Cmd+Shift+X / Ctrl+Shift+X) → Install. Or CLI: code --install-extension cleanstart.cleanlibrary
MCP server (Claude Desktop / Cursor / Windsurf / Cline)pip install cleanlib-mcp-server (LIVE on PyPI). Then point your MCP client config at the installed entry point + set CLEANLIB_ENDPOINT + CLEANLIB_API_KEY env vars
Python SDKpip install cleanlib-sdk
Go SDKgo get pkg.clnstrt.dev/cleanlib-sdk-go
JS/TS SDKnpm install @cleanstart/cleanlib-sdk
CLI cleanlibDistributed as a statically-linked binary (Rust); install path per release artifacts

After installing, configure each surface with your Bearer token per the matrix below.

1.6 Batch scanning — POST /v1/scan​

Resolve verdicts for many coordinates in a single request. POST a packages array, each entry {ecosystem, package, version}:

curl -sH "Authorization: Bearer $CLEANLIB_API_KEY" \
-H "Content-Type: application/json" \
-X POST https://cleanapp.clnstrt.dev/v1/scan \
-d '{
"packages": [
{"ecosystem": "npm", "package": "cors", "version": "2.8.4"},
{"ecosystem": "pypi", "package": "requests", "version": "2.31.0"}
]
}' | jq

The response is a results array (one entry per requested package, order preserved) plus a coverage summary. Each result echoes its ecosystem / package / version and carries the same customer-verdict fields as the single-package endpoint — customer_state, state, source_state, reason_class, and (when applicable) remediation:

{
"results": [
{
"ecosystem": "npm", "package": "cors", "version": "2.8.4",
"customer_state": "clean", "state": "ALLOWED", "source_state": "ALLOWED_NO_FINDINGS"
},
{
"ecosystem": "pypi", "package": "requests", "version": "2.31.0",
"error": "…"
}
],
"coverage": { "…": "per-scan coverage summary" }
}

Partial success: one bad coordinate never fails the batch. A package that cannot be resolved carries an error string on its own result entry while every other package still returns its verdict. A well-formed request returns HTTP 200; inspect each entry for its per-package outcome.

Attestation: batch results carry an attestation_status field but no per-package signed cosign object — call the single-package endpoint (/v1/customer/verdicts/{ecosystem}/{package}/{version}) when you need the full signed attestation.

Rate limits (§1.7) apply to the /v1/scan request as a whole, not per package.

1.7 Rate limits & 429 responses​

Requests are rate-limited per (organization-tier, route). Every response carries X-RateLimit-Limit (the sustained per-minute ceiling) and X-RateLimit-Reset (the 60-second window). X-RateLimit-Remaining is intentionally not sent — the limiter keeps no faithful remaining-token count, and an approximate value would mislead a self-throttling client.

When you exceed the quota the response is HTTP 429 with a Retry-After: <seconds> header and the body below. Note that error is a nested object (matching the 401 shape), with retry_after_seconds and tier as siblings — not a flat string:

{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded for tier <Tier>; retry after <n> seconds",
"request_id": "…"
},
"retry_after_seconds": <n>,
"tier": "<Tier>"
}

Back off using Retry-After (or the equivalent retry_after_seconds) rather than retrying immediately; both carry the same window.

2. Configuration matrix​

SurfaceHow to configureNotes
VS Code extensionRun CleanLibrary: Set API Key from the Command Palette (Cmd+Shift+P) — stored in OS keychain via VS Code SecretStorage (v0.1.3+). Set cleanlib.endpoint: https://cleanapp.clnstrt.dev in SettingsThe cleanlib.apiKey setting is DEPRECATED (auto-migrated to keychain on activation). 4-state status bar shows connection mode (cyan LIVE_CONNECTED / amber LIVE_WITH_FALLBACK / red ERROR / gray NOT_CONFIGURED); falls back to local fixtures if no key set
Python SDKCleanlibClient(endpoint="https://cleanapp.clnstrt.dev", api_key="clk_poc_...")See sdk-py README
Go SDKcleanlibsdk.NewClient("https://cleanapp.clnstrt.dev", cleanlibsdk.WithAPIKey("clk_poc_..."))See sdk-go README
JS/TS SDKnew CleanlibClient("https://cleanapp.clnstrt.dev", { apiKey: "clk_poc_..." })See sdk-js README
MCP server (Claude Desktop / Cursor / Windsurf / Cline)Set CLEANLIB_ENDPOINT + CLEANLIB_API_KEY env vars in your MCP client configSee cleanlib-mcp-server README
CLI cleanlib~/.config/cleanlib/config.toml with endpoint = "..." + api_key = "..."Or CLEANLIB_ENDPOINT + CLEANLIB_API_KEY env
Raw curl-H "Authorization: Bearer <key>"Examples throughout POC walkthroughs

3. Phase 1 (GA) production key provisioning — forthcoming​

At Phase 1 General Availability, CleanLibrary will provision per-customer-organization API keys via CDP (Customer Data Platform) admin UI. Each customer organization gets:

  • A unique organization_id (UUID; one per customer)
  • One or more API keys scoped to that organization_id
  • Per-org rate limits (Phase 1 baseline: 100/min, 1000/h, 10000/d — scales per commercial tier)
  • Per-org policy assignment + verdict-API access

During early-access evaluation, CleanStart issues your organization a token directly; the self-service CDP provisioning flow above arrives at General Availability.

4. Key rotation + security​

  • Treat your API token as a secret: store it in a secret manager, never commit it
  • To rotate or revoke a token during early-access, contact CleanStart

For Phase 1 GA + commercial deployment:

  • Keys rotated via CDP admin UI (forthcoming)
  • Recommend storing in your environment's secret manager (GCP Secret Manager, AWS Secrets Manager, HashiCorp Vault, etc.) — never inline in source or commits
  • API keys must be fetched at runtime — never baked into images or committed to source

5. Cosign attestation chain (read-only)​

Every artifact CleanLibrary serves carries a cosign attestation signed with CleanStart's current cosign attestation signing key. The attestation binds verdict_id, policy_decision, risk_acceptance_status, app_version, and served_at, so your compliance team can verify provenance and extract it as SBOM material.

Verify against the published key CleanStart provides — do not assume a key identity. Contact CleanStart at cto.office@cleanstart.com for the current published verification key and cosign verify instructions.

6. Troubleshooting​

SymptomLikely causeResolution
401 Unauthorized from /v1/customer/verdicts/...Missing Authorization headerAdd -H "Authorization: Bearer ..."
404 Not Found with JSON body {"error":"verdict_not_found",...}Package version not in the current evaluation setTry one of the 4 anchor packages (cors/helmet/dotenv/oracledb) with documented versions
404 Not Found with HTML bodyCloud Run reachability issueCheck https://cleanapp.clnstrt.dev/health returns 200 + JSON
Connection refused / TLS errorCert provisioning or DNS issue (rare)Contact onboarding
SDK / extension stuck loadingEndpoint mis-configured (typo or http vs https)Verify endpoint is https://cleanapp.clnstrt.dev exactly

7. Support​

8. What's next (post Phase 1 GA)​

  • Per-customer-organization key provisioning via CDP admin UI
  • Self-service key rotation
  • Tiered rate limits by plan
  • API key scopes (read-only verdict vs write-policy vs admin)
  • OAuth flow for IDE extensions