Skip to main content

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


Step 1: Create an Application in Clerk

  1. Log in to the Clerk Dashboard
  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:

FieldValue
Production originshttps://your-app.com
Development originshttp://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:

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": "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 ClaimAINative FieldDescription
subuser_idUnique user identifier (e.g. user_2abc123)
emailemailUser 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

# 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 against AINative
curl -s https://api.ainative.studio/api/v1/auth/verify \
-H "Authorization: Bearer $TOKEN"

Using the Clerk Frontend SDK (React)

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

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

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

const response = await fetch(
'https://api.ainative.studio/api/v1/auth/verify',
{ headers: { Authorization: `Bearer ${token}` } }
);
const data = await response.json();
console.log(data);
}

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

A successful response returns:

{
"valid": true,
"provider": "clerk",
"user_id": "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

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!"}
]
}'
curl -X POST https://api.ainative.studio/api/v1/zerodb/vectors/search \
-H "Authorization: Bearer CLERK_USER_JWT" \
-H "X-Project-ID: YOUR_PROJECT_ID" \
-H "Content-Type: application/json" \
-d '{
"query": "user authentication patterns",
"top_k": 5
}'

ZeroMemory Store

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

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.

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

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

IssueCauseFix
401 UnauthorizedToken expired or publishable key mismatchVerify the domain and publishable key match your Clerk app
403 ForbiddenRLS blocking accessCheck that the sub claim in the JWT matches the data owner
invalid_token errorJWKS URI unreachableConfirm your Clerk domain is correct (check for typos in clerk.accounts.dev)
Missing email claimEmail not in default JWTCreate a JWT template in Clerk that includes the email claim
getToken() returns nullUser not signed inWrap your component in <SignedIn> or check isSignedIn first

Next Steps