# Count tokens

`POST https://api.llm.buzz/api/v1/messages/count_tokens`

An estimate of a Messages request's input tokens, from llm.buzz's own tokenizer, never the provider's. It costs nothing and is not refused for a key's spending limit. The body names the estimate in `x-sgr-ignored-parameters` as `input_tokens->estimated(gateway_tokenizer)`.

Authentication: an inference key, as `Authorization: Bearer KEY` or in `x-api-key`.

## Body

- `model` (string, required): A model's name from `GET /api/v1/models`, such as `deepseek/deepseek-v4.1-flash`. A suffix changes one request: `:floor` tries the cheapest provider first and `:nitro` the fastest. On Chat Completions and Responses `:online` asks for a web search, which llm.buzz does not run today: the request is served without one and `x-sgr-ignored-parameters` names `web_search->dropped(search_unavailable)`, or for an organization whose requests llm.buzz keeps in the EU it answers 400 `web_search_unavailable_in_region`. On Messages `:online` does nothing and is named as `model:online`.
- `messages` (object[], required): The conversation, as on Messages.
- `system` (string or object[]): The system prompt: a string, or a list of text blocks, which may carry `cache_control`.
- `tools` (object[]): Tools, as on Messages.

## Responses

- 200: The estimate.
- 401: Messages keeps Anthropic's error body: a 401 is an `authentication_error`, a 402 a `billing_error`, a 403 a `permission_error` and a 429 a `rate_limit_error`.

## Example (curl)

```bash
curl -X POST https://api.llm.buzz/api/v1/messages/count_tokens \
  -H "Authorization: Bearer $LLM_BUZZ_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "model": "anthropic/claude-haiku-5.5",
  "messages": [
    {
      "role": "user",
      "content": "Say hello in one word."
    }
  ]
}'
```

## Example response

```json
{
  "input_tokens": 14,
  "x-sgr-ignored-parameters": [
    "input_tokens->estimated(gateway_tokenizer)"
  ]
}
```
