Cortexiom API — Developer Guide

Version: v1
Base URL: https://api.cortexiom.com
Auth: Bearer token (cx_live_...)


What This API Is

Most AI APIs return an answer. The Cortexiom API returns an answer and builds a model of the person asking — deepening its understanding of them across every interaction, without you managing any of that state.

You send a message. You get a response. Between those two things, a multi-step reasoning pipeline runs: it generates competing interpretations of the input, holds contradictions as signals rather than errors, calibrates its own confidence, and synthesizes across everything before responding. Each cycle, what it learns gets folded back into an encrypted state token you store alongside your user record.

The result: an AI that reasons differently in session 20 than it did in session 1 — because it actually knows the person it is talking to.

This is what we mean by reasoning infrastructure. Not a chatbot. Not a wrapper around a language model. A reasoning layer you embed underneath your product so your AI gets smarter about each of your users over time.


Who Builds With This

The Cortexiom API is for developers building products where the quality of AI reasoning matters more than volume. The clearest use cases:

  • ·Mental health and coaching apps — where the AI needs to hold what someone has said across sessions and reason about patterns without being told them again
  • ·Executive and career coaching tools — where depth builds trust and surface-level responses break it
  • ·Learning and tutoring platforms — where understanding how a student thinks is more useful than generating any individual answer
  • ·Sales and CRM intelligence — where an AI that builds a model of a prospect reasons about their objections differently than one that starts from zero each call
  • ·Policy and governance — where an AI that tracks context across briefings, stakeholder positions, and prior decisions reasons about tradeoffs differently than one starting from zero each session
  • ·Natural resource management — where regulatory complexity and long-horizon decisions demand an AI that maintains context across months, not turns
  • ·Climate and sustainability consulting — where cross-domain reasoning across science, policy, and economics must hold tension between competing frameworks rather than collapse it prematurely
  • ·Legal and compliance tools — where the cost of a confident wrong answer is measured in liability, not retries

The common thread: domains where confident hallucination is a product failure, and where the AI getting to know the user — and the problem — is the feature.


Core Concepts

The Encounter

Every API call is an encounter — a single reasoning cycle that processes a user's message, updates the internal model, and returns a response. Encounters are not "chat turns." They are structured reasoning events that produce confidence scores, depth metrics, and an updated state.

The State Token

The Cortexiom API is stateless on our side by design. We hold no user data between calls.

Instead, every encounter response includes a state_token — an encrypted blob that encodes everything the reasoning pipeline has learned about this user: their reasoning patterns, unresolved tensions, core insights from prior sessions, and an evolving model of how they think.

You store the token. You pass it back on the next call. We decrypt it, run the pipeline, and return a new token with the updated state.

Your App
  │  POST /v1/encounter  (message + state_token from your DB)
  ▼
Cortexiom API
  │  runs reasoning pipeline (5–8 seconds)
  ▼
Your App
  │  response + new state_token  →  save token to your DB

The token is opaque. You cannot read it. You cannot modify it. It is AES-256-GCM encrypted with a key only Cortexiom holds. If a token is tampered with, the next call returns 400 Invalid or tampered state_token.

What this means for you:

  • ·Zero data custody on your end beyond the encrypted blob — no GDPR concern from holding our data
  • ·Enterprise procurement doesn't stall on "where does this user data live"
  • ·Simply swap the token in your database after each encounter, your users' context persists automatically

The Persona

The persona is your AI's character layer. You define who the AI is — its name, role, domain focus, and any hard constraints. The reasoning architecture underneath is Cortexiom's to control. You control the voice.

Persona is sent on the first call only. It is stored inside the encrypted state token and carried forward automatically. You never need to resend it unless you want to change it.

"persona": {
  "name": "Maya",
  "role": "executive coach",
  "domain": "You work with professionals navigating major career transitions. You are direct, warm, and push past surface-level answers.",
  "constraints": "Do not give financial or legal advice."
}

Depth and Confidence

Every response includes two signal fields:

  • ·

    depth — how many reasoning cycles have occurred in this user's session. Depth 1 is the first encounter. As depth grows, the system's model of the user matures and responses reflect accumulated understanding.

  • ·

    confidence — the pipeline's self-assessed certainty in the response, on a 0–1 scale. Low confidence (0.4–0.6) signals genuine ambiguity — the pipeline is holding competing interpretations. High confidence (0.8+) signals synthesis: the pieces aligned. This is not a sentiment score. It is a calibrated epistemic signal.

These fields exist because your application can use them. Show a confidence indicator to your users. Route low-confidence responses to human review. Use depth to trigger a "session milestone" UI. The data is there.


Authentication

All requests require an API key in the Authorization header:

Authorization: Bearer cx_live_...

Keys are prefixed cx_live_ for production. Keep your key server-side. Never expose it in client-side code.

To get your API key: visit developers.cortexiom.com


Quick Start

A complete working example in under 30 lines.

First call — new user

const response = await fetch('https://api.cortexiom.com/v1/encounter', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer cx_live_YOUR_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    message: "I have been avoiding a difficult conversation with my manager for months.",
    persona: {
      name: "Maya",
      role: "executive coach",
      domain: "You work with professionals navigating major career transitions. You are direct and push past surface-level answers.",
      constraints: "Do not give financial or legal advice."
    }
  }),
});

const { response: reply, depth, confidence, state_token } = await response.json();

// Save state_token to your database alongside this user
await db.users.update(userId, { cortexiomStateToken: state_token });

console.log(reply);        // Maya's response
console.log(depth);        // 1
console.log(confidence);   // e.g. 0.58

Subsequent calls — returning user

// Load the token you saved last time
const { cortexiomStateToken } = await db.users.find(userId);

const response = await fetch('https://api.cortexiom.com/v1/encounter', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer cx_live_YOUR_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    message: "I finally had the conversation. My manager had no idea I wanted a promotion.",
    state_token: cortexiomStateToken,
    // persona is not required — it's already in the state token
  }),
});

const data = await response.json();

// Always replace the token — the state has been updated
await db.users.update(userId, { cortexiomStateToken: data.state_token });

console.log(data.response);    // Maya's response, aware of prior context
console.log(data.depth);       // 2

That is the entire integration pattern. Two fields in, two fields out that matter: response and state_token.


API Reference

POST /v1/encounter

Runs a full reasoning cycle on the user's message and returns a response with updated state.

Request

POST /v1/encounter
Authorization: Bearer cx_live_...
Content-Type: application/json
{
  "message": "string",
  "state_token": "string",
  "persona": { ... },
  "stream": false
}
FieldTypeRequiredDescription
messagestringAlwaysThe user's input. Max 4,000 characters.
state_tokenstringAfter first callToken from the previous encounter response. Omit on first call.
personaobjectFirst callCharacter configuration. Stored in state after first call. Optional on subsequent calls.
streambooleanNoSet true to receive a streaming SSE response. Default false.

Persona object

FieldTypeRequiredDescription
namestringYesThe AI's name as the user will encounter it.
rolestringYesThe AI's role, stated plainly. Used to frame every reasoning step.
domainstringYesDetailed description of the AI's domain, style, and approach. This is the most important field — write it as a brief but specific brief for the character.
constraintsstringNoHard limits on what the AI will and won't do.

Response (non-streaming)

{
  "response": "string",
  "depth": 7,
  "confidence": 0.74,
  "credits_used": 1,
  "state_token": "cx_st_..."
}
FieldTypeDescription
responsestringThe final response, directly addressed to the user.
depthintegerHow many reasoning cycles have occurred with this user. Increments by 1 per encounter.
confidencefloatPipeline confidence in the response, 0.0–1.0.
credits_usedintegerAlways 1 per encounter. One encounter = one billing unit.
state_tokenstringUpdated encrypted state. Always replace your stored token with this value.

Streaming

Add "stream": true to your request. The response is delivered as Server-Sent Events.

const response = await fetch('https://api.cortexiom.com/v1/encounter', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer cx_live_YOUR_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    message: "I have been avoiding a difficult conversation with my manager.",
    state_token: savedToken,
    stream: true,
  }),
});

const reader = response.body.getReader();
const decoder = new TextDecoder();
let fullResponse = '';
let newStateToken = '';

while (true) {
  const { done, value } = await reader.read();
  if (done) break;

  const lines = decoder.decode(value).split('\n');
  for (const line of lines) {
    if (!line.startsWith('data: ')) continue;
    const event = JSON.parse(line.slice(6));

    if (event.type === 'start_response') {
      // Reasoning phase is done — response tokens are starting.
      hideThinkingIndicator();
    }

    if (event.type === 'token') {
      fullResponse += event.text;
      appendToUI(event.text);
    }

    if (event.type === 'done') {
      newStateToken = event.state_token;
      await db.users.update(userId, { cortexiomStateToken: newStateToken });
    }

    if (event.type === 'error') {
      console.error('Pipeline error:', event.error);
    }
  }
}

SSE event types

EventPayloadWhen
start_responseThe reasoning phase is complete. Response tokens are about to start.
token{ text: string }One chunk of the response text. Render these progressively.
doneFull response object (same fields as non-streaming)After all tokens. Contains the new state_token — save it here.
error{ error: string }Pipeline failure. The state token from the previous call is still valid.

Timing note: There is typically a 5–8 second delay before start_response while the reasoning pipeline runs. This is not a network stall — it is the cost of multi-step reasoning. Plan your loading UI around it.


State Tokens — Full Behaviour

Understanding the token lifecycle prevents the most common integration mistakes.

First call

Omit state_token. A fresh reasoning state is initialised. The response will include a state_token — store it immediately.

Every subsequent call

Pass the token from the previous response. The pipeline decrypts it, reasons with the accumulated context, then encrypts the updated state into a new token.

Always replace the token you stored. Every successful encounter returns a new token. The previous token is not invalidated (it can still be used), but it no longer reflects the latest state. If you don't update your stored token, the user's state rolls back to the previous encounter.

What happens if you lose the token

If a token is lost, the user's accumulated state is unrecoverable — it is not stored on our servers. That user's session resets to a fresh state on the next call (omit state_token). Design your storage accordingly: treat the state token like a session JWT that must be persisted reliably.

Overriding the persona mid-session

Pass a persona field alongside a state_token. The new persona replaces the stored one going forward.

Token format

All state tokens begin with cx_st_. They are base64url-encoded and variable length. Do not attempt to parse or modify them — the encryption includes an authentication tag and any modification will cause a 400 error.


Persona — Writing a Good Domain Brief

The domain field is where you define how the AI reasons, not just what it is called. The difference between a mediocre persona and a sharp one is usually here.

Weak:

"domain": "You are a helpful assistant for career advice."

Strong:

"domain": "You work with professionals navigating major career transitions — promotions, pivots, and decisions about staying or leaving. You believe most career problems are communication problems in disguise. You push past the stated question to the underlying one, and you name what you observe rather than waiting to be asked. You do not tell people what they want to hear."

The stronger version tells the pipeline how to interpret ambiguity, what to probe for, and what the AI's underlying epistemology is. That framing shapes reasoning across every cycle of the session.

Constraints are not a substitute for domain. Constraints say what not to do. Domain says what to do. Both are needed but domain does the heavy lifting.


Confidence — In Depth

The confidence field is not a quality indicator. A low-confidence response is not a bad response. It means the pipeline is holding competing interpretations of the input and has not fully resolved them.

RangeWhat it meansHow to use it
0.0–0.50High ambiguity. Multiple interpretations remain genuinely unresolved.Consider surfacing a follow-up question to the user.
0.50–0.70Moderate confidence. One interpretation leads, others are not dismissed.Normal range for early-session philosophical encounters.
0.70–0.85Good confidence. Clear synthesis with acknowledged remaining uncertainty.Normal range for factual and task encounters.
0.85–1.0High confidence. Strong convergence on a single interpretation.Common for factual queries. Can also signal a session insight.

In practice: use confidence to decide whether to ask a clarifying question before showing the response, to flag responses for human review in high-stakes contexts, or to build "I am uncertain here — can you tell me more?" logic into your product.


Integration Patterns

Pattern 1 — New user session

async function startSession(userId, firstMessage, persona) {
  const res = await cortexiom.post('/v1/encounter', {
    message: firstMessage,
    persona,
  });

  await db.users.update(userId, {
    cx_state_token: res.state_token,
    cx_depth: res.depth,
  });

  return res.response;
}

Pattern 2 — Returning user

async function continueSession(userId, message) {
  const user = await db.users.find(userId);

  if (!user.cx_state_token) {
    throw new Error('No active session for this user');
  }

  const res = await cortexiom.post('/v1/encounter', {
    message,
    state_token: user.cx_state_token,
  });

  // Always update — never skip this
  await db.users.update(userId, {
    cx_state_token: res.state_token,
    cx_depth: res.depth,
  });

  return res;
}

Pattern 3 — Confidence-gated routing

async function encounter(userId, message) {
  const res = await continueSession(userId, message);

  if (res.confidence < 0.45) {
    return {
      response: res.response,
      follow_up_prompt: "Can you tell me more about what you mean by that?",
      needs_clarification: true,
    };
  }

  return { response: res.response, needs_clarification: false };
}

Pattern 4 — Streaming with typing indicator

async function streamEncounter(userId, message, onToken, onDone) {
  const user = await db.users.find(userId);

  const res = await fetch('https://api.cortexiom.com/v1/encounter', {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${process.env.CX_API_KEY}` },
    body: JSON.stringify({
      message,
      state_token: user.cx_state_token,
      stream: true,
    }),
  });

  const reader = res.body.getReader();
  const decoder = new TextDecoder();

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    for (const line of decoder.decode(value).split('\n')) {
      if (!line.startsWith('data: ')) continue;
      const event = JSON.parse(line.slice(6));

      switch (event.type) {
        case 'start_response': hideThinkingDots(); break;
        case 'token':          onToken(event.text); break;
        case 'done':
          await db.users.update(userId, { cx_state_token: event.state_token });
          onDone(event);
          break;
      }
    }
  }
}

Error Reference

All errors return JSON with an error field. Errors before the SSE stream opens are plain JSON. Errors during streaming arrive as { "type": "error", "error": "..." } events.

StatusMeaning
400Bad request — missing message, invalid state_token format, or tampered token.
401Invalid or missing API key.
402Encounter limit reached. Upgrade your plan.
405Method not allowed — use POST.
429Per-user rate limit exceeded (30 encounters per user per 24h).
500Pipeline error. The state token from the previous call is still valid — retry is safe.
{ "error": "Missing or malformed Authorization header" }
{ "error": "Invalid API key" }
{ "error": "message is required" }
{ "error": "Invalid or tampered state_token" }
{ "error": "Encounter limit reached. Upgrade your plan to continue.", "encounters_used": 50, "encounters_limit": 50 }
{ "error": "Daily limit of 30 cycles reached. Resets in 14 hours." }
{ "error": "Failed to process encounter" }

Rate Limits

Two separate rate limits apply:

Key-level (your account): Determined by your plan. Free tier: 50 total encounters across all users. PAYG and higher: as provisioned.

User-level (per state token): 30 encounters per user per 24-hour rolling window. This is enforced inside the encrypted state and resets automatically. If a user hits this limit, the API returns 429.


Security

Keep your API key server-side

Never include cx_live_... in client-side code, mobile app binaries, or public repositories. All calls to /v1/encounter should come from your backend.

Your User  →  Your Backend  →  Cortexiom API

Your backend authenticates your user, retrieves their state token from your database, calls Cortexiom, and returns only the response field to the client. The state_token never leaves your backend.

// Your API route — e.g. POST /api/chat
export default async function chat(req, res) {
  const user = await authenticate(req);
  const saved = await db.stateTokens.find(user.id);

  const cx = await fetch('https://api.cortexiom.com/v1/encounter', {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${process.env.CX_API_KEY}` },
    body: JSON.stringify({
      message: req.body.message,
      state_token: saved?.token,
    }),
  }).then(r => r.json());

  await db.stateTokens.upsert(user.id, cx.state_token);

  res.json({ response: cx.response, depth: cx.depth, confidence: cx.confidence });
}

State token custody

The state token is encrypted ciphertext. Treat it as sensitive data: store it in your database with the same care as a session token.


Frequently Asked Questions

Does the API store my users' data?

No. The Cortexiom API is stateless. We hold no user data between calls. The state token is the entirety of the user's context, and it lives in your database, encrypted. We cannot read it — we only process it for the duration of a single request.

What language model is running underneath?

The underlying language model is Claude by Anthropic. The reasoning system built on top of it is Cortexiom — a multi-step pipeline that structures how reasoning happens across each encounter.

How long does an encounter take?

Typically 5–10 seconds non-streaming. For latency-sensitive applications, use streaming so your users see tokens arriving immediately once the reasoning phase completes.

Can I read the state token?

No. It is AES-256-GCM encrypted with a key only Synexiom holds. What the token contains is not something we expose — only what it produces.

What happens if I don't pass state_token?

A fresh state is initialised. The user starts from zero — no memory of prior sessions.

Can I use one API key for all my users?

Yes. One API key serves your entire user base. The per-user context is carried by the state token, not by separate keys.

Can the persona change mid-session?

Yes. Pass a new persona object alongside a state_token to override the stored persona. The accumulated state (depth, tensions, self-model) is preserved — only the character layer changes.

Is there an SDK?

Not yet. An npm package and Python client are on the roadmap. For now, the examples in this guide are everything you need.


Glossary

TermDefinition
EncounterOne reasoning cycle: one user message in, one response out, state updated.
State tokenEncrypted blob encoding accumulated user context. You store it, we process it.
PersonaDeveloper-configured character: name, role, domain, constraints. Stored in state after the first call.
DepthCount of reasoning cycles with this user. Increments by 1 per encounter.
ConfidencePipeline's self-assessed certainty in the current response. Calibrated epistemic signal, not a quality score.
Fresh stateA new session with no accumulated context. Created when state_token is omitted.

Cortexiom API is developed and operated by Synexiom Labs Inc.
Questions: evolve@synexiomlabs.com

Cortexiom API · by Synexiom Labs Inc.

← Back to dashboard