Skip to content

User Claims

User claims are key-value records attached to your users that the assistant reads automatically on every conversation. They give the assistant contextual knowledge about who it's talking to — without any prompt engineering on your part.


How claims work

When you send a request to /v1/responses with an x-user-id header, Nodexa loads all claims stored for that user and injects them into the assistant's context before it generates a reply. The assistant sees the user's name, role, preferences, and any other attributes you've stored — and uses that information naturally in its responses.

You never need to paste user data into the input field. Store it once, and every conversation automatically reflects it.


Authentication

All User Claims endpoints require an API key sent as x-api-key or Authorization: Bearer <key>.

-H "x-api-key: nxk_your_api_key_here"

Endpoints

Store claims — POST /v1/user-claims/bulk

Create or update multiple claims for a user in a single request. Each entry is an upsert: if a claim with the same userId + claimKey already exists, its value is overwritten.

Request headers:

Header Required Description
x-api-key Yes Your Nodexa API key
x-user-id Yes The user whose claims you are writing
Content-Type Yes application/json

Request body:

{
  "claims": [
    { "claimKey": "name", "claimValue": "Ada Lovelace" },
    { "claimKey": "preferred_language", "claimValue": "pt-BR" },
    { "claimKey": "role", "claimValue": "software_engineer" },
    { "claimKey": "subscription_plan", "claimValue": "pro" }
  ]
}
Field Required Type Description
claims Yes array Array of claim objects
claims[].claimKey Yes string Claim name. Use snake_case. Max 255 chars.
claims[].claimValue Yes any Any JSON value. Max 64KB total per user.

Response — 201 Created:

{
  "count": 2
}
const BASE_URL = 'https://app.nodexa.cloud';

async function setUserClaims(userId: string, claims: Record<string, unknown>) {
  const body = {
    claims: Object.entries(claims).map(([claimKey, claimValue]) => ({
      claimKey,
      claimValue,
    })),
  };

  const res = await fetch(`${BASE_URL}/v1/user-claims/bulk`, {
    method: 'POST',
    headers: {
      'x-api-key': process.env.NODEXA_API_KEY!,
      'x-user-id': userId,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(body),
  });

  if (!res.ok) throw new Error(`Failed to set claims: ${res.status}`);
  return res.json();
}

// On user sign-up or profile update
await setUserClaims('user_abc123', {
  name: 'Ada Lovelace',
  preferred_language: 'pt-BR',
  role: 'software_engineer',
  subscription_plan: 'pro',
});

Use fetch to write claims, then let the SDK handle conversations:

import OpenAI from 'openai';

const BASE_URL = 'https://app.nodexa.cloud';

const client = new OpenAI({
  baseURL: `${BASE_URL}/v1`,
  apiKey: process.env.NODEXA_API_KEY!,
  defaultHeaders: {
    'x-user-id': 'user_abc123',
  },
});

// 1. Store claims before (or at any time before) the conversation
await fetch(`${BASE_URL}/v1/user-claims/bulk`, {
  method: 'POST',
  headers: {
    'x-api-key': process.env.NODEXA_API_KEY!,
    'x-user-id': 'user_abc123',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    claims: [
      { claimKey: 'name', claimValue: 'Ada Lovelace' },
      { claimKey: 'preferred_language', claimValue: 'pt-BR' },
    ],
  }),
});

// 2. The assistant now knows the user's name and language automatically
const response = await client.responses.create({
  model: process.env.NODEXA_ASSISTANT_ID!,
  input: 'What features are available in my plan?',
});

console.log(response.output_text);
curl https://app.nodexa.cloud/v1/user-claims/bulk \
  -X POST \
  -H "x-api-key: nxk_your_api_key_here" \
  -H "x-user-id: user_abc123" \
  -H "Content-Type: application/json" \
  -d '{
    "claims": [
      { "claimKey": "name",               "claimValue": "Ada Lovelace" },
      { "claimKey": "preferred_language", "claimValue": "pt-BR" },
      { "claimKey": "role",               "claimValue": "software_engineer" },
      { "claimKey": "subscription_plan",  "claimValue": "pro" }
    ]
  }'

Retrieve claims — GET /v1/user-claims/:userId

Returns all claims stored for a user.

Path parameters:

Parameter Type Description
userId string The user's identifier

Response — 200 OK:

{
  "claims": [
    {
      "claimKey": "name",
      "claimValue": { "name": "Alice", "job": "Engineer" }
    },
    {
      "claimKey": "preferred_language",
      "claimValue": "pt-BR"
    }
  ],
  "userId": "user_abc123",
  "organizationId": "org_abc"
}

Note: claimValue can be any JSON value — a string, number, boolean, array, or object.

const res = await fetch(
  `https://app.nodexa.cloud/v1/user-claims/user_abc123`,
  { headers: { 'x-api-key': process.env.NODEXA_API_KEY! } }
);

const { claims, userId, organizationId } = await res.json();
console.log(claims);
curl "https://app.nodexa.cloud/v1/user-claims/user_abc123" \
  -H "x-api-key: nxk_your_api_key_here"

Delete a claim — DELETE /v1/user-claims/:userId/:claimKey

Permanently removes a single claim.

Path parameters:

Parameter Type Description
userId string The user's identifier
claimKey string The claim key to delete

Response: 200 OK on success. 404 if the claim does not exist.

const res = await fetch(
  `https://app.nodexa.cloud/v1/user-claims/user_abc123/preferred_language`,
  {
    method: 'DELETE',
    headers: { 'x-api-key': process.env.NODEXA_API_KEY! },
  }
);

if (res.ok) {
  console.log('Claim deleted');
} else if (res.status === 404) {
  console.log('Claim not found');
}
curl "https://app.nodexa.cloud/v1/user-claims/user_abc123/preferred_language" \
  -X DELETE \
  -H "x-api-key: nxk_your_api_key_here"

How the assistant uses claims

When a user sends a message, Nodexa automatically:

  1. Looks up all claims for the x-user-id provided in the request.
  2. Serialises the claims into a structured context block.
  3. Prepends that block to the assistant's system context before the LLM call.

The result is that the assistant always knows who it's talking to. If a user has preferred_language: "pt-BR", the assistant will respond in Portuguese — no extra prompt needed. If a user has role: "data_analyst", the assistant tailors its explanations accordingly.

Claims are not visible in output_text

Claims are injected as system-level context, not as part of the conversation history that the user sees. They influence responses silently.


Best practices

Claim key naming

Use snake_case, descriptive names. Keep keys stable — changing a key name effectively creates a new claim and orphans the old one.

Good Avoid
name n, userName
preferred_language lang, language_preference_value
subscription_plan plan_type_current
role jobRole, user_role_string
timezone tz, user_tz_code

What to store

Focus on stable, reusable facts about the user that many assistant interactions would benefit from:

  • Identity: name, email (if needed for tool calls)
  • Localisation: preferred_language, timezone, locale
  • Role / access: role, subscription_plan, team
  • Personalisation: communication_style (e.g., "concise" vs "detailed"), industry

Avoid storing ephemeral session data or large blobs — use the input field in the request body for that.

Syncing from your user database

Call the bulk endpoint whenever a user is created or their profile changes:

async function syncUserToNodexa(user: {
  id: string;
  fullName: string;
  locale: string;
  plan: string;
  role: string;
}) {
  await fetch('https://app.nodexa.cloud/v1/user-claims/bulk', {
    method: 'POST',
    headers: {
      'x-api-key': process.env.NODEXA_API_KEY!,
      'x-user-id': user.id,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      claims: [
        { claimKey: 'name', claimValue: user.fullName },
        { claimKey: 'preferred_language', claimValue: user.locale },
        { claimKey: 'subscription_plan', claimValue: user.plan },
        { claimKey: 'role', claimValue: user.role },
      ],
    }),
  });
}

Limits

Limit Value
Maximum total claims storage per user 64KB
Maximum claims per bulk request 50
Maximum claimKey length 255 characters

See Limits for the full limits reference.