For developers

Neurolism API

Integrate Neurolism into your own applications, automations and internal tools. The API is available to Enterprise organizations and is billed by token usage - no separate SDK, a single HTTP endpoint with Server-Sent-Events streaming.

1. Authentication

Every request needs an organization API key in the Authorization header. Create a key in the Enterprise portal under "API keys" - the plaintext key is shown only once at creation and can be revoked at any time.

Header: Authorization: Bearer nl_org_...

API keys always belong to an organization, not an individual person - requests made via a key run server-side as an anonymous service account (no chat history, no conversation is stored).

2. Quick start

A minimal call you can run straight in your terminal (the response arrives as a Server-Sent-Events stream):

bash
curl -N https://neurolism.com/api/chat \
  -H "Authorization: Bearer nl_org_DEIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "neurolism-g",
    "messages": [
      { "role": "user", "content": "Erklär mir in einem Satz, was Neurolism ist." }
    ]
  }'

3. Request format

POST to /api/chat with a JSON body. Required fields are messages and model; all other fields are optional.

Fields

modelstring

ID from GET /api/models - currently neurolism-g (general) or neurolism-c (code/CLI).

messagesMessage[]

Conversation history as an array. Each message: {"role": "user"|"assistant", "content": string, "attachments"?: Attachment[]}. The last message must have role "user".

reasoning"low" | "medium" | "high"

Model thinking depth: "low" (default, fastest), "medium" or "high" (more thorough, slower).

attachmentsAttachment[]

Optional file attachments per message (max. 5, each up to ~10 MB): {"kind": "image"|"document", "mediaType": string, "data": string, "name"?: string}. data is Base64 WITHOUT the data: prefix. Images (PNG/JPEG/GIF/WebP) are seen directly by the model; PDFs are extracted to text server-side.

preset"classify" | "ocr" | "split"

Optional: activates a prebuilt solution (see section 4) and replaces the system prompt for focused, structured output. Without this field the request runs as a normal chat call.

json
{
  "model": "neurolism-g",
  "messages": [
    { "role": "user", "content": "Fasse den Anhang zusammen.",
      "attachments": [
        { "kind": "document", "mediaType": "application/pdf",
          "name": "bericht.pdf", "data": "<base64, ohne data:-Präfix>" }
      ]
    }
  ],
  "reasoning": "medium"
}

4. Prebuilt solutions

For recurring document processing there are three specialized, prebuilt solutions - usable exclusively via the API through the preset field, not selectable as a skill in the chat interface. Each request processes exactly one document (as an attachment or text in content) and returns a structured response, usually JSON.

classifypreset

Determines category, language and a confidence score. Response as JSON.

ocrpreset

Recognizes and structures the full text from scanned documents or photos.

splitpreset

Detects the boundaries of individual documents in a batch scan and splits them apart. Response as JSON.

Custom categories (classify only)

categoriesstring[]

Optional, fixed list of allowed categories (e.g. ["Invoice", "Contract", "Other"]). If set, the model assigns the document to EXACTLY ONE of them instead of categorizing freely. Without this field the model picks the category itself.

json
{
  "model": "neurolism-g",
  "preset": "classify",
  "categories": ["Rechnung", "Vertrag", "Kündigung", "Antrag", "Sonstiges"],
  "messages": [
    { "role": "user", "content": "",
      "attachments": [
        { "kind": "document", "mediaType": "application/pdf",
          "name": "dokument.pdf", "data": "<base64, ohne data:-Präfix>" }
      ]
    }
  ]
}

5. Streaming response

The response is a text/event-stream with the following events, in this order:

event: start{"chatId": null}

Stream starts. chatId is always null for API keys (no history).

event: thinking{"text": string}

Optional interim status (e.g. during a web search) - safe to skip.

event: delta{"text": string}

A text fragment of the reply. Concatenating them gives the full text.

event: done{"chatId": null, "title": null, "stopReason": string}

Stream finished. stopReason is e.g. end_turn, max_tokens or tool_use.

event: error{"message": string}

Error during the stream - message is already user-friendly.

Example: reading the stream

javascript
const res = await fetch("https://neurolism.com/api/chat", {
  method: "POST",
  headers: {
    Authorization: "Bearer nl_org_DEIN_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "neurolism-g",
    messages: [{ role: "user", content: "Sag Hallo." }],
  }),
});

const reader = res.body.getReader();
const decoder = new TextDecoder();
let buffer = "", answer = "";

for (;;) {
  const { done, value } = await reader.read();
  if (done) break;
  buffer += decoder.decode(value, { stream: true });

  let idx;
  while ((idx = buffer.indexOf("\n\n")) !== -1) {
    const frame = buffer.slice(0, idx);
    buffer = buffer.slice(idx + 2);

    const event = /^event: (.+)$/m.exec(frame)?.[1];
    const data = /^data: (.+)$/m.exec(frame)?.[1];
    if (!data) continue;
    const payload = JSON.parse(data);

    if (event === "delta") {
      answer += payload.text;
      process.stdout.write(payload.text); // live ausgeben
    } else if (event === "error") {
      throw new Error(payload.message);
    }
  }
}
python
import httpx, json

url = "https://neurolism.com/api/chat"
headers = {"Authorization": "Bearer nl_org_DEIN_KEY"}
body = {
    "model": "neurolism-g",
    "messages": [{"role": "user", "content": "Sag Hallo."}],
}

answer = ""
with httpx.stream("POST", url, headers=headers, json=body, timeout=120) as res:
    event = None
    for line in res.iter_lines():
        if line.startswith("event:"):
            event = line[6:].strip()
        elif line.startswith("data:"):
            payload = json.loads(line[5:].strip())
            if event == "delta":
                answer += payload["text"]
                print(payload["text"], end="", flush=True)
            elif event == "error":
                raise RuntimeError(payload["message"])

6. Models

GET /api/models (no API key required) lists the available models: neurolism-g (general-purpose, for chat/analysis/research) and neurolism-c (tuned for code and terminal workflows, powers the CLI). Both IDs stay stable even as the underlying model is updated.

bash
curl https://neurolism.com/api/models

7. Errors & billing

Errors come back as an HTTP status code with a JSON body {"error": string, "code"?: string}. The most important ones:

401Unauthorized

API key missing, invalid or revoked.

400Bad Request

Invalid request (e.g. empty messages, missing model).

402Payment Required

The organization's credit balance is exhausted - top up in the Enterprise portal.

500Server Error

Unexpected error on our side - if it persists, contact team@neurolism.com.

Billing is by token (input and output priced separately) from the organization's balance - see the Enterprise page for current prices. There is no separate daily limit for API calls.

8. Support

Questions about integration, custom limits or API keys: team@neurolism.com. We typically reply within one business day.

Go to the Enterprise portal