# Messages (Anthropic)

> POST /v1/messages no formato Anthropic Messages, usado pelos SDKs da Anthropic e pelo Claude Code.


A requisição e a resposta do Anthropic Messages, rodando nos modelos da NotHoly. Os SDKs da Anthropic recebem `https://api.notholy.com` como URL base, sem `/v1`. Tanto `x-api-key` quanto `Authorization: Bearer` funcionam.

```endpoint
POST https://api.notholy.com/v1/messages
```

## Requisição

| Campo | Tipo | Obrigatório | Observações |
|---|---|---|---|
| `model` | string | Sim | Um ID de modelo, por exemplo `notholy-specter` |
| `max_tokens` | number | Sim | Maior que 0. Limitado à saída máxima do modelo |
| `messages` | array | Sim | Turnos `user` e `assistant` com blocos `text`, `image`, `tool_use` e `tool_result` |
| `system` | string ou array | Não | Só blocos de texto |
| `tools` | array | Não | Suas próprias ferramentas, com `input_schema`. Ferramentas de servidor, como busca na web, são ignoradas |
| `tool_choice` | object | Não | `auto`, `any`, `none` ou `{"type": "tool", "name": …}` |
| `thinking` | object | Não | `{"type": "enabled", "budget_tokens": N}` ou `{"type": "adaptive"}` ativa o raciocínio |
| `output_config.effort` | string | Não | Esforço de raciocínio; tem prioridade sobre `thinking`. É mapeado para o nível mais próximo que o modelo tem |
| `stop_sequences`, `temperature`, `top_p` | | Não | Repassados ao modelo |
| `stream` | boolean | Não | `true` retorna eventos de stream da Anthropic |

`POST /v1/messages/count_tokens` recebe o mesmo corpo e retorna `{"input_tokens": n}`, uma estimativa feita sem chamar o modelo.

## Resposta sem streaming

```json
{
  "id": "msg_3Jd8a",
  "type": "message",
  "role": "assistant",
  "model": "notholy-specter",
  "content": [
    { "type": "thinking", "thinking": "…", "signature": "nh" },
    { "type": "text", "text": "A Sigma rule is a generic detection rule in YAML…" }
  ],
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": { "input_tokens": 24, "output_tokens": 131, "cache_read_input_tokens": 0, "cache_creation_input_tokens": 0 }
}
```

- `stop_reason` é `end_turn`, `max_tokens` ou `tool_use`.
- Blocos `thinking` reenviados no histórico são descartados antes de chegar ao modelo.
- `cache_control` é aceito e ignorado.
- Fontes `document` de PDF e de arquivo retornam `400 unsupported_parameter`. Envie arquivos pelo chat ou por `POST /v1/files`.
- Num stream, tool calls chegam inteiras: um único `input_json_delta` com os argumentos completos. Em pausas longas, chegam eventos `ping`.

## Exemplo

```bash test
curl https://api.notholy.com/v1/messages \
  -H "x-api-key: $NOTHOLY_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{"model": "notholy-specter", "max_tokens": 512, "messages": [{"role": "user", "content": "What is a Sigma rule?"}]}'
```

```python test
import os
from anthropic import Anthropic

client = Anthropic(base_url="https://api.notholy.com", api_key=os.environ["NOTHOLY_API_KEY"])

with client.messages.stream(
    model="notholy-specter",
    max_tokens=512,
    messages=[{"role": "user", "content": "Write a Sigma rule title for encoded PowerShell."}],
) as s:
    for text in s.text_stream:
        print(text, end="")
print()
```

Conte os tokens antes de enviar:

```bash test
curl https://api.notholy.com/v1/messages/count_tokens \
  -H "x-api-key: $NOTHOLY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "notholy-specter", "messages": [{"role": "user", "content": "What is a Sigma rule?"}]}'
```

## Erros

Os erros seguem o formato da Anthropic, `{"type": "error", "error": {"type", "message"}}`: `invalid_request_error` (400) · `authentication_error` (401) · `billing_error` (402) · `permission_error` (403) · `not_found_error` (404) · `rate_limit_error` (429) · `overloaded_error` (503). Veja [Erros](/pt-br/guides/errors).
