# Messages (Anthropic API)

> Anthropic SDK বা curl দিয়ে POST /v1/messages call করা: base URL, header, পুরো উদাহরণ, streaming event, error-এর shape, আর কোন header forward হয় না।

Tokens-এ Anthropic Messages API পাওয়া যায় `POST https://tokens.bd/v1/messages`-এ। Claude Code আর Anthropic SDK এই endpoint-ই call করে, তাই শুধু base URL আর key বদলে এদের Tokens-এ ঘুরিয়ে দিতে পারবেন। এখান দিয়ে আপনার catalog-এর যেকোনো model চাওয়া যায়, শুধু Claude model নয়।

## Base URL আর header

Anthropic SDK আর Claude Code নিজেরাই `/v1/messages` জুড়ে নেয়। তাই এদের base URL হবে শুধু host: `https://tokens.bd`।

| Header                         | Value                                             | আবশ্যক কিনা                          |
| ------------------------------ | ------------------------------------------------- | ------------------------------------ |
| `x-api-key` বা `Authorization` | `tok_live_your_key` বা `Bearer tok_live_your_key` | হ্যাঁ                                |
| `anthropic-version`            | `2023-06-01`                                      | দেওয়া ভালো; upstream-এ forward হয়    |
| `anthropic-beta`               | Beta flag, কমা দিয়ে আলাদা করা                     | ঐচ্ছিক; upstream-এ forward হয়        |
| `content-type`                 | `application/json`                                | হ্যাঁ                                |

SDK নিজেই `x-api-key` আর `anthropic-version` পাঠিয়ে দেয়। `ANTHROPIC_AUTH_TOKEN` দিয়ে চালালে Claude Code তার বদলে Bearer header পাঠায়; দুটোই চলে।

## curl দিয়ে Messages API request পাঠান

```bash
curl https://tokens.bd/v1/messages \
  -H "x-api-key: $TOKENS_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "deepseek/deepseek-v4.1-flash",
    "max_tokens": 512,
    "system": "You are a concise senior engineer.",
    "messages": [
      {"role": "user", "content": "Explain idempotency keys in two sentences."}
    ]
  }'
```

Messages API-তে `max_tokens` দিতেই হয়। সাধারণ একটা response এমন দেখায়:

```json
{
  "id": "msg_01AbCdEf",
  "type": "message",
  "role": "assistant",
  "model": "deepseek/deepseek-v4.1-flash",
  "content": [
    { "type": "text", "text": "An idempotency key is a client-chosen id sent with a request..." }
  ],
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": { "input_tokens": 31, "output_tokens": 58 }
}
```

## Anthropic Python SDK ব্যবহার করুন

```python
import os
import anthropic

client = anthropic.Anthropic(
    base_url="https://tokens.bd",
    api_key=os.environ["TOKENS_API_KEY"],
)

message = client.messages.create(
    model="deepseek/deepseek-v4.1-flash",
    max_tokens=512,
    messages=[{"role": "user", "content": "Explain idempotency keys in two sentences."}],
)
print(message.content[0].text)
print(message.usage)
```

TypeScript SDK-ও একইভাবে চলে: `new Anthropic({ baseURL: "https://tokens.bd", apiKey: process.env.TOKENS_API_KEY })`।

Claude Code-এর settings থাকে `~/.claude/settings.json`-এ। Setup-এর ধাপ দেখুন [quickstart](/docs/quickstart)-এ, অথবা [Connect your agent](/dashboard/connect)-এর snippet থেকে নিন।

## /v1/messages-এ native আর translated model

প্রতিটা model এক বা একাধিক upstream provider দিয়ে চলে। কোনো provider নিজেই Messages API বোঝে, তাহলে আপনার request যেমন আছে তেমনই তার কাছে যায়। Thinking block, prompt caching, `anthropic-beta`-র feature আর ঠিকঠাক usage-র সংখ্যা অবিকৃত ফেরত আসে। কোনো model যে provider-এ পাওয়া যায় তাদের কেউ Messages API বুঝলে Tokens সেটাকেই আগে বেছে নেয়।

আর যদি model শুধু এমন provider-এ থাকে যে OpenAI format বোঝে, তখন gateway আপনার Messages request-কে chat completions request বানিয়ে পাঠায়, আর উত্তরটা আবার ফিরিয়ে Messages format-এ দেয়। এই translation-এ যা যায়: `system`, `messages` (text আর image), `max_tokens`, `stop_sequences`, `temperature`, `top_p`, `tools` ও `tool_choice`। শুধু Anthropic-এর নিজস্ব জিনিস (prompt caching marker, extended thinking block, document) translation-এ বাদ পড়ে যেতে পারে। তাই এসব feature-এর ওপর নির্ভর করার আগে ওই নির্দিষ্ট model-এ test করে নিন।

## Streaming event

`"stream": true` দিলে response আসে Anthropic-এর format-এ Server-Sent Events হিসেবে:

```text
event: message_start
data: {"type":"message_start","message":{"id":"msg_01AbCdEf","type":"message","role":"assistant","content":[],"model":"deepseek/deepseek-v4.1-flash","stop_reason":null,"usage":{"input_tokens":31,"output_tokens":0}}}

event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"An idempotency"}}

event: content_block_stop
data: {"type":"content_block_stop","index":0}

event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"output_tokens":58}}

event: message_stop
data: {"type":"message_stop"}
```

Tool call stream হয়ে আসে `"type": "tool_use"`-সহ একটা `content_block_start` হিসেবে, তারপর আসে `input_json_delta` delta। Python SDK-তে `client.messages.stream(...)` ব্যবহার করলে event parse করার কাজটা SDK-ই করে দেয়। Disconnect আর timeout নিয়ে আরও আছে [streaming](/docs/streaming) পেজে।

## /v1/messages-এর error shape

`/v1/messages` আর `/v1/messages/count_tokens`-এর প্রতিটা error Anthropic-এর error format-এ আসে। Error Tokens-এর নিজের হোক (key ভুল, ব্যালান্স নেই, plan-এর limit) কিংবা upstream provider-এর, format একই:

```json
{
  "type": "error",
  "error": {
    "type": "billing_error",
    "message": "Prepaid wallet balance is insufficient for this request. Top up your wallet in the dashboard: https://tokens.bd/dashboard/billing",
    "code": "insufficient_credits"
  },
  "request_id": "8f0c7a4e-2b1d-4c55-9a51-3f7e2d9b6c10"
}
```

`error.type` Anthropic-এর list মেনে চলে (`invalid_request_error`, `authentication_error`, `billing_error`, `permission_error`, `not_found_error`, `request_too_large`, `rate_limit_error`, `api_error`, `overloaded_error`)। তাই SDK আর Claude Code ঠিক exception তোলে এবং যেখানে retry করার কথা সেখানে retry করে। Tokens থেকে আসা error-এ `error.code`-ও থাকে, যা দেখে বোঝা যায় ঠিক কোন limit-এ ঠেকেছে; দেখুন [errors](/docs/errors)।

Upstream-এর error message বদলে একটা সাধারণ message বসিয়ে দেওয়া হয়, যাতে provider-এর ভেতরের কোনো তথ্য বেরিয়ে না যায়। Support-এর সঙ্গে যোগাযোগ করলে response header থেকে `x-tokens-request-id` দেখে নিয়ে সেটা জানান।

## Token গোনা

`POST /v1/messages/count_tokens` `/v1/messages`-এর মতোই body নেয় (শুধু `max_tokens` লাগে না) আর ফেরত দেয় `{"input_tokens": N}`। এর জন্য কোনো বিল হয় না, আর model-ও চলে না। তবে এটা limit-এর বাইরে নয়: এটাও আপনার per-minute request limit-এ গোনা হয়, একটা concurrency slot নেয়, আর অ্যাকাউন্টে চালু plan বা Wallet-এ ব্যালান্স থাকতে হয় (usage window শেষ হয়ে গেলে বা key-এর allowed-models list-এ model না থাকলে অন্য যেকোনো request-এর মতোই এটাও আটকে যায়)। দেখুন [Token counting](/docs/token-counting)।

আপনার model যে provider-এ আছে সে নিজে token গুনতে পারলে ঠিক সংখ্যাটাই পাবেন। না পারলে Tokens আন্দাজ করে উত্তর দেয় আর response-এ `x-tokens-estimated: true` header জুড়ে দেয়। মোটামুটি budget ঠিক করতে এটা কাজে লাগে; তবে বিল হয় প্রতিটা response-এর `usage` object ধরে।

## anthropic-beta

`anthropic-beta` header forward হয় সেই provider-দের কাছে, যারা Messages API বোঝে। তাই provider support করলে beta feature (নতুন tool type, বড় context ইত্যাদি) কাজ করে। Translation-এর মধ্য দিয়ে চলা model-এ এই header-এর কোনো প্রভাব নেই।

## Anthropic format-এ model-এর list

Request-এ `anthropic-version` থাকলে (Anthropic SDK এটা পাঠায়) `GET /v1/models` Anthropic-এর format-এ উত্তর দেয়, ফলে `client.models.list()` কাজ করে:

```json
{
  "data": [
    {
      "type": "model",
      "id": "deepseek/deepseek-v4.1-flash",
      "display_name": "DeepSeek V4.1 Flash",
      "created_at": "2026-09-01T00:00:00.000Z"
    }
  ],
  "has_more": false,
  "first_id": "deepseek/deepseek-v4.1-flash",
  "last_id": "deepseek/deepseek-v4.1-flash"
}
```

---
Page: https://tokens.bd/bn/docs/messages
