Token counting
Find out how many input tokens a request would use before you send it. The count uses the model’s real tokenizer and includes everything that is billed as input: the Syntic identity instruction, your system message, every message, tool definitions, images and documents. The model is not run, and counting is free.
When to use it
- Check that a long conversation or document still fits the context window.
- Estimate cost before a large job or batch.
- Decide when to trim or summarise history, or turn on context management.
- Show users how much room is left in a chat.
Endpoint
POST https://app.syntic.ai/v1/chat/completions/count_tokens
Authorization: Bearer sk_live_...
Content-Type: application/jsonA matching POST /v1/messages/count_tokens takes the Messages body.
Request body
The same body you would send to /v1/chat/completions. These fields affect the count:
| Field | Counted |
|---|---|
model | Required. Tokenizers differ between models. |
messages | Yes, including text, images, files and tool calls/results. |
tools | Yes, as they would be presented to the model. |
response_format | Yes, the schema adds input tokens. |
reasoning, mcp_servers | Yes, for any instructions they add. |
Fields that only affect output (max_tokens, stream, temperature, stop) are accepted and ignored, so you can pass your real request unchanged.
Response
{
"object": "token_count",
"model": "Amara S1.2",
"input_tokens": 18342,
"details": {
"system_tokens": 412,
"message_tokens": 15210,
"tool_tokens": 1890,
"image_tokens": 765,
"document_tokens": 0
},
"context_window": 262144,
"remaining_tokens": 243802
}| Field | Description |
|---|---|
input_tokens | The total that usage.prompt_tokens would report. |
details | Breakdown by source. Parts add up to input_tokens. |
context_window | The model’s context size. |
remaining_tokens | context_window minus input_tokens. Your reply (max_tokens) must fit here. |
The count matches the real request exactly, except that server-side tool results (for example web search results added during the request) cannot be known in advance.
Examples
curl https://app.syntic.ai/v1/chat/completions/count_tokens \
-H "Authorization: Bearer $SYNTIC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "Amara S1.2",
"messages": [
{ "role": "system", "content": "You are a careful contracts assistant." },
{ "role": "user", "content": "Summarise clause 14 of the attached lease." }
]
}'Errors
Unified envelope. Validation is the same as the real endpoint, so a request that counts without error will also pass validation when sent.
| Status | code | Cause |
|---|---|---|
| 400 | messages_required | No messages. |
| 400 | model_required | model missing. Unlike chat completions, counting has no default model. |
| 400 | any validation code | Same checks as the real request (images, files, schemas, tools). |
| 404 | model_not_found | Unknown model. |
| 429 | rate_limited | Over the counting limit. |
Limits and cost
| Price | Free. Not billed and does not use plan allowance. |
| Rate limit | Separate from inference: 100 requests per minute per key. |
| Request size | Same as the real endpoint. |
Remote image URLs are fetched to measure them, which can make counting slower than you expect; send sizes you already know or use Files.
Build notes for the platform team
- Must use the real tokenizer or the model service’s own count endpoint. The current internal estimate of about 4 characters per token is not acceptable here.
- Share the validation and request-building code with the real endpoint so the two can never disagree.
- Include the identity instruction in the count.