---
title: "Stytch"
description: "Integrate Stytch authentication with AINative Studio APIs and ZeroDB"
canonical: "https://docs.ainative.studio/docs/integrations/stytch"
last-updated: "2026-10-22T17:48:46.689Z"
---

# Stytch

Source: https://docs.ainative.studio/docs/integrations/stytch

> Integrate Stytch authentication with AINative Studio APIs and ZeroDB

## 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

- A [Stytch account](https://stytch.com) with a project
- An [AINative Studio account](https://ainative.studio) with a project and API key
- Your AINative project ID (found in the dashboard under **Settings**)

---

## Step 1: Create a Project in Stytch

1. Log in to the [Stytch Dashboard](https://stytch.com/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**:

| Field | Value |
|-------|-------|
| **Login redirect URL** | `https://your-app.com/authenticate` |
| **Signup redirect URL** | `https://your-app.com/authenticate` |
| **Development URLs** | `http://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:

```bash
curl -X POST https://api.ainative.studio/api/v1/auth/providers \
  -H "Authorization: Bearer $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 Claim | AINative Field | Description |
|--------------|----------------|-------------|
| `sub` | `user_id` | Unique 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:

```bash
## 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 the provider JWT against AINative
## PROVIDER_ID is the id returned when you registered the provider in Step 3.
curl -s -X POST https://api.ainative.studio/api/v1/public/auth-providers/PROVIDER_ID/verify \
  -H "Authorization: Bearer $AINATIVE_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"token\": \"$TOKEN\"}"
```

A successful response returns the decoded claims:

```json
{
  "valid": true,
  "user_id": "user-live-abc123",
  "email": "user@example.com",
  "claims": { "sub": "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

```bash
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!"}
    ]
  }'
```

### ZeroDB Vector Search

```bash
curl -X POST https://api.ainative.studio/api/v1/public/YOUR_PROJECT_ID/embeddings/search \
  -H "Authorization: Bearer STYTCH_SESSION_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "passwordless authentication",
    "limit": 5
  }'
```

### ZeroMemory Store

```bash
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.

```bash
curl -X POST https://api.ainative.studio/api/v1/zerodb/projects/YOUR_PROJECT_ID/rls \
  -H "Authorization: Bearer $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

---

## Magic Links (Passwordless)

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

### 1. Send a Magic Link

```bash
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:

```bash
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

```bash
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

| Issue | Cause | Fix |
|-------|-------|-----|
| `401 Unauthorized` | Session JWT expired | Request a new session or refresh the existing one |
| `403 Forbidden` | RLS blocking access | Check that the `sub` claim in the JWT matches the data owner |
| `invalid_token` error | JWKS URI unreachable or project ID wrong | Confirm the JWKS URL contains the correct Stytch project ID |
| Missing email | Email not in session claims | Stytch stores emails in the session response, not always in the JWT -- fetch from the `/v1/sessions/authenticate` endpoint |
| Magic link expired | Token older than 10 minutes | Magic link tokens expire after 10 minutes by default -- send a new one |

---

## Next Steps

- [ZeroMemory Guide](/docs/zeromemory/overview) -- Add persistent memory to your Stytch-authenticated agents
- [API Reference](/docs/api/overview) -- Full API documentation
- [SDK Quick Start](/docs/sdks/overview) -- Client SDKs for React, Next.js, Vue, Svelte, and Python
