Anthropic SDK
The official Anthropic SDK (Python or TypeScript) speaks the Anthropic Messages protocol, which MirAPI implements on the bare API origin. To switch from Anthropic to MirAPI you only change the base URL and API key; request and response shapes stay the same.
What you need
Section titled “What you need”| Element | Value |
|---|---|
| Base URL | https://api.mirapi.ai — bare origin, no /v1 |
| API key | MIRAPI_API_KEY |
| Model | deepseek-chat |
The SDK authenticates with the x-api-key header by default. MirAPI accepts both x-api-key and Authorization: Bearer on /v1/messages.
Install
Section titled “Install”pip install anthropicnpm install @anthropic-ai/sdkConfigure
Section titled “Configure”Python
Section titled “Python”import osfrom anthropic import Anthropic
client = Anthropic( base_url="https://api.mirapi.ai", api_key=os.environ["MIRAPI_API_KEY"],)TypeScript
Section titled “TypeScript”import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({ baseURL: "https://api.mirapi.ai", apiKey: process.env.MIRAPI_API_KEY,});The SDK sends the anthropic-version header by default; MirAPI accepts it like any other header.
Verify with a message
Section titled “Verify with a message”message = client.messages.create( model="deepseek-chat", max_tokens=200, messages=[{"role": "user", "content": "Reply with exactly: connected to MirAPI"}],)print(message.content[0].text)The output should contain connected to MirAPI. The Anthropic protocol requires max_tokens, so set it on every call.
Streaming
Section titled “Streaming”with client.messages.stream( model="deepseek-chat", max_tokens=200, messages=[{"role": "user", "content": "Count from 1 to 5."}],) as stream: for text in stream.text_stream: print(text, end="")Streaming uses standard SSE. Reasoning content, when the model produces it, arrives before the final answer.
Prompt caching
Section titled “Prompt caching”Add cache_control to a system or messages block to mark a cache breakpoint:
message = client.messages.create( model="deepseek-chat", max_tokens=200, system=[ { "type": "text", "text": "You are a helpful assistant.", "cache_control": {"type": "ephemeral"}, } ], messages=[{"role": "user", "content": "Hello"}],)- You can mark up to 4 breakpoints.
"ttl": "1h"extends the cache to 1 hour and raises the write price. - Minimum length and TTL are decided by the vendor (Claude 1,024–4,096 tokens; OpenAI 1,024; default about 5 minutes).
- Confirm a hit through the
usage.prompt_tokens_details.cached_tokens/cache_write_tokensfields. Cache reads are cheaper than normal input.
Errors and troubleshooting
Section titled “Errors and troubleshooting”| Status | Meaning | What to do |
|---|---|---|
| 401 | Missing, invalid, or unknown key | Fix your credentials |
| 403 | Valid key, but rejected | Resolve the cause and retry (balance, whitelist, quota, IP allowlist) |
| 413 | Payload too large | Reduce the request size |
| 429 | Rate limited | Retry with jittered exponential backoff (1s → 2s → 4s, cap ~30s) |
| 500 | Gateway or upstream error | Idempotent requests are safe to retry |
The Anthropic error envelope looks like this:
{"type":"error","error":{"type":"permission_error","message":"..."}}Every error message ends with a request ID — include it when you open a support ticket. A 403 with a valid key usually means the model is not on your whitelist or the balance is exhausted.
Billing
Section titled “Billing”- A non-streaming response’s
usagereports token counts only, never an amount. Check the amount in the console or viaGET /api/log/token. - Text and multimodal chat bill per token (input / output / cache read, per 1M USD). Reasoning tokens bill as output.
- Balance is prepaid USD, never expires, and there is no subscription or monthly fee. When it runs out, calls fail with 403; top up and the same key recovers immediately.
Troubleshooting
Section titled “Troubleshooting”- Bare
base_url, no/v1. The SDK builds/v1/messagesitself; adding/v1duplicates the segment. /v1/messages/count_tokensis not implemented and returns 404. The SDK exposes it, but counting is not required to callmessages.create.- Unsupported parameters. Tool use, streaming, and
thinkingmap to gateway behavior only when the upstream model supports them; unsupported parameters may be ignored or rejected upstream. - 429 has no
Retry-Afterheader. Implement backoff in your client instead of waiting for a hint. baseURLvsbase_url. The Python SDK usesbase_url; the TypeScript SDK usesbaseURL.