Authentication
Syaala Platform uses API keys and JWT tokens for secure authentication across all services.
Security First: Never commit API keys to version control. Always use environment variables or secure secret management.
Authentication Methods
Syaala supports three authentication methods:
- API Keys - For programmatic access (CLI, SDK, direct API calls)
- JWT Tokens - For dashboard and web applications
- Service Role Keys - For server-to-server communication (admin only)
API Keys
API keys provide long-lived authentication for automated systems, scripts, and integrations.
Creating an API Key
- Log into the Syaala Dashboard
- Navigate to Settings → API Keys
- Click “Create API Key”
- Enter a descriptive name (e.g.,
production-server,ci-cd-pipeline) - Select permissions scope:
- Full Access - All operations (deployments, billing, settings)
- Deployments Only - Create, read, update, delete deployments
- Read Only - View deployments and metrics (no writes)
- Click “Generate Key”
⚠️ Copy your API key immediately!
For security, we only show the key once. Store it securely - you won’t be able to see it again.
API Key Format
sk_live_1a2b3c4d5e6f7g8h9i0j # Production key
sk_test_9z8y7x6w5v4u3t2s1r0q # Development/testing key- Prefix:
sk_live_(production) orsk_test_(development) - Length: 32 characters after prefix
- Encoding: Base62 (alphanumeric)
Using API Keys
# Store in environment variable
export SYAALA_API_KEY="sk_live_1a2b3c4d5e6f7g8h9i0j"
# Authenticate CLI
syaala auth login --api-key "$SYAALA_API_KEY"
# Or authenticate interactively (prompts for key)
syaala auth loginRotating API Keys
For security, rotate API keys every 90 days:
- Create a new API key with the same permissions
- Update all systems to use the new key
- Test that everything works with the new key
- Delete the old API key from Dashboard → Settings → API Keys
💡 Pro Tip: Use separate API keys for each environment (development, staging, production) and service (CI/CD, backend, cron jobs).
JWT Tokens (Dashboard Authentication)
The Syaala Dashboard uses Supabase authentication with JWT tokens.
Login Flow
-
Email/Password Login:
POST https://platform.syaala.com/api/auth/login Content-Type: application/json { "email": "user@company.com", "password": "your-secure-password" } -
Response:
{ "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "refresh_token": "v1.Ma7Ql3...", "expires_in": 3600, "token_type": "bearer", "user": { "id": "user-uuid", "email": "user@company.com", "organization_id": "org-uuid" } } -
Token Storage:
- Access Token: Valid for 1 hour, stored in memory or httpOnly cookie
- Refresh Token: Valid for 30 days, used to obtain new access tokens
Token Refresh
Access tokens expire after 1 hour. Use the refresh token to get a new one:
const response = await fetch('https://platform.syaala.com/api/auth/refresh', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
refresh_token: 'v1.Ma7Ql3...'
})
})
const { access_token, refresh_token } = await response.json()Using JWT Tokens
// In browser/dashboard
const response = await fetch('https://platform.syaala.com/api/deployments', {
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
})Service Role Keys (Admin Only)
Service role keys bypass Row-Level Security (RLS) and have full database access.
🔴 DANGER: Service Role Keys
- Never expose service role keys in client-side code
- Only use in trusted server environments
- Rotate immediately if compromised
- Log all service role key usage
When to Use
- Database migrations - Applying schema changes
- Admin operations - Bulk user management, organization setup
- System scripts - Automated cleanup, billing reconciliation
Retrieving Service Role Key
- Log into Supabase Dashboard
- Select your project:
fvpedpplixboccfyoewv - Navigate to Settings → API
- Copy service_role key (not anon key!)
Using Service Role Keys
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!, // NEVER expose this!
{
auth: {
autoRefreshToken: false,
persistSession: false
}
}
)
// Bypass RLS - full database access
const { data: allUsers } = await supabase
.from('users')
.select('*')Security Best Practices
Environment Variables
DO use environment variables:
# .env (NEVER commit this file!)
SYAALA_API_KEY=sk_live_1a2b3c4d5e6f7g8h9i0j
SYAALA_ORG_ID=org_abc123xyz
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...// ✅ CORRECT
const apiKey = process.env.SYAALA_API_KEY
// ❌ WRONG - Never hardcode!
const apiKey = "sk_live_1a2b3c4d5e6f7g8h9i0j"Secret Management
For production environments, use proper secret management:
- Vercel: Environment Variables UI
- AWS: AWS Secrets Manager
- GCP: Secret Manager
- Kubernetes: Sealed Secrets or External Secrets Operator
Least Privilege
Grant minimum required permissions:
| Use Case | Recommended Permission |
|---|---|
| CI/CD pipeline | Deployments Only |
| Monitoring dashboard | Read Only |
| Admin scripts | Full Access |
| Customer integrations | Deployments Only |
Audit Logging
All API key usage is logged in the audit_logs table:
SELECT
action,
resource_type,
resource_id,
user_id,
api_key_id,
ip_address,
created_at
FROM audit_logs
WHERE api_key_id = 'key_abc123'
ORDER BY created_at DESC
LIMIT 100;Rate Limiting
API keys and JWT tokens are subject to rate limits:
| Plan | Rate Limit | Burst |
|---|---|---|
| Free | 60 requests/minute | 100 requests |
| Startup | 600 requests/minute | 1,000 requests |
| Growth | 6,000 requests/minute | 10,000 requests |
| Enterprise | Custom | Custom |
Rate Limit Headers
API responses include rate limit information:
HTTP/1.1 200 OK
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 587
X-RateLimit-Reset: 1728003600Handling Rate Limits
const response = await fetch('/api/deployments')
const remaining = parseInt(response.headers.get('X-RateLimit-Remaining') || '0')
const resetTime = parseInt(response.headers.get('X-RateLimit-Reset') || '0')
if (response.status === 429) {
const waitSeconds = resetTime - Math.floor(Date.now() / 1000)
console.log(`Rate limited. Retry after ${waitSeconds} seconds`)
await new Promise(resolve => setTimeout(resolve, waitSeconds * 1000))
// Retry request...
}Troubleshooting
Invalid API Key
Error: 401 Unauthorized: Invalid API key
Causes:
- API key is incorrect or has a typo
- API key has been deleted or revoked
- Using
sk_test_key in production environment
Solution: Verify the API key in Dashboard → Settings → API Keys
Token Expired
Error: 401 Unauthorized: Token expired
Causes:
- Access token has expired (1-hour lifetime)
- Refresh token has expired (30-day lifetime)
Solution: Use the refresh token to obtain a new access token
Insufficient Permissions
Error: 403 Forbidden: Insufficient permissions
Causes:
- API key has “Read Only” permissions but trying to create a deployment
- User account lacks organization admin privileges
Solution: Use an API key with appropriate permissions or contact your organization admin
Next Steps
Now that you understand authentication, you’re ready to: