Substratal Apps Substratal Apps Hub specs
GitHub

Help Developers

Developers

Authentication

Every authenticated request sends Authorization: Bearer <credential>, plus the Substratal-Version header. Which credential you send depends on who's calling.

Caller Credential Lifetime How you get it
A person, in a Hub app or your own first-party app Platform access token (JWT) 15 minutes, refreshed with a rotating refresh token (30 days idle, 90 days absolute) POST /auth/login, then POST /auth/mfa/verify if two-factor is on
Your server or backend job API key (satk_live_… or satk_test_…) Until revoked, or until its optional expires_at Created by a person in the Hub (API Keys), or with POST /api-keys
A person opening your Application App token (JWT, aud = your application_id) 5 minutes Minted by the Hub at launch (POST /auth/app-tokens) or through the hosted PKCE flow

Signing in as a person

curl -s https://api.substratalapps.com/auth/login \
  -H 'Substratal-Version: 1' -H 'Content-Type: application/json' \
  -d '{"email":"dana@example.com","password":"correct horse battery staple"}'

If two-factor is on, the response is a challenge:

{ "mfa_required": true, "mfa_token": "mfa_01JAG…", "methods": ["totp", "recovery_code"], "expires_in": 300 }

Finish with POST /auth/mfa/verify {"mfa_token": "…", "code": "123456"}. Both paths end with the same session: access_token, refresh_token, session_id.

Refresh tokens are single-use. Refresh once, persist the new refresh token atomically, and never run two refreshes in parallel. Reusing a rotated refresh token revokes the whole session and raises a security.session_reuse_detected alert.

API keys are for servers only

  • Never put an API key in a mobile app, desktop app or browser. The API refuses a key sent with an Origin header (400 api_key_in_browser).
  • A key's secret is shown once, when it's created. Store it in your secret manager straight away.
  • An app-scoped key can only reach its own Application's rows. A platform key can't hold more permissions than the person who created it.
  • Mark keys used by AI agents as intended_use: agent. They default to restrict_destructive: true, so an agent can't run destructive operations unless a person turns that on.

Verifying app tokens

Applications verify app tokens locally against the keys at https://api.substratalapps.com/.well-known/jwks.json (cache them for an hour). Check iss, aud, exp and the signature, then read effective_permissions. Subscribe to the access.revoked and role.removed webhooks so access you turn off ends immediately, not when the token expires. That subscription is required.

Last updated 2026-10-23 · Built 2026-10-25 from a9ef3be · API 1.0.0-draft.13 · Substratal-Version: 1