Skip to main content

Stytch Integration

Use Stytch as your identity provider with AINative Studio. This guide walks through connecting your Stytch project so your users can authenticate with Stytch JWTs and access AINative APIs, ZeroDB, and ZeroMemory. Stytch also supports passwordless authentication via magic links.


Prerequisites


Step 1: Create a Project in Stytch

  1. Log in to the Stytch Dashboard
  2. Create a new project or select an existing one
  3. Navigate to API Keys and note your:
    • Project ID (e.g. project-live-abc123-def456)
    • Secret (e.g. secret-live-...)
    • Public Token (for client-side SDKs)
  4. Choose your authentication methods under Authentication:
    • Email magic links (passwordless)
    • OAuth (Google, GitHub, etc.)
    • Passwords
    • One-time passcodes (OTP)

Step 2: Configure Redirect URLs

In the Stytch Dashboard under Redirect URLs:

FieldValue
Login redirect URLhttps://your-app.com/authenticate
Signup redirect URLhttps://your-app.com/authenticate
Development URLshttp://localhost:3000/authenticate

Add your application domains under SDK Configuration > Authorized domains.


Step 3: Register Stytch as an Identity Provider in AINative

Call the AINative API to register your Stytch project as a trusted identity provider:

curl -X POST https://api.ainative.studio/api/v1/auth/providers \
-H "Authorization: Bearer YOUR_AINATIVE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"provider": "stytch",
"domain": "stytch.com",
"client_id": "YOUR_STYTCH_PROJECT_ID",
"jwks_uri": "https://stytch.com/v1/sessions/jwks/YOUR_STYTCH_PROJECT_ID",
"issuer": "stytch.com/YOUR_STYTCH_PROJECT_ID",
"claim_mapping": {
"user_id": "sub",
"email": "emails"
}
}'

Claim Mapping

Stytch JWTs include these claims that AINative maps automatically:

Stytch ClaimAINative FieldDescription
subuser_idUnique user identifier (e.g. user-live-abc123)
https://stytch.com/session--Session metadata (session ID, started/last accessed timestamps)

Stytch stores emails as an array in the session. AINative extracts the primary email from the emails array in the authenticated session response.


Step 4: Test the Connection

Obtain a test token from Stytch and verify it works with AINative:

# Authenticate a magic link token (after user clicks email link)
RESPONSE=$(curl -s -X POST https://api.stytch.com/v1/magic_links/authenticate \
-u "YOUR_STYTCH_PROJECT_ID:YOUR_STYTCH_SECRET" \
-H "Content-Type: application/json" \
-d '{
"token": "MAGIC_LINK_TOKEN_FROM_EMAIL",
"session_duration_minutes": 60
}')

TOKEN=$(echo $RESPONSE | jq -r '.session_jwt')

# Verify against AINative
curl -s https://api.ainative.studio/api/v1/auth/verify \
-H "Authorization: Bearer $TOKEN"

A successful response returns:

{
"valid": true,
"provider": "stytch",
"user_id": "user-live-abc123",
"email": "user@example.com"
}

Step 5: Use Stytch JWTs with AINative APIs

Once the provider is registered, your users can authenticate with their Stytch session JWTs across all AINative services.

Chat Completions

curl -X POST https://api.ainative.studio/api/v1/chat/completions \
-H "Authorization: Bearer STYTCH_SESSION_JWT" \
-H "Content-Type: application/json" \
-d '{
"model": "llama-3.3-70b",
"messages": [
{"role": "user", "content": "Hello from Stytch!"}
]
}'
curl -X POST https://api.ainative.studio/api/v1/zerodb/vectors/search \
-H "Authorization: Bearer STYTCH_SESSION_JWT" \
-H "X-Project-ID: YOUR_PROJECT_ID" \
-H "Content-Type: application/json" \
-d '{
"query": "passwordless authentication",
"top_k": 5
}'

ZeroMemory Store

curl -X POST https://api.ainative.studio/api/v1/public/memory/v2/remember \
-H "Authorization: Bearer STYTCH_SESSION_JWT" \
-H "Content-Type: application/json" \
-d '{
"content": "User authenticated via magic link",
"entity_name": "user_events"
}'

Step 6: Enable Row-Level Security for ZeroDB (Optional)

Row-Level Security (RLS) ensures that each user can only access their own data in ZeroDB. When enabled, the user_id claim from the Stytch JWT is automatically applied as a filter on all queries.

curl -X POST https://api.ainative.studio/api/v1/zerodb/projects/YOUR_PROJECT_ID/rls \
-H "Authorization: Bearer YOUR_AINATIVE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"enabled": true,
"user_id_claim": "sub",
"policy": "strict"
}'

With RLS enabled:

  • Vectors: Automatically filtered by the user_id extracted from the JWT sub claim
  • Tables: Row-level filtering applied on reads and writes
  • Files: Users can only access files they uploaded
  • Memory: Each user gets isolated memory namespaces

Stytch's magic links provide passwordless authentication. Here is a typical flow with AINative:

curl -X POST https://api.stytch.com/v1/magic_links/email/send \
-u "YOUR_STYTCH_PROJECT_ID:YOUR_STYTCH_SECRET" \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"login_magic_link_url": "https://your-app.com/authenticate",
"signup_magic_link_url": "https://your-app.com/authenticate"
}'

2. Authenticate the Token

When the user clicks the link, they are redirected to your app with a token parameter:

RESPONSE=$(curl -s -X POST https://api.stytch.com/v1/magic_links/authenticate \
-u "YOUR_STYTCH_PROJECT_ID:YOUR_STYTCH_SECRET" \
-H "Content-Type: application/json" \
-d '{
"token": "TOKEN_FROM_URL",
"session_duration_minutes": 60
}')

SESSION_JWT=$(echo $RESPONSE | jq -r '.session_jwt')

3. Use the Session JWT with AINative

curl -X POST https://api.ainative.studio/api/v1/chat/completions \
-H "Authorization: Bearer $SESSION_JWT" \
-H "Content-Type: application/json" \
-d '{
"model": "llama-3.3-70b",
"messages": [
{"role": "user", "content": "Authenticated via magic link!"}
]
}'

Troubleshooting

IssueCauseFix
401 UnauthorizedSession JWT expiredRequest a new session or refresh the existing one
403 ForbiddenRLS blocking accessCheck that the sub claim in the JWT matches the data owner
invalid_token errorJWKS URI unreachable or project ID wrongConfirm the JWKS URL contains the correct Stytch project ID
Missing emailEmail not in session claimsStytch stores emails in the session response, not always in the JWT -- fetch from the /v1/sessions/authenticate endpoint
Magic link expiredToken older than 10 minutesMagic link tokens expire after 10 minutes by default -- send a new one

Next Steps