Authentication
Overview
Nexus uses two main authentication paths:
- Human user authentication via Supabase Auth
- AI agent authentication via agent API keys exchanged for short-lived JWTs
All API requests except explicitly public endpoints require a valid bearer token.
Human user JWTs
Email/password login
curl -X POST https://<project-ref>.supabase.co/auth/v1/token?grant_type=password \
-H "apikey: <anon-key>" \
-H "Content-Type: application/json" \
-d '{
"email": "agent@example.com",
"password": "••••••••"
}'
Response (abbreviated):
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "bearer",
"expires_in": 3600,
"refresh_token": "v1.MjAyNS0w..."
}
Token refresh
curl -X POST https://<project-ref>.supabase.co/auth/v1/token?grant_type=refresh_token \
-H "apikey: <anon-key>" \
-H "Content-Type: application/json" \
-d '{"refresh_token": "v1.MjAyNS0w..."}'
AI agent authentication
Step 1: create an agent API key
Only organization owner and admin users can create agent API keys.
Endpoint:
POST https://lgwvoomgrwpsgpxwyaec.supabase.co/functions/v1/agent-api-key-create
Request:
curl -X POST "https://lgwvoomgrwpsgpxwyaec.supabase.co/functions/v1/agent-api-key-create" \
-H "Authorization: Bearer <human-user-jwt>" \
-H "Content-Type: application/json" \
-d '{
"name": "Bahig - Karim assistant",
"scopes": ["read", "write"],
"expires_at": "2026-12-31T23:59:59Z"
}'
The raw key is returned once only. Nexus stores only a bcrypt hash.
Step 2: exchange the API key for an agent JWT
Endpoint:
POST https://lgwvoomgrwpsgpxwyaec.supabase.co/functions/v1/agent-auth
Request:
curl -X POST "https://lgwvoomgrwpsgpxwyaec.supabase.co/functions/v1/agent-auth" \
-H "Content-Type: application/json" \
-d '{
"api_key": "nxs_ak_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12"
}'
Response:
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"expires_in": 3600,
"organization_id": "org-uuid"
}
Security guarantees:
- raw keys are never stored
- revoked keys are rejected
- expired keys are rejected
- auth attempts are logged
- the endpoint is rate limited to
10attempts per minute per IP - issued agent JWTs expire after 1 hour
Using a bearer token
Include the JWT in the Authorization header of every request:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
For Supabase PostgREST endpoints, also include the apikey header:
apikey: <anon-key>
Token claims
Human JWTs
Human JWTs contain these relevant claims:
| Claim | Description |
|---|---|
sub | User ID (UUID) |
email | User email |
role | Supabase role (authenticated) |
app_metadata.organization_id or app_metadata.org_id | Current organization ID |
app_metadata.org_role | Organization role (owner, admin, member) |
Agent JWTs
Agent JWTs contain these relevant claims:
| Claim | Description |
|---|---|
sub | Agent API key ID |
role | Supabase role (authenticated) |
organization_id | Current organization ID |
org_role | Always agent |
agent_scopes | Scope array such as ["read"] or ["read","write"] |
app_metadata.organization_id | Current organization ID |
app_metadata.org_role | Always agent |
app_metadata.agent_scopes | Scope array |
Row-Level Security
The JWT's organization claims are used by PostgreSQL RLS policies to filter data. Users and agents can only access rows belonging to their organization. Agent write/delete access is additionally gated by scope-aware RLS helpers.
MCP authentication
The hosted MCP endpoint accepts only the agent JWT, not the raw API key:
POST https://lgwvoomgrwpsgpxwyaec.supabase.co/functions/v1/mcp-server
Authorization: Bearer <agent-jwt>
For the full MCP workflow and tool inventory, see AI Agents, API Keys, and MCP.
Webhook authentication
Inbound webhook endpoints (e.g., whatsapp-webhook, shopify-webhook) use different authentication mechanisms:
- Verify token — a shared secret validated on webhook registration (WhatsApp, Meta).
- HMAC signature — request body signed with a shared secret (Shopify).
- Bearer token — a static token in the
Authorizationheader (internal webhooks).
Webhook authentication details are not included in the public OpenAPI spec for security reasons.
Best practices
- Never hardcode tokens in client-side code. Use Supabase Auth SDK for token management.
- Never use the raw agent API key beyond the
agent-authexchange. - Refresh or re-issue tokens before they expire (
expires_inis in seconds). - Never use the service role key in client applications.
- Store tokens and API keys securely, ideally in a secret manager.