Build with AI that refuses to be weaponized.

API access to Thaura's model: chat, vision, document parsing, and speech-to-text. Ethics, not extraction. It never trains on your data, and never will.

API Illustration

Quick Start Guide

Get up and running with the Thaura API in minutes

1

Authentication

Works with the OpenAI SDKs

Point any official OpenAI SDK at https://backend.thaura.ai/v1 with your Thaura key and model "thaura". Streaming, the stream() and runTools() helpers, parse() with JSON schemas, tool calling (including forced tool_choice), log probabilities and the SDK's error classes all work unchanged. The differences are listed below.

All requests must include an Authorization header with your API key:

Authorization: Bearer YOUR_API_KEY

API Access

Create your API key in the app: open your account menu (your name, at the bottom of the sidebar) → API → API Keys.

Prepaid Billing

Pay only for what you use, charged exactly: $0.50 per million input tokens and $2.00 per million output tokens, with nothing rounded up and no minimum charge (a call with 52 input and 18 output tokens costs $0.000062). Audio transcription is $0.006 per audio minute, charged by the millisecond. Add funds from your account menu → API → Billing.

While a request runs, the most it can cost is held on your balance: its input plus max_tokens of output (32,000 when you don't set it). When it ends you pay for the tokens it used and the rest is released. A request your balance can't cover is refused with 402 insufficient_balance, so on a small balance set a lower max_tokens. There is no minimum balance.

A request you cancel, or whose connection closes, before the model starts answering costs nothing. Once the model has started answering, its input and the output written until then are billed, streamed or not.

2

Inference Endpoint

Simplified Attachments

Now supports sending attachments as simple base64 strings! No need for complex object structures.

POST
/v1/chat/completions

Request Parameters:

Required
messagesMessage array. Can include custom system prompts via system role messages. Default: "You are Thaura, an ethical AI assistant."
Optional
modelModel to use: only "thaura" is supported for chat (default: "thaura"). Any other name returns 404 model_not_found. /v1/models also lists "thaura-whisper", the transcription model for /v1/audio/transcriptions, which is not valid here, so pin your client to "thaura" rather than letting it pick from the model list.
Optional
streamEnable SSE streaming (default: false). Recommended for long requests: the model may think before it answers, and a stream keeps the connection open while it does.
Optional
temperatureAccepted for compatibility (0.0-2.0) and checked, but not applied: the model always thinks before it answers, and its sampling is held at the model's own settings (temperature 1.0, top_p 0.95) so its reasoning stays reliable. Use seed for repeatable answers.
Optional
attachmentsFile attachments: simple base64 string or array (images, PDFs, audio)
Optional
max_tokensMaximum tokens to generate (deprecated name, still fully supported). Capped at 32000. If both this and max_completion_tokens are sent, max_completion_tokens wins. Under 16,000 it limits the answer itself, and the model gets extra room for its hidden thinking. At 16,000 or more, or when unset, the hidden thinking counts toward this limit. Thinking is never returned or billed.
Optional
max_completion_tokensMaximum tokens to generate. The current OpenAI SDK sends this name, and it takes precedence over max_tokens. Capped at 32000. Under 16,000 it limits the answer itself. At 16,000 or more, or when unset, the hidden thinking counts toward this limit. Thinking is never returned or billed.
Optional
response_formatControl the output format: {"type": "text"} (default), {"type": "json_object"} for any valid JSON, or {"type": "json_schema", "json_schema": {"name": ..., "schema": ..., "strict": true}} for JSON that matches your schema. The OpenAI SDK's parse() helper works with it.
Optional
toolsArray of function tools with JSON schemas. Parallel tool calls, 30+ tools, nested/enum/array argument schemas and strict:true schemas are all supported. When the model calls a tool, finish_reason is "tool_calls"; when streaming, each tool_calls delta carries an index so the OpenAI SDK can reassemble it. Custom tools (type "custom") are not supported and return 400.
Optional
tool_choice"auto" (default: the model calls a tool when it needs one), "none" (ordinary prose, never a tool call), "required" (the model must call one or more tools), {"type": "function", "function": {"name": "..."}} (the model must call that function), or {"type": "allowed_tools", "allowed_tools": {"mode": "auto" | "required", "tools": [...]}} (only those tools may be called). As on OpenAI, a call forced by name ends with finish_reason "stop", and "required" with "tool_calls". Naming a tool that isn't in tools returns 400.
Optional
parallel_tool_callsWhether the model may call several tools in one answer (default: true). With false, at most one tool call is returned.
Optional
functions, function_callThe legacy functions and function_call parameters are supported for older clients. They are read as tools and tool_choice, and the answer comes back as message.function_call with finish_reason "function_call". New code should use tools.
Optional
stopUp to 4 sequences where the answer stops (string or array). The stop text is not included in the output. Stop sequences apply to the visible answer, never to the model's hidden thinking or to a forced tool call's arguments.
Optional
seedInteger for best-effort deterministic sampling: the same seed and parameters usually return the same output, but it isn't guaranteed.
Optional
nNumber of choices. Only 1 is supported (the default); a larger n returns 400 unsupported_value.
Optional
logprobsReturn the log probability of each token of the answer (boolean, default false). Only the visible answer's tokens are returned, never the hidden thinking's.
Optional
top_logprobsWith logprobs: true, the number of most likely alternatives to return at each token (0-20).
Optional
storeAccepted for compatibility. Thaura never stores your completions, whatever this says.

Messages with the developer role are treated as system instructions.

Parameters accepted but not applied

temperature, top_p, frequency_penalty and presence_penalty are checked against OpenAI's ranges and then held at the model's own settings: the model always thinks before it answers, and changing its sampling makes that thinking unreliable. Thaura pins it so the API never quietly produces worse output than the product. logit_bias, reasoning_effort, verbosity, user, safety_identifier, prompt_cache_key, service_tier, prediction, web_search_options and moderation are accepted and have no effect. metadata and store are accepted, but Thaura never stores your completions.

Parameters that are rejected

n greater than 1 returns 400 unsupported_value: Thaura returns one choice per request, so send one request per choice. Custom tools, audio output (modalities with "audio", or audio) and top_logprobs without logprobs: true also return 400.

Rate limits

  • • 60 requests per minute per API key
  • • 8 concurrent requests per API key
  • • Over either limit returns 429 — retry after a moment. Agent frameworks spend several requests per user turn (one per tool round), so budget for that when sizing concurrency. Need more? Contact us and we will raise the ceiling on your key.

Limits

  • • Context window: 128,000 tokens per request, prompt and output together. max_tokens is lowered to fit what the prompt leaves; a prompt that leaves no room for an answer returns 400 context_length_exceeded.
  • • Output: up to 32,000 tokens per response, which is also the default when max_tokens isn't set.
  • • Attachments: up to 20 per message (images, PDFs and audio together).
  • • Request size: up to 50 MB of JSON per chat request, base64 files included (413 past it).
  • • Speech-to-text: files up to 50 MB and 60 minutes long.
POST
/v1/audio/transcriptions

Speech-to-text: upload an audio file as multipart form data, get the transcript back. Billed per audio minute. Full examples in the Speech-to-Text tab below.

3

Response Formats

Non-Streaming Response (Thaura Format):

{
  "id": "chatcmpl-...",
  "object": "chat.completion",
  "created": 1234567890,
  "model": "thaura",
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "content": "The AI response text..."
    },
    "finish_reason": "stop"
  }],
  "usage": {
    "prompt_tokens": 52,
    "completion_tokens": 18,
    "total_tokens": 70
  }
}

Streaming Response (Thaura SSE Format):

data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":1234567890,"model":"thaura","choices":[{"index":0,"delta":{"content":"Response "},"finish_reason":null}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":1234567890,"model":"thaura","choices":[{"index":0,"delta":{"content":"text..."},"finish_reason":null}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":1234567890,"model":"thaura","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: [DONE]

Streaming with Token Usage:

Token usage comes in its own chunk just before data: [DONE], with an empty choices array (the OpenAI shape), so read choices[0] only when choices isn't empty. It's on by default; send stream_options: {"include_usage": false} to turn it off.

usage follows OpenAI's shape: prompt_tokens_details.cached_tokens is the part of the prompt read from cache. completion_tokens counts only the visible answer, which is what you pay for, so completion_tokens_details.reasoning_tokens is always 0. The model's hidden thinking is never returned, counted or billed.

data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":1234567890,"model":"thaura","choices":[{"index":0,"delta":{"content":"text"},"finish_reason":null}]}
...
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":1234567890,"model":"thaura","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":1234567890,"model":"thaura","choices":[],"usage":{"prompt_tokens":52,"completion_tokens":18,"total_tokens":70,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}}}
data: [DONE]

Error Response:

{
  "error": {
    "message": "n greater than 1 is not supported: Thaura returns one choice per request. ...",
    "type": "invalid_request_error",
    "param": "n",
    "code": "unsupported_value"
  }
}

Status codes:

  • 400invalid_messages, unsupported_value, invalid_json_schema, invalid_type, invalid_value, decimal_below_min_value, decimal_above_max_value, integer_below_min_value, integer_above_max_value, array_above_max_length, missing_required_parameter — The request is malformed or asks for something unsupported: a bad messages array, a value outside OpenAI's range, n greater than 1, a tool_choice naming a tool that isn't in tools, a custom tool, or an invalid JSON schema. error.param names the field.
  • 400context_length_exceeded — The prompt is too long for the 128,000-token window, or carries more images than one request can.
  • 400too_many_attachments, invalid_attachments, invalid_image — More than 20 attachments in a message, an attachment that can't be read, or an image that can't be decoded.
  • 401unauthorized — The API key is missing or invalid.
  • 402insufficient_balance — Your balance can't cover this request's maximum cost. Add funds, or lower max_tokens.
  • 403key_scope — This key can't be used on this endpoint.
  • 404model_not_found — Unknown model: chat completions and /v1/models/{model} answer a model other than "thaura" with 404 model_not_found, and transcription answers an unknown transcription model the same way.
  • 413file_too_large — The request body, or the audio file, is over 50 MB.
  • 429rate_limit_exceeded, concurrency_limit_exceeded — More than 60 requests a minute, or 8 at once, on this key. Retry after a moment.
  • 500internal_error, transcription_failed — Something failed on our side. Retry the request.
  • 503service_unavailable, upstream_rate_limited — The model is temporarily unavailable or busy. Retry after retry_after_seconds.
  • 504upstream_timeout — The model took too long to answer. Retry the request.

Thaura answers an empty balance with 402 insufficient_balance (OpenAI uses 429 insufficient_quota). The SDK does not retry a 402.

Once a stream has started, an error arrives as a data: {"error": …} chunk with the same type and code, followed by data: [DONE].

Code Examples

Ready-to-use examples for common use cases

Simple Question

Basic API call with a simple question

curl -X POST https://backend.thaura.ai/v1/chat/completions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {"role": "system", "content": "You are an ethical AI assistant"},
      {"role": "user", "content": "What is 2+2?"}
    ],
    "stream": true
  }'

Start Building with Ethical AI Today

Create your API key in the app from your account menu → API, and start building with Thaura AI.