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):
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
modelstringID 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.
{
"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.
classifypresetDetermines category, language and a confidence score. Response as JSON.
ocrpresetRecognizes and structures the full text from scanned documents or photos.
splitpresetDetects 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.
{
"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
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);
}
}
}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.
curl https://neurolism.com/api/models7. Errors & billing
Errors come back as an HTTP status code with a JSON body {"error": string, "code"?: string}. The most important ones:
401UnauthorizedAPI key missing, invalid or revoked.
400Bad RequestInvalid request (e.g. empty messages, missing model).
402Payment RequiredThe organization's credit balance is exhausted - top up in the Enterprise portal.
500Server ErrorUnexpected 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