Support chat inside your product
Answer questions inside your product with a streaming chat model through the OpenAI-compatible endpoint. Each tenant is a customer tag, so the cost of the assistant is known per account.
Request
POST https://api.tovano.ai/v1/chat/completions Authorization: Bearer $TOVANO_API_KEY Content-Type: application/json X-Tovano-Customer: tenant-1093 { "model": "text/demo-chat-1", "stream": true, "stream_options": { "include_usage": true }, "messages": [ { "role": "system", "content": "You are the support assistant for a payroll product. Answer only from the help-centre excerpts below. …" }, { "role": "user", "content": "How do I correct a payslip after it has been sent?" } ] }
Response · Last chunk before [DONE]
Waiting for the run to finish.
{
"id": "chatcmpl_7b9a836b04",
"object": "chat.completion.chunk",
"model": "text/demo-chat-1",
"choices": [],
"usage": {
"prompt_tokens": 3120,
"completion_tokens": 410,
"total_tokens": 3530
},
"tovano": {
"task_id": "tsk_a471ed2469fc",
"charged_micro": 4760
}
}Tasks
7 tasks
-
Completed $0.00476
tenant-1093 · payslip correction
tsk_a471ed2469fc · 3,120 in · 410 out tokens
-
Completed $0.00388
tenant-0218 · leave balance
tsk_7c28fd439bac · 2,480 in · 350 out tokens
-
Completed $0.00609
tenant-0771 · tax code change
tsk_3f4d0a7258fe · 4,010 in · 520 out tokens
-
Completed $0.00409
tenant-1093 · bank details
tsk_25da86f96c0e · 2,890 in · 300 out tokens
-
Completed $0.00539
tenant-0450 · overtime rules
tsk_3fbe0450f840 · 3,550 in · 460 out tokens
-
Completed $0.00294
tenant-0218 · new starter
tsk_379c563fed7e · 1,980 in · 240 out tokens
-
Completed $0.00482
tenant-0904 · year-end report
tsk_fac0636ec054 · 3,300 in · 380 out tokens
Output
How do I correct a payslip after it has been sent?
Issue a correction run. Open Payroll, choose the pay period and the employee, then select Correct payslip. The employee receives the corrected payslip, the original is marked as replaced, and any difference is carried into the next run. If the period is already closed, reopen it first under Settings, Pay periods.
Events
- 0:00.0POST /v1/chat/completions · 7 requests streaming
- 0:05.0tsk_7c28fd439bac completed · $0.00388
- 0:06.0tsk_25da86f96c0e completed · $0.00409
- 0:07.2tsk_a471ed2469fc completed · $0.00476
- 0:07.2tsk_3f4d0a7258fe completed · $0.00609
- 0:07.2tsk_379c563fed7e completed · $0.00294
- 0:08.2tsk_3fbe0450f840 completed · $0.00539
- 0:08.8tsk_fac0636ec054 completed · $0.00482
- 0:09.6Done · 7 tasks · $0.03197 charged
A played-back run with realistic requests, responses and charges. No API call is made and no key is used. Times are compressed.
Cost of this run
$0.03197 for 7 tasks
| Model | Usage | Amount | |
|---|---|---|---|
| Demo Chat 1 text/demo-chat-121,330 input tokens × $1.00 / 1M input tokens | $0.02133 | ||
| Demo Chat 1 text/demo-chat-12,660 output tokens × $4.00 / 1M output tokens | $0.01064 | ||
| Total | $0.03197 |
Unit prices from the model catalogue, in US dollars, excluding tax. Agent jobs are charged per step at each step model's price.
At your volume
What a month costs
List prices. Committed-volume pricing, invoicing and an SLA are agreed in your contract. Talk to sales
How it works
Three calls you would write anyway.
- 1
Use the client you have
The chat endpoint speaks the OpenAI format, including streaming. Point an existing client at api.tovano.ai/v1 and keep your code.
- 2
Tenant as customer tag
Send X-Tovano-Customer with every request. Token spend per tenant comes back from /v1/usage, ready for a usage-based plan or a fair-use limit.
- 3
Charge in the stream
The last chunk carries the token counts and the exact charge, so you can log the cost of every reply next to the conversation.
The code
Copy it, add your key, run it.
The same request in curl, TypeScript and Python. The TypeScript client is tovano on npm.
curl https://api.tovano.ai/v1/chat/completions \ -H "Authorization: Bearer $TOVANO_API_KEY" \ -H "Content-Type: application/json" \ -H "X-Tovano-Customer: tenant-1093" \ -d '{ "model": "text/demo-chat-1", "stream": true, "stream_options": { "include_usage": true }, "messages": [ { "role": "system", "content": "You are the support assistant for a payroll product. Answer only from the help-centre excerpts below." }, { "role": "user", "content": "How do I correct a payslip after it has been sent?" } ] }' # Server-sent events. The last chunk has "usage" and "tovano": { "task_id", "charged_micro" }.
import Tovano, { type ChatMessage } from "tovano";
const tovano = new Tovano();
export async function* answer(tenantId: string, messages: ChatMessage[]) {
const stream = tovano.chat.completions.create({
model: "text/demo-chat-1",
messages,
stream: true,
stream_options: { include_usage: true },
customer: tenantId, // spend per tenant
});
for await (const chunk of stream) {
const text = chunk.choices[0]?.delta?.content;
if (text) yield text;
if (chunk.tovano) log.cost(tenantId, chunk.tovano.charged_micro);
}
}import os, json, requests
r = requests.post(
"https://api.tovano.ai/v1/chat/completions",
headers={
"Authorization": f"Bearer {os.environ['TOVANO_API_KEY']}",
"X-Tovano-Customer": tenant_id,
},
json={
"model": "text/demo-chat-1",
"stream": True,
"stream_options": {"include_usage": True},
"messages": messages,
},
stream=True,
)
for line in r.iter_lines():
if not line.startswith(b"data: ") or line == b"data: [DONE]":
continue
chunk = json.loads(line[6:])
for choice in chunk["choices"]:
print(choice["delta"].get("content", ""), end="", flush=True)
if "tovano" in chunk:
log_cost(tenant_id, chunk["tovano"]["charged_micro"])More examples
What else teams run at volume.
Run it on your volume, with your contract.
Committed-volume pricing, monthly invoices, higher limits and a named contact for teams that run AI in production.