feat(api): public API plan gating, docs auth, and dashboard snippets (#701)
* fix(automation): align public API plan gating across cloud and self-hosted Add shared canUsePublicApi helper so cloud allows Early Adopter and Enterprise while self-hosted requires Enterprise. Update the API key dashboard page and backend key creation checks to use the same rules. Co-authored-by: Rotimi Best <[email protected]> * docs(api): document bearer auth on public API reference Add shared OpenAPI enrichment with bearerAuth security scheme and authentication instructions. The interactive reference now loads an enriched spec with Authorize support, and the API guide explains how to create and use org API keys. Co-authored-by: Rotimi Best <[email protected]> * feat(dashboard): add API quick-start code snippets on automation page Mirror the MCP client setup section with cURL, JavaScript, and Python examples that show how to authenticate public API requests with org keys. Co-authored-by: Rotimi Best <[email protected]> * ci(openapi): republish spec when public API OpenAPI helpers change Co-authored-by: Rotimi Best <[email protected]> * feat(dashboard): add Go snippet to API quick-start examples Co-authored-by: Rotimi Best <[email protected]> * docs(api): use /org/*/api and clarify dashboard key generation path Co-authored-by: Rotimi Best <[email protected]> * fix(api): escape backticks in OpenAPI description template literal Greptile flagged that unescaped backticks around * in PUBLIC_API_OPENAPI_DESCRIPTION evaluated to NaN and dropped auth docs from the Scalar spec. Also use plan-specific snackbar message on upgrade. Co-authored-by: Rotimi Best <[email protected]> --------- Co-authored-by: Cursor Agent <[email protected]> Co-authored-by: Rotimi Best <[email protected]>
This commit is contained in:
co-authored by
Rotimi Best
Cursor Agent
parent
447e54b1f4
commit
fe9f8c441f
@@ -0,0 +1,89 @@
|
||||
export const PUBLIC_API_BASE_URL = 'https://api.classroomio.com/public-api/v1';
|
||||
export const PUBLIC_API_OPENAPI_URL = 'https://api.cdn.clsrio.com/openapi/public-api/openapi-latest.json';
|
||||
export const PUBLIC_API_BEARER_SCHEME = 'bearerAuth';
|
||||
|
||||
const HTTP_METHODS = ['get', 'post', 'put', 'patch', 'delete', 'options', 'head'] as const;
|
||||
|
||||
export const PUBLIC_API_OPENAPI_DESCRIPTION = `# Authentication
|
||||
|
||||
All public API endpoints require an **organization-scoped API key** sent as a Bearer token.
|
||||
|
||||
## Get an API key
|
||||
|
||||
1. Sign in to [ClassroomIO](https://app.classroomio.com) as an **organization admin**.
|
||||
2. In the org sidebar, open the **Automation** section, then **API** ([/org/*/api](https://app.classroomio.com/org/*/api) — \`*\` picks your current organization automatically).
|
||||
3. Click **Generate API key** and copy the secret immediately (it is shown only once).
|
||||
4. Keys look like \`cio_api_...\` and include the \`public_api:*\` scope.
|
||||
|
||||
## Send requests
|
||||
|
||||
Add the key to every request:
|
||||
|
||||
\`\`\`
|
||||
Authorization: Bearer cio_api_your_key_here
|
||||
\`\`\`
|
||||
|
||||
Base URL: \`${PUBLIC_API_BASE_URL}\`
|
||||
|
||||
## Try requests in this reference
|
||||
|
||||
Use the **Authorize** button (lock icon) on this page, choose **bearerAuth**, paste your full API key, then run **Try it** on any endpoint.
|
||||
|
||||
## Plan access
|
||||
|
||||
On ClassroomIO Cloud, API keys are available on **Early Adopter** and **Enterprise** plans. Self-hosted deployments require **Enterprise**.
|
||||
`;
|
||||
|
||||
type OpenApiDocument = Record<string, unknown>;
|
||||
|
||||
function applySecurityToOperations(paths: Record<string, unknown>) {
|
||||
for (const pathItem of Object.values(paths)) {
|
||||
if (!pathItem || typeof pathItem !== 'object') {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const method of HTTP_METHODS) {
|
||||
const operation = (pathItem as Record<string, unknown>)[method];
|
||||
|
||||
if (!operation || typeof operation !== 'object') {
|
||||
continue;
|
||||
}
|
||||
|
||||
(operation as Record<string, unknown>).security = [{ [PUBLIC_API_BEARER_SCHEME]: [] }];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function enrichPublicApiOpenApiSpec<T extends OpenApiDocument>(spec: T): T {
|
||||
const components = (spec.components ?? {}) as Record<string, unknown>;
|
||||
const securitySchemes = (components.securitySchemes ?? {}) as Record<string, unknown>;
|
||||
const paths = (spec.paths ?? {}) as Record<string, unknown>;
|
||||
const info = (spec.info ?? {}) as Record<string, unknown>;
|
||||
|
||||
applySecurityToOperations(paths);
|
||||
|
||||
return {
|
||||
...spec,
|
||||
info: {
|
||||
...info,
|
||||
title: typeof info.title === 'string' ? info.title : 'ClassroomIO Public API',
|
||||
version: typeof info.version === 'string' ? info.version : '1.0.0',
|
||||
description: PUBLIC_API_OPENAPI_DESCRIPTION
|
||||
},
|
||||
paths,
|
||||
components: {
|
||||
...components,
|
||||
securitySchemes: {
|
||||
...securitySchemes,
|
||||
[PUBLIC_API_BEARER_SCHEME]: {
|
||||
type: 'http',
|
||||
scheme: 'bearer',
|
||||
bearerFormat: 'API Key',
|
||||
description:
|
||||
'Organization API key from Automation → API in your org dashboard. Paste the full `cio_api_...` value as the Bearer token.'
|
||||
}
|
||||
}
|
||||
},
|
||||
security: [{ [PUBLIC_API_BEARER_SCHEME]: [] }]
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user