Chat API
OpenAI-compatible Chat Completions API with 20+ models, streaming, structured outputs, function calling and more.
OpenAI-compatible Chat Completions API with 20+ models, streaming, structured outputs, function calling and more.
Send chat messages and receive an AI-generated response.
/api/v1/llm/chat/completionsSDK compatibility
| Parameter | Type | Description |
|---|---|---|
modelrequired | string | Model ID, e.g. gpt-4o or claude-sonnet-4-20250514. |
messagesrequired | array | Array of messages with role and content. |
stream | boolean | If true, the response is streamed via SSE. |
temperature | number | Response creativity (0–2). Lower values = more focused. |
max_tokens | integer | Maximum number of tokens in the response. |
top_p | number | Nucleus sampling — alternative to temperature. |
response_format | object | Forces a specific output format (e.g. JSON). |
tools | array | List of tools/functions the model can call. |
tool_choice | string | Controls whether and which tools are called. |
frequency_penalty | number | Penalizes frequently used tokens (-2 to 2). |
presence_penalty | number | Penalizes already used tokens (-2 to 2). |
stop | string | array | Sequences at which generation stops. |
Each message has a role (system, user, assistant) and content.
[
{
"role": "system",
"content": "You are a helpful assistant."
},
{
"role": "user",
"content": "What is the capital of France?"
},
{
"role": "assistant",
"content": "The capital of France is Paris."
},
{
"role": "user",
"content": "And Germany?"
}
]Minimal request with a single user message.
1curl -X POST https://app.anymize.ai/api/v1/llm/chat/completions \2 -H #86efac">"Authorization: Bearer YOUR_API_KEY" \3 -H #86efac">"Content-Type: application/json" \4 -d '{5 #86efac">"model": "fountain-1.0",6 #86efac">"messages": [7 {#86efac">"role": "system", "content": "You are a helpful assistant."},8 {#86efac">"role": "user", "content": "Explain quantum computing in one sentence."}9 ],10 #86efac">"temperature": 0.7,11 #86efac">"max_tokens": 25612 }'The response contains the generated message, model info, and token usage.
{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"created": 1700000000,
"model": "fountain-1.0",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Quantum computing uses quantum-mechanical phenomena like superposition and entanglement to process information in ways that classical computers cannot."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 28,
"completion_tokens": 24,
"total_tokens": 52
}
}Every response includes prompt_tokens, completion_tokens, and total_tokens.
When sending pre-anonymized text to the standard chat endpoint, the model must preserve [[Type-HASH]] placeholders exactly. Add the following system prompt to your messages.
Without prompt
Dear [name redacted], regarding your request...
With prompt
Dear Mr. [[Person-ABC123]], regarding your request...
Without explicit instructions, the model replaces placeholders with generic descriptions like '[redacted]'. This breaks the mapping for de-anonymization.
When processing pre-anonymized text, add this part to your system prompt:
1const response = await client.chat.completions.create({2 model: "fountain-1.0",3 messages: [4 {5 role: "system",6 content: `## CRITICAL RULE: ANONYMIZATION PLACEHOLDERS78The user's messages contain anonymized placeholders in format [[Type-HASH]]:9- [[Person-QSEZB6]] = a person's name10- [[email-BE2966]] = an email address11- [[iban-5B7BCF]] = a bank account12- [[telephone_number-F29732]] = a phone number1314FORBIDDEN:15- Writing "[Name anonymisiert]" or "[anonymized]"16- Describing WHAT the placeholder is instead of USING it1718REQUIRED:19- Copy [[Person-QSEZB6]] exactly as-is20- Write "Herr [[Person-QSEZB6]] hat..." (use it like a real name)2122WHY: After your response, placeholders get replaced with real values.`,23 },24 {25 role: "user",26 content: "Schreibe eine E-Mail an [[Person-ABC123]] bezuglich dem Vertrag.",27 },28 ],29})3031// Model responds: "Sehr geehrter Herr [[Person-ABC123]], ..."32// After de-anonymization: "Sehr geehrter Herr Max Mustermann, ..."Or use the anonymous endpoint
Set stream: true in the request to receive responses in real time.
/api/v1/llm/chat/completionsResponses arrive as Server-Sent Events — one chunk per line with a data: prefix.
data: {"id": "chatcmpl-abc123","object": "chat.completion.chunk","created": 1700000000,"model": "fountain-1.0","choices":[{"index": 0,"delta":{"content": "Hello"},"finish_reason": null}]}
data: {"id": "chatcmpl-abc123","object": "chat.completion.chunk","created": 1700000000,"model": "fountain-1.0","choices":[{"index": 0,"delta":{"content": " world"},"finish_reason": null}]}
data: {"id": "chatcmpl-abc123","object": "chat.completion.chunk","created": 1700000000,"model": "fountain-1.0","choices":[{"index": 0,"delta":{},"finish_reason": "stop"}]}
data: [DONE]Each chunk contains a delta object with the new text fragment.
{
"id": "chatcmpl-abc123",
"object": "chat.completion.chunk",
"created": 1700000000,
"model": "fountain-1.0",
"choices": [
{
"index": 0,
"delta": {
"content": "Hello"
},
"finish_reason": null
}
]
}Read the stream line by line and parse each data: line as JSON.
1curl -X POST https://app.anymize.ai/api/v1/llm/chat/completions \2 -H #86efac">"Authorization: Bearer YOUR_API_KEY" \3 -H #86efac">"Content-Type: application/json" \4 -d '{5 #86efac">"model": "fountain-1.0",6 #86efac">"messages": [7 {#86efac">"role": "user", "content": "Write a short poem about the sea."}8 ],9 #86efac">"stream": true10 }'The first chunk typically contains the role and an empty content delta.
{
"id": "chatcmpl-abc123",
"object": "chat.completion.chunk",
"created": 1700000000,
"model": "fountain-1.0",
"choices": [
{
"index": 0,
"delta": {
"role": "assistant",
"content": ""
},
"finish_reason": null
}
]
}Token info during streaming
Force structured JSON outputs from the model — ideal for data extraction and APIs.
Set response_format to json_object to enforce valid JSON output.
/api/v1/llm/chat/completions1curl -X POST https://app.anymize.ai/api/v1/llm/chat/completions \2 -H #86efac">"Authorization: Bearer YOUR_API_KEY" \3 -H #86efac">"Content-Type: application/json" \4 -d '{5 #86efac">"model": "fountain-1.0",6 #86efac">"messages": [7 {#86efac">"role": "system", "content": "You extract contact info. Respond in JSON with keys: name, email, phone."},8 {#86efac">"role": "user", "content": "My name is Anna Schmidt, email anna@example.com, phone +49 170 1234567."}9 ],10 #86efac">"response_format": {"type": "json_object"}11 }'{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"model": "fountain-1.0",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "{\"name\": \"Anna Schmidt\", \"email\": \"anna@example.com\", \"phone\": \"+49 170 1234567\"}"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 42,
"completion_tokens": 28,
"total_tokens": 70
}
}Define an exact schema for the output — the model will follow it strictly.
1curl -X POST https://app.anymize.ai/api/v1/llm/chat/completions \2 -H #86efac">"Authorization: Bearer YOUR_API_KEY" \3 -H #86efac">"Content-Type: application/json" \4 -d '{5 #86efac">"model": "fountain-1.0",6 #86efac">"messages": [7 {#86efac">"role": "user", "content": "List three European capitals with their countries and population."}8 ],9 #86efac">"response_format": {10 #86efac">"type": "json_schema",11 #86efac">"json_schema": {12 #86efac">"name": "capitals",13 #86efac">"schema": {14 #86efac">"type": "object",15 #86efac">"properties": {16 #86efac">"capitals": {17 #86efac">"type": "array",18 #86efac">"items": {19 #86efac">"type": "object",20 #86efac">"properties": {21 #86efac">"city": {"type": "string"},22 #86efac">"country": {"type": "string"},23 #86efac">"population": {"type": "number"}24 },25 #86efac">"required": ["city", "country", "population"]26 }27 }28 },29 #86efac">"required": ["capitals"]30 }31 }32 }33 }'Prompt tip
Function Calling lets the model call your defined tools. Instead of just generating text, the model recognizes when an external tool would be helpful and returns the parameters. You execute the function locally and send the result back.
The flow in four steps:
Web search (Brave, Google, etc.)
Database queries and CRM systems
Email and messaging
External APIs (weather, calendar, maps, etc.)
Tools are defined as JSON Schema. The model uses the descriptions to decide when to call which tool.
{
"type": "function",
"function": {
"name": "web_search",
"description": "Search the web for current information",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "The search query"
}
},
"required": [
"query"
]
}
}
}A complete example: The model recognizes that current information is needed, calls the Brave Search API, and summarizes the results.
1import OpenAI from "openai"23const client = new OpenAI({4 apiKey: "YOUR_API_KEY",5 baseURL: "https://app.anymize.ai/api/v1/llm",6})78const BRAVE_API_KEY = process.env.BRAVE_API_KEY910// Step 1: Define the tool11const tools = [12 {13 type: "function" as const,14 function: {15 name: "web_search",16 description: "Search the web for current information. Use this when the user asks about recent events, news, or anything that requires up-to-date data.",17 parameters: {18 type: "object",19 properties: {20 query: { type: "string", description: "Search query" },21 },22 required: ["query"],23 },24 },25 },26]2728// Step 2: Send message with tools29const response = await client.chat.completions.create({30 model: "fountain-1.0",31 messages: [32 { role: "user", content: "What are the latest AI news today?" },33 ],34 tools,35 tool_choice: "auto",36})3738const message = response.choices[0].message3940// Step 3: Check if the model wants to call a tool41if (message.tool_calls && message.tool_calls.length > 0) {42 const toolCall = message.tool_calls[0]43 const args = JSON.parse(toolCall.function.arguments)4445 // Step 4: Execute the Brave Search API46 const searchResponse = await fetch(47 `https://api.search.brave.com/res/v1/web/search?q=${encodeURIComponent(args.query)}&count=5`,48 { headers: { "X-Subscription-Token": BRAVE_API_KEY } },49 )50 const searchData = await searchResponse.json()5152 // Format results for the model53 const results = searchData.web?.results54 ?.map((r: any) => `${r.title}: ${r.description}`)55 .join("\n") || "No results found"5657 // Step 5: Send the search results back to the model58 const finalResponse = await client.chat.completions.create({59 model: "fountain-1.0",60 messages: [61 { role: "user", content: "What are the latest AI news today?" },62 message,63 {64 role: "tool",65 tool_call_id: toolCall.id,66 content: results,67 },68 ],69 })7071 console.log(finalResponse.choices[0].message.content)72}When the model wants to call a tool, the response contains tool_calls instead of content. The finish_reason is 'tool_calls'.
{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"model": "fountain-1.0",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_abc123",
"type": "function",
"function": {
"name": "web_search",
"arguments": "{\"query\": \"latest AI news today\"}"
}
}
]
},
"finish_reason": "tool_calls"
}
]
}Check finish_reason
You can define multiple tools. The model automatically picks the right one based on the message.
1const tools = [2 {3 type: "function",4 function: {5 name: "web_search",6 description: "Search the web for current information",7 parameters: {8 type: "object",9 properties: {10 query: { type: "string" },11 },12 required: ["query"],13 },14 },15 },16 {17 type: "function",18 function: {19 name: "get_weather",20 description: "Get current weather for a location",21 parameters: {22 type: "object",23 properties: {24 location: { type: "string" },25 },26 required: ["location"],27 },28 },29 },30 {31 type: "function",32 function: {33 name: "send_email",34 description: "Send an email to a recipient",35 parameters: {36 type: "object",37 properties: {38 to: { type: "string", description: "Email address" },39 subject: { type: "string" },40 body: { type: "string" },41 },42 required: ["to", "subject", "body"],43 },44 },45 },46]4748// The model picks the right tool based on the user's message49const response = await client.chat.completions.create({50 model: "fountain-1.0",51 messages: [52 { role: "user", content: "Search for the latest Next.js release" },53 ],54 tools,55 tool_choice: "auto",56})Use tool_choice to control if and how the model uses tools.
| Parameter | Type | Description |
|---|---|---|
"auto" | string | Model decides on its own (default) |
"none" | string | No tool will be called |
"required" | string | Model must call a tool |
{"type": "function", ...} | object | Force a specific function call |
Function Calling is the foundation for the Model Context Protocol (MCP) and similar tool platforms. You can integrate MCP servers as function calling tools by passing the MCP server's tool definitions as the tools parameter.
MCP compatible
Reasoning models show their thought process — ideal for complex logic and multi-step problems.
Different models offer reasoning in different ways.
waterfall-1.0Models with built-in chain-of-thought like o1 and o3.Control reasoning effort via the reasoning_effort parameter.
/api/v1/llm/chat/completions| Parameter | Type | Description |
|---|---|---|
reasoning.effortrequired | string | Determines how much the model thinks before responding. |
"low"Quick response with minimal thinking."medium"Balanced mode — good for most tasks."high"Maximum thinking for complex problems.Request to a reasoning model with medium effort.
1curl -X POST https://app.anymize.ai/api/v1/llm/chat/completions \2 -H #86efac">"Authorization: Bearer YOUR_API_KEY" \3 -H #86efac">"Content-Type: application/json" \4 -d '{5 #86efac">"model": "waterfall-1.0",6 #86efac">"messages": [7 {#86efac">"role": "user", "content": "A farmer has 17 sheep. All but 9 run away. How many sheep does he have left?"}8 ],9 #86efac">"reasoning": {10 #86efac">"effort": "high"11 }12 }'The response contains the visible thought process and the final answer.
{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"model": "waterfall-1.0",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "The farmer has 9 sheep left. The phrase \"all but 9\" means every sheep except 9 ran away."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 32,
"completion_tokens": 45,
"total_tokens": 77,
"reasoning_tokens": 128
}
}Token usage note
Recommendation
Simplified API format for quick integrations — inspired by the Responses format.
/api/v1/llm/responsesCompatibility
| Parameter | Type | Description |
|---|---|---|
modelrequired | string | Model ID, same as Chat Completions. |
inputrequired | string | array | Input as a string or array of messages. |
instructions | string | System instructions as a string (replaces the system role). |
temperature | number | Response creativity (0–2). |
max_output_tokens | integer | Maximum number of tokens in the response. |
top_p | number | Nucleus sampling parameter. |
You can send input as a simple string or as a message array.
{
"model": "fountain-1.0",
"input": "What is the capital of France?"
}{
"model": "fountain-1.0",
"input": [
{
"role": "user",
"content": "What is the capital of France?"
}
],
"instructions": "You are a helpful geography assistant."
}1curl -X POST https://app.anymize.ai/api/v1/llm/responses \2 -H #86efac">"Authorization: Bearer YOUR_API_KEY" \3 -H #86efac">"Content-Type: application/json" \4 -d '{5 #86efac">"model": "fountain-1.0",6 #86efac">"input": "Explain quantum computing in one sentence.",7 #86efac">"instructions": "You are a helpful science assistant."8 }'The response follows the Responses format with output_text as the main field.
{
"id": "resp-abc123",
"object": "response",
"created_at": 1700000000,
"model": "fountain-1.0",
"output": [
{
"type": "message",
"role": "assistant",
"content": [
{
"type": "output_text",
"text": "Quantum computing uses quantum-mechanical phenomena like superposition and entanglement to process information in ways that classical computers cannot."
}
]
}
],
"usage": {
"input_tokens": 24,
"output_tokens": 28,
"total_tokens": 52
}
}Comparison between Chat Completions and Responses API.
| Feature | Chat API | Responses API |
|---|---|---|
| Endpoint | /chat/completions | /responses |
| Input | messages | input |
| System prompt | system role message | instructions |
| Response object | chat.completion | response |
| Response text | choices[0].message.content | output[0].content[0].text |
| Token usage | prompt_tokens / completion_tokens | input_tokens / output_tokens |
Combine chat and anonymization in a single request — your data is masked before reaching the model.
/api/v1/llm-anonymous/chat/completionshttps://app.anymize.ai/api/v1/llm-anonymousHere's how anonymous chat processes your request:
Higher Latency
Same parameters as Chat Completions plus anonymization options.
| Parameter | Type | Description |
|---|---|---|
modelrequired | string | Model ID — all chat models are supported. |
messagesrequired | array | Array of messages (system, user, assistant). |
language | string | Text language for better PII detection. |
stream | boolean | Enable SSE streaming. |
In anonymous chat, personal data is automatically replaced with placeholders in the format [[Type-HASH]]. For de-anonymization to work, the model must preserve these placeholders exactly.
Wrong
Dear [name redacted], I am writing to you regarding...
Correct
Dear Mr. [[Person-ABC123]], I am writing to you regarding...
Without the right system prompt, the model often writes 'an anonymized person' or '[name redacted]' instead of using the placeholder [[Person-ABC123]]. This makes de-anonymization impossible.
The anonymous endpoint automatically appends the following part to your system prompt. It is added to your own system prompt, not replacing it:
1## CRITICAL RULE: ANONYMIZATION PLACEHOLDERS23THIS IS THE MOST IMPORTANT RULE. VIOLATING IT MAKES YOUR RESPONSE USELESS.45The user's messages contain anonymized placeholders in format [[Type-HASH]]:6- [[Person-QSEZB6]] = a person's name7- [[email-BE2966]] = an email address8- [[iban-5B7BCF]] = a bank account9- [[telephone_number-F29732]] = a phone number10- [[Adress-NT9DQE]] = an address1112FORBIDDEN:13- Writing "[Name anonymisiert]" or "[anonymized]"14- Describing WHAT the placeholder is instead of USING it15- Inventing NEW [[Type-HASH]] placeholders1617REQUIRED:18- Copy [[Person-QSEZB6]] exactly as-is19- Write "Herr [[Person-QSEZB6]] hat..." (use it like a real name)2021WHY: After your response, placeholders get replaced with real values.22BEFORE RESPONDING: Check that every [[Placeholder-HASH]] appears exactly as written.Automatically injected
1curl -X POST https://app.anymize.ai/api/v1/llm-anonymous/chat/completions \2 -H #86efac">"Authorization: Bearer YOUR_API_KEY" \3 -H #86efac">"Content-Type: application/json" \4 -d '{5 #86efac">"model": "fountain-1.0",6 #86efac">"messages": [7 {#86efac">"role": "user", "content": "Schreibe eine E-Mail an Max Mustermann, max@example.com, wegen dem Termin am 15. Januar."}8 ],9 #86efac">"language": "de",10 }'The response contains the de-anonymized text and metadata.
{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"model": "fountain-1.0",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Sehr geehrter Herr Max Mustermann,\n\nich schreibe Ihnen bezüglich unseres Termins am 15. Januar..."
},
"finish_reason": "stop"
}
],
"_anymize": {
"anonymized": true,
"job_id": "job_anon_456def",
"language": "de"
}
}Response header
Zero Data Retention
Anonymous chat consumes credits for two services:
Retrieve all available models and their metadata.
/api/v1/llm/models1curl https://app.anymize.ai/api/v1/llm/models \2 -H #86efac">"Authorization: Bearer YOUR_API_KEY"The response contains an array of all models with ID, provider, and capabilities.
{
"object": "list",
"data": [
{
"id": "fountain-1.0",
"object": "model",
"owned_by": "anymize"
},
{
"id": "claude-sonnet-4-5-20250514",
"object": "model",
"owned_by": "anthropic"
},
{
"id": "gpt-5",
"object": "model",
"owned_by": "openai"
},
{
"id": "gemini-2.5-flash",
"object": "model",
"owned_by": "google"
}
]
}Retrieve details for a specific model.
/api/v1/llm/models/{id}1curl https://app.anymize.ai/api/v1/llm/models/fountain-1.0 \2 -H #86efac">"Authorization: Bearer YOUR_API_KEY"{
"id": "fountain-1.0",
"object": "model",
"owned_by": "anymize"
}Models are grouped by provider — here's an overview.
| Provider | Models |
|---|---|
| Anthropic | Claude 4.5 Haiku, Claude Sonnet 4.6, Claude Opus 4.6 |
| OpenAI | GPT-5, GPT-5 Mini |
| Gemini 2.5 Flash, Gemini 3.0 Flash, Gemini 3.1 Pro | |
| Mistral | Mistral Medium 3 |
| Perplexity | Perplexity Pro |
| anymize | fountain-1.0, waterfall-1.0 |
Token pricing varies by model and direction.
| Model | Input / 1M tokens | Output / 1M tokens |
|---|---|---|
fountain-1.0 | 0.15 EUR | 0.60 EUR |
waterfall-1.0 | 0.60 EUR | 3.00 EUR |
Claude 4.5 Haiku | 1.00 EUR | 5.00 EUR |
Claude Sonnet 4.6 | 3.00 EUR | 15.00 EUR |
Claude Opus 4.6 | 5.00 EUR | 25.00 EUR |
GPT-5 | 1.50 EUR | 10.00 EUR |
GPT-5 Mini | 0.30 EUR | 2.00 EUR |
Gemini 2.5 Flash | 0.15 EUR | 0.60 EUR |
Gemini 3.0 Flash | 0.30 EUR | 2.50 EUR |
Gemini 3.1 Pro | 2.00 EUR | 12.00 EUR |
Mistral Medium 3 | 0.80 EUR | 2.50 EUR |
Perplexity Pro | 3.00 EUR | 15.00 EUR |
Pricing note
Just replace the base URL in your existing setup. Everything else stays the same.
https://app.anymize.ai/api/v1/llmhttps://app.anymize.ai/api/v1/llm-anonymousUse the official OpenAI SDK with anymize as base URL.
1import OpenAI from "openai"23const client = new OpenAI({4 apiKey: "YOUR_API_KEY",5 baseURL: "https://app.anymize.ai/api/v1/llm",6})78const response = await client.chat.completions.create({9 model: "fountain-1.0",10 messages: [{ role: "user", content: "Hello!" }],11})Universal compatibility
Use anymize directly in your n8n workflows. Set the base URL in the OpenAI Chat node or HTTP Request node.

Example: OpenAI Chat node in n8n with anymize base URL
1. Open the OpenAI Chat node in n8n and set the base URL to https://app.anymize.ai/api/v1/llm
2. Enter your anymize API key as Bearer token
3. Select a model (e.g. fountain-1.0) and start your workflow