Authentication
Send the key as an HTTP Bearer token. Full secrets are displayed only when created or rotated.
Authorization: Bearer 9k_live_...9000INC developer platform
Read privacy-safe aggregate analytics from 9000INC products without exposing private account, payroll, invoice, support-content, raw Discord identity, or server-statistics data.
Chart studio
Try the chart styles with sample data, or load a public dataset using your scoped API key. Live requests use your normal API quota and the key ownerβs website theme.
The key is sent only in the Authorization header to this website. It is not saved by this preview or included in downloads.
Preparing sample chartβ¦
Send the key as an HTTP Bearer token. Full secrets are displayed only when created or rotated.
Authorization: Bearer 9k_live_...The public API is versioned in the URL. Public endpoints use /api/v1/analytics/.... Existing internal/admin analytics routes remain separate.
Datasets
| Dataset | Endpoint | Required scope |
|---|---|---|
| Platform overview | /api/v1/analytics/platform | analytics:platform |
| Game downloads | /api/v1/analytics/game-downloads | analytics:downloads |
| Advertising | /api/v1/analytics/ads | analytics:ads |
| Giveaways | /api/v1/analytics/giveaways | analytics:giveaways |
| Games | /api/v1/analytics/games | analytics:games |
| Login geography | /api/v1/analytics/login-geography | analytics:geography |
Date filters: ?unit=days&amount=30. Public v1 accepts days (max 365), weeks (max 52), or months (max 24). Login geography instead uses ?month=YYYY-MM&granularity=city|region|country and retains the existing privacy threshold.
curl -H "Authorization: Bearer $NINEK_API_KEY" \
"https://9000inc.com/api/v1/analytics/platform?unit=days&amount=30"
const response = await fetch(
'https://9000inc.com/api/v1/analytics/platform?unit=days&amount=30&include_charts=1',
{ headers: { Authorization: `Bearer ${process.env.NINEK_API_KEY}` } }
);
if (!response.ok) throw new Error(`Analytics request failed: ${response.status}`);
const { data, charts, presentation } = await response.json();
Add include_charts=1 to any dataset endpoint to receive chart_schema: "9000inc.chart.v1", a charts array, and the API key ownerβs resolved presentation. Existing authentication, privacy filtering, and quotas apply once to the request. Omitting this option keeps the original data response.
Each chart contains its title, labels, numeric series, display, format, range, and coverage. Models contain only data already released by that public dataset. Underlying collection limits still apply; login geography includes only groups released by its existing privacy threshold.
The same renderer used by the website and Discord is available at /analytics/chart-renderer.js. It exports window.NineKCharts in a browser and a CommonJS module in Node. Load it, then render a model:
const scene = NineKCharts.render(charts[0], {
width: 1280, height: 720, theme: presentation
});
// scene.svg is the exportable SVG source.
// scene.model is the normalized chart model.
Use the preview above for SVG, PNG, and chart JSON downloads. PNG is rendered in your browser from the same SVG. The public API does not expose private Discord server charts or require an npm package.
Scopes
analytics:platformanalytics:downloadsanalytics:adsanalytics:giveawaysanalytics:gamesanalytics:geographyQuotas
| Membership | Per minute | Per day |
|---|---|---|
| Free | 30 | 500 |
| Basic | 90 | 5,000 |
| Premium | 180 | 25,000 |
| Pro | 360 | 100,000 |
Rate-limit information is returned in response headers and the JSON envelope. Quotas are account-wide across all keys, enforced with an atomic account reservation before dataset generation, and membership changes automatically change the active quota without regenerating a key. Rate-limited requests do not extend the lockout window.
Keys can be limited to specific datasets, edited later, rotated without changing their scopes, or revoked immediately. Rotation invalidates the previous secret as soon as the new one is issued.
X-RateLimit-Plan, minute/day limit and remaining values, minute/day reset Unix timestamps, and Retry-After on throttled responses are available for client backoff.
Rejected requests return a stable error_code such as missing_api_key, invalid_or_revoked_api_key, scope_denied, rate_limit_exceeded, or quota_accounting_busy, alongside a human-readable message.
The public API intentionally excludes raw account IDs, emails, support message content, wallet transactions, invoices, Teams payroll, private room/player identifiers, raw Discord user/server/channel identifiers, and internal server statistics. Login geography keeps the existing distinct-user suppression threshold. Advertising exposes only the verified event ledger created in Patch 674.