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

# Clerk

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

> Integrate Clerk authentication with AINative Studio APIs and ZeroDB

## Clerk Integration

Use Clerk as your identity provider with AINative Studio. This guide walks through connecting your Clerk application so your users can authenticate with Clerk JWTs and access AINative APIs, ZeroDB, and ZeroMemory. Clerk includes built-in user management, so you get sign-up, sign-in, and profile management out of the box.

---

## Prerequisites

- A [Clerk account](https://clerk.com) with an application
- 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 an Application in Clerk

1. Log in to the [Clerk Dashboard](https://dashboard.clerk.com)
2. Click **Create application** (or select an existing one)
3. Choose your sign-in methods:
   - Email address
   - Google, GitHub, or other social providers
   - Phone number
4. Note your credentials under **API Keys**:
   - **Publishable Key** (e.g. `pk_live_abc...` or `pk_test_abc...`)
   - **Secret Key** (e.g. `sk_live_abc...` or `sk_test_abc...`)

Your Clerk domain follows the pattern `{app}.clerk.accounts.dev`.

---

## Step 2: Configure Allowed Origins

In the Clerk Dashboard under **Paths > Allowed origins**:

| Field | Value |
|-------|-------|
| **Production origins** | `https://your-app.com` |
| **Development origins** | `http://localhost:3000` |

Clerk supports standard OIDC discovery at `https://{app}.clerk.accounts.dev/.well-known/openid-configuration`.

### JWT Templates (Optional)

To customize the claims included in your JWT, go to **JWT Templates** in the Clerk Dashboard:

1. Click **New template**
2. Choose **Blank** or start from a preset
3. Add custom claims your application needs (e.g. `org_id`, `role`)
4. Note the template name -- you will use it when requesting tokens

---

## Step 3: Register Clerk as an Identity Provider in AINative

Call the AINative API to register your Clerk application 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": "clerk",
    "domain": "YOUR_APP.clerk.accounts.dev",
    "client_id": "YOUR_CLERK_PUBLISHABLE_KEY",
    "jwks_uri": "https://YOUR_APP.clerk.accounts.dev/.well-known/jwks.json",
    "issuer": "https://YOUR_APP.clerk.accounts.dev",
    "claim_mapping": {
      "user_id": "sub",
      "email": "email"
    }
  }'
```

### Claim Mapping

Clerk JWTs include these claims that AINative maps automatically:

| Clerk Claim | AINative Field | Description |
|-------------|----------------|-------------|
| `sub` | `user_id` | Unique user identifier (e.g. `user_2abc123`) |
| `email` | `email` | User primary email address |

If you use Clerk Organizations, you can add `org_id` to your JWT template and map it to AINative's `tenant` field for multi-tenant isolation.

---

## Step 4: Test the Connection

Obtain a test token from Clerk and verify it works with AINative.

### Using the Clerk Backend API

```bash
## Get a session token via Clerk Backend API
## First, create a test user session through the Clerk Dashboard or SDK
## Then retrieve the session token:

TOKEN=$(curl -s https://api.clerk.com/v1/sessions/SESSION_ID/tokens \
  -H "Authorization: Bearer YOUR_CLERK_SECRET_KEY" | jq -r '.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\"}"
```

### Using the Clerk Frontend SDK (React)

```tsx
import { useAuth } from '@clerk/clerk-react';

function MyComponent() {
  const { getToken } = useAuth();

  async function callAINative() {
    const token = await getToken();

    // PROVIDER_ID is the id returned when you registered the provider in Step 3.
    const response = await fetch(
      'https://api.ainative.studio/api/v1/public/auth-providers/PROVIDER_ID/verify',
      {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${process.env.AINATIVE_API_KEY}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ token }),
      }
    );
    const data = await response.json();
    console.log(data);
  }

  return <button onClick={callAINative}>Verify Token</button>;
}
```

A successful response returns the decoded claims:

```json
{
  "valid": true,
  "user_id": "user_2abc123",
  "email": "user@example.com",
  "claims": { "sub": "user_2abc123", "email": "user@example.com" }
}
```

---

## Step 5: Use Clerk JWTs with AINative APIs

Once the provider is registered, your users can authenticate with their Clerk tokens across all AINative services.

### Chat Completions

```bash
curl -X POST https://api.ainative.studio/api/v1/chat/completions \
  -H "Authorization: Bearer CLERK_USER_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "llama-3.3-70b",
    "messages": [
      {"role": "user", "content": "Hello from Clerk!"}
    ]
  }'
```

### ZeroDB Vector Search

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

### ZeroMemory Store

```bash
curl -X POST https://api.ainative.studio/api/v1/public/memory/v2/remember \
  -H "Authorization: Bearer CLERK_USER_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "User signed up via Google OAuth",
    "entity_name": "user_events"
  }'
```

### Using Clerk React SDK with AINative

```tsx
import { useAuth } from '@clerk/clerk-react';

function AIChatComponent() {
  const { getToken } = useAuth();
  const [response, setResponse] = useState('');

  async function sendMessage(message: string) {
    const token = await getToken();

    const res = await fetch(
      'https://api.ainative.studio/api/v1/chat/completions',
      {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${token}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          model: 'llama-3.3-70b',
          messages: [{ role: 'user', content: message }],
        }),
      }
    );
    const data = await res.json();
    setResponse(data.choices[0].message.content);
  }

  return (
    <div>
      <button onClick={() => sendMessage('Hello!')}>Send</button>
      <p>{response}</p>
    </div>
  );
}
```

---

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

---

## Clerk User Management

Clerk provides built-in user management components. You can use these alongside AINative to manage your users without building custom UI:

- **`<SignIn />`** -- Pre-built sign-in form
- **`<SignUp />`** -- Pre-built sign-up form
- **`<UserButton />`** -- User avatar with profile/sign-out menu
- **`<UserProfile />`** -- Full profile management page
- **`<OrganizationSwitcher />`** -- Multi-tenant organization picker

These components handle authentication and return JWTs that work directly with AINative APIs.

---

## Troubleshooting

| Issue | Cause | Fix |
|-------|-------|-----|
| `401 Unauthorized` | Token expired or publishable key mismatch | Verify the domain and publishable key match your Clerk app |
| `403 Forbidden` | RLS blocking access | Check that the `sub` claim in the JWT matches the data owner |
| `invalid_token` error | JWKS URI unreachable | Confirm your Clerk domain is correct (check for typos in `clerk.accounts.dev`) |
| Missing `email` claim | Email not in default JWT | Create a JWT template in Clerk that includes the `email` claim |
| `getToken()` returns null | User not signed in | Wrap your component in `<SignedIn>` or check `isSignedIn` first |

---

## Next Steps

- [ZeroMemory Guide](/docs/zeromemory/overview) -- Add persistent memory to your Clerk-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
