Getting started
Authentication
Two layers: your app authenticates with OAuth client credentials; your end users authenticate with email + password (and optional TOTP) and carry a session token.
Get your credentials
Before any token exchange you need a client_id and client_secret. Request access, and once an operator approves you'll get a one-time link to retrieve them.
- Submit the Request access form with your company, contact email, and intended use.
- An operator provisions your network identity and approves the request (manual review).
- You receive an email with a one-time link that reveals your
client_idandclient_secret— the secret is displayed once, so store it in your secret manager. - Put them in this app's env as
HSC_CLIENT_IDandHSC_CLIENT_SECRET(see Quickstart).
Why approval is manual
entity_hotkey that is minted out-of-band on Bittensor. We provision that first, then approve your request and issue OAuth credentials scoped to your tenant./v2/apps/meConfirm which tenant a key resolves to and which scopes it has. The secret is never returned — rotate it in the admin console if lost.
{
"app_id": "app_...",
"slug": "company-a",
"name": "Company A",
"entity_hotkey": "5ABC...",
"allowed_scopes": ["api"],
"active": true
}/v2/apps/meRuns live against your environment using the app's server-side credentials and your session. Sign in to the dashboard first for authenticated reads.
App token (OAuth client credentials)
Exchange your client_id/client_secret for a short-lived bearer token. Do this server-side only — never expose the secret to the browser.
/v2/oauth/tokengrant_type | string | required | "client_credentials" |
client_id | string | required | Your app's client id (hsc_…) |
client_secret | string | required | Your app's secret (hsk_…) |
scope | string | optional | Defaults to "api" |
curl -X POST http://localhost:8000/v2/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "client_credentials",
"client_id": "hsc_...",
"client_secret": "hsk_...",
"scope": "api"
}'{
"access_token": "eyJhbGciOiJI...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "api"
}Server-side only
lib/hsc/client.ts on the server, which caches the token automatically.End-user sessions
Once your app is authenticated, you create and authenticate the people who use it. A successful signup verification or login returns a session_token to send as X-Session-Token on subsequent calls.
/v2/auth/signup{ "email": "trader@example.com", "password": "correct horse battery staple" }{
"user_id": "usr_...",
"email": "trader@example.com",
"email_verified": false,
"otp_sent": true
}/v2/auth/verify-email{ "email": "trader@example.com", "code": "123456" }{
"user_id": "usr_...",
"email": "trader@example.com",
"email_verified": true,
"session_token": "sess_...",
"session_expires_at": "2026-06-29T00:00:00Z"
}/v2/auth/loginemail | string | required | User email |
password | string | required | User password |
totp_code | string | optional | 6-digit TOTP if MFA is enabled |
{
"user_id": "usr_...",
"email": "trader@example.com",
"session_token": "sess_...",
"session_expires_at": "2026-06-29T00:00:00Z",
"mfa_required": false
}Other endpoints in this group: POST /v2/auth/resend-otp, POST /v2/auth/password-reset/request, POST /v2/auth/password-reset/confirm, POST /v2/auth/sessions/revoke (logout).
Who am I?
Verify a session and resolve the current user. Pass both the app bearer token and the user's X-Session-Token.
/v2/auth/mecurl http://localhost:8000/v2/auth/me \
-H "Authorization: Bearer <app_access_token>" \
-H "X-Session-Token: <user_session_token>"import { auth } from "@/lib/hsc/client";
const me = await auth.me();
// { user_id: "usr_...", email: "...", app_id: "app_..." }{ "user_id": "usr_...", "email": "trader@example.com", "app_id": "app_..." }/v2/auth/meRuns live against your environment using the app's server-side credentials and your session. Sign in to the dashboard first for authenticated reads.
Full API reference
/docs on the API. See also the Quickstart.