Back to Developers
Security & Authentication

Authentication Guide

How to authenticate with BuildStability's MCP server and API

View Raw Markdown

Overview

BuildStability uses Supabase Auth for authentication. All API requests require a valid JWT (JSON Web Token) in the Authorization header.

Getting Your Access Token

Method 1: Copy Token (Easiest)

When API access is enabled for your business:

  1. Go to BusinessBusiness SettingsAPI & Integrations
  2. Turn on Enable API/MCP Access if needed
  3. Click Copy Token — your JWT is copied to the clipboard

Use it as Authorization: Bearer <token> in MCP, PostgREST, or any API client.

Method 2: Browser / Local Storage (Quick Test)

  1. Log in to BuildStability at https://buildstability.com/login
  2. Open browser DevTools (F12) → Application → Local Storage
  3. Find sb-<project-id>-auth-token
  4. Copy the access_token value

Method 3: Supabase Client (For Code)

import { createClient } from '@supabase/supabase-js';

const supabase = createClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_ANON_KEY!
);

// Sign in
const { data: { session }, error } = await supabase.auth.signInWithPassword({
  email: 'your@email.com',
  password: 'your-password'
});

// Get access token
const accessToken = session?.access_token;

Method 4: API Login Endpoint

curl -X POST https://buildstability.com/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "your@email.com",
    "password": "your-password"
  }'

Response includes access_token and refresh_token.

What a JWT Looks Like

A JWT has three base64url-encoded segments separated by dots: header.payload.signature. The header describes the algorithm; the payload holds claims (e.g. sub, email, exp); the signature ensures integrity. Tokens are usually 200–500+ characters.

Example format (always use your own from Copy Token—tokens are user-specific and expire in 1 hour):

eyJhbGciOiJIUzI1NiIsImtpZCI6InV2YkpJdUExNWpQeFBDdXAiLCJ0eXAiOiJKV1QifQ.eyJhYWwiOiJhYWwxIiwiYW1yIjpbeyJtZXRob2QiOiJwYXNzd29yZCIsInRpbWVzdGFtcCI6MTc2ODc5MzM3M31dLCJhcHBfbWV0YWRhdGEiOnsicHJvdmlkZXIiOiJlbWFpbCIsInByb3ZpZGVycyI6WyJlbWFpbCJdfSwiYXVkIjoiYXV0aGVudGljYXRlZCIsImVtYWlsIjoibWF0dGNub3RlcysxMEBnbWFpbC5jb20iLCJleHAiOjE3Njg5MTkzNzAsImlhdCI6MTc2ODkxNTc3MCwiaXNfYW5vbnltb3VzIjpmYWxzZSwiaXNzIjoiaHR0cHM6Ly95eWJvdWlpc2xkcWl6Z2VldnFuYy5zdXBhYmFzZS5jby9hdXRoL3YxIiwicGhvbmUiOiIiLCJyb2xlIjoiYXV0aGVudGljYXRlZCIsInNlc3Npb25faWQiOiIwZGExMWFjZC1iMTA0LTRmNWUtODBhOC1mYmE5NzU0NjVjYzQiLCJzdWIiOiI3OTYzNzUwNS0xMmM4LTQyYzQtOTVmZi1kYTFhNWFlZmNjMmUiLCJ1c2VyX21ldGFkYXRhIjp7ImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJmaXJzdF9uYW1lIjoiTUFyY28iLCJsYXN0X25hbWUiOiJQb2xsbyJ9fQ.y5O4bfebJunfHq3GETKq3c-1R_KhlTkb7rM2QjJJ770

What to do with it: Put it in the Authorization: Bearer <your-token> header for MCP (POST /api/mcp), PostgREST, or any BuildStability API that uses JWT auth.

Using the Token

MCP Requests

curl -X POST https://api.buildstability.com/api/mcp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -d '{ ... }'

Supabase PostgREST API Requests

Uses the same JWT tokens - no database credentials exposed. RLS automatically filters to your business data.

curl -X GET "https://your-project.supabase.co/rest/v1/profiles?business_id=eq.{id}" \
  -H "apikey: YOUR_ANON_KEY" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json"

See PostgREST API Guide for detailed usage.

Token Expiration

Access tokens expire after 1 hour. Refresh tokens are valid for 30 days.

Refreshing a Token

const { data: { session }, error } = await supabase.auth.refreshSession({
  refresh_token: storedRefreshToken
});

const newAccessToken = session?.access_token;

Automatic Refresh (Supabase Client)

The Supabase client automatically refreshes tokens when they expire. Use the client's onAuthStateChange listener:

supabase.auth.onAuthStateChange((event, session) => {
  if (event === 'TOKEN_REFRESHED') {
    console.log('Token refreshed:', session?.access_token);
  }
});

Security Best Practices

1. Never Commit Tokens

# .gitignore
.env
*.token
secrets.json

2. Use Environment Variables

const accessToken = process.env.BUILDSTABILITY_ACCESS_TOKEN;

3. Store Tokens Securely

  • Server-side: Use environment variables or secret management (AWS Secrets Manager, etc.)
  • Client-side: Use secure storage (not localStorage for sensitive apps)
  • Mobile: Use Keychain (iOS) or Keystore (Android)

4. Rotate Tokens Regularly

If a token is compromised, revoke it immediately:

await supabase.auth.signOut();

5. Use HTTPS Only

Always use https:// endpoints. Never send tokens over HTTP.

Multi-Tenancy & API Access

BuildStability uses business-level isolation with explicit API opt-in:

Security Model

  • API Access Must Be Enabled: Your business administrator must enable API access before MCP endpoints work.
  • Business Isolation: You can only access data for your business. All queries are automatically filtered by business_id.
  • Multi-Business Support: If you belong to multiple businesses, use the X-Business-ID header to specify which business to access.

Enabling API Access

Business administrators can enable API access:

  1. Go to Business SettingsAPI & Integrations
  2. Toggle Enable API Access and save if needed
  3. Click Copy Token to copy your JWT to the clipboard

Multi-Business Users

If you belong to multiple businesses with API access enabled:

# Specify which business to access
curl -X POST https://api.buildstability.com/api/mcp \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "X-Business-ID: your-business-uuid" \
  -H "Content-Type: application/json" \
  -d '{ ... }'

Without the X-Business-ID header, the system uses your first API-enabled business.

API Keys vs Access Tokens

  • Access Token (JWT): User-specific, expires after 1 hour. Use for MCP and authenticated API calls.
  • Anon Key: Public, never expires. Use for unauthenticated Supabase queries (limited access).

For MCP, always use the Access Token.

Troubleshooting

"Business context required" Error

  • Your token is missing or invalid
  • Token has expired (refresh it)
  • You're not authenticated
  • API access not enabled for your business

"Invalid Request" Error

  • Check your JSON-RPC format
  • Verify jsonrpc: "2.0" is present
  • Ensure method and id are included

"Method not found" Error

  • Check the method name spelling
  • Verify you're using the correct endpoint (/api/mcp)
  • Review available methods with tools/list

Next Steps