New: MCP server monitoring is live. Start free

Documentation

Authentication

Browser users: signing in to the Intello app is enough. The UI handles tokens. This page is for direct HTTP API access (automation, custom integrations).

All /api/* routes (except health checks and explicitly public ones) require a Bearer token issued by Supabase Auth and verified by Intello.

Request header

Authorization: Bearer <supabase_access_token>
Content-Type: application/json

Verification rules (production posture)

Intello’s verifier typically enforces:

  • Algorithm: ES256 (ECDSA P-256), keys from Supabase JWKS
  • Issuer: ${SUPABASE_URL}/auth/v1 (overridable via AUTH_JWT_ISSUER)
  • Audience: authenticated (overridable via AUTH_JWT_AUDIENCE)
  • Clock skew: small leeway window to tolerate minor drift

Tokens failing any check return 401 with code=unauthorized or token_expired.

User sync gate

The JWT proves Supabase identity, but Intello persists org membership in its own database. If the user row is missing, APIs return:

HTTP/1.1 428 Precondition Required

{
  "error": {
    "code": "user_not_synced",
    "message": "user account not synced, call POST /auth/sync first"
  }
}

Remediation: call POST /auth/sync once after login with the same Bearer token.

Organization scope

After auth, Intello loads the users row and sets org_id from that record—not from JWT custom claims clients can manipulate.

Never trust a client-supplied organization id in request bodies for authorization. All IDOR-safe handlers re-verify resource ownership via org_id in the store layer.

Service-to-service

Customer automation should use a dedicated Supabase user (machine account) or future org API keys if enabled in your deployment. Platform integrations use a separate PLATFORM_API_KEY on /internal/* routes—those endpoints are not supported for customer use.

Example: obtain token (pseudo-code)

const { data, error } = await supabase.auth.signInWithPassword({
  email: process.env.INTELLO_BOT_EMAIL,
  password: process.env.INTELLO_BOT_PASSWORD,
});
if (error) throw error;
const accessToken = data.session.access_token;

Refresh tokens before expiry—long-running jobs should renew sessions.

Related topics

Catch OpenAPI breaking changes early

Add your spec—diffs and alerts on every sync. No credit card to start; upgrade for faster polling, Slack or Teams, and more seats.