How to Use the Claude Fable 5 API

Call the Claude Fable 5 API with working Python, TypeScript, and curl code: streaming, tool use, errors, cost math, plus how to test it in Apidog.

INEZA Felin-Michel

INEZA Felin-Michel

10 June 2026

How to Use the Claude Fable 5 API

Apidog for Enterprise

On-Premises Deploy

SSO & RBAC

SOC 2 Compliant

Explore Apidog Enterprise

Anthropic shipped Claude Fable 5 on June 9, 2026, and if you write code for a living, the Claude Fable 5 API is the part you care about. It runs on the same Messages API you already know, so the model string is the only thing that really changes: claude-fable-5. This guide walks through every call you need to get working code in front of a real response, from a one-line curl request to streaming, tool use, error handling, and cost math. If you have shipped against Claude before, the shape will feel familiar. If you migrated from an older model, the move is mostly a string swap, the same way it was for the Claude Opus 4.8 API.

TL;DR

Get an API key from the Anthropic Console, set it as ANTHROPIC_API_KEY, then POST to the Messages API with model: "claude-fable-5", a max_tokens value, and a messages array. Use the official Anthropic SDK for Python or TypeScript, or raw HTTP. Stream long outputs so you do not hit request timeouts. Pricing is $10 per million input tokens and $50 per million output tokens.

Before you start

You need four things in place before your first request:

  1. An Anthropic account. Sign up at console.anthropic.com. The Console is where you manage keys, usage, and billing.
  2. An API key. Create one in the Console under API Keys. Copy it once; you will not see it again. Treat it like a password.
  3. Billing or an Enterprise plan. Fable 5 is available on the standard Claude API and is fully available on consumption-based Enterprise plans. Add a payment method or confirm your plan covers it before you send traffic. If you are still deciding whether Fable 5 fits your use case, the overview of what Claude Fable 5 is covers the model’s strengths in plain terms.
  4. An SDK (optional but recommended). Install the official Anthropic SDK for your language. You can also call the raw HTTP endpoint with curl or any HTTP client if you prefer.

Set the key as an environment variable so it never lands in your source code:

export ANTHROPIC_API_KEY="sk-ant-..."

Both SDKs read ANTHROPIC_API_KEY from the environment automatically, so you rarely pass it in code. Keep keys out of git. If a key leaks, rotate it in the Console right away.

One behavior to know up front: Fable 5 ships with safeguards that route a small slice of sensitive queries (cybersecurity, biology and chemistry, and model distillation attempts) to Claude Opus 4.8 instead. This triggers in under 5% of sessions. You do not configure anything for it, but it explains the occasional response that comes back labeled as a different model. More on that in the error-handling section.

Your first Claude Fable 5 API call

Start with curl so you can see the raw request and response with nothing in the way. The endpoint is POST https://api.anthropic.com/v1/messages, documented in the Anthropic Messages API reference, and it needs three headers plus a JSON body.

curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model":"claude-fable-5","max_tokens":1024,"messages":[{"role":"user","content":"Summarize what makes a good REST API in 3 bullet points."}]}'

Three headers matter here. x-api-key carries your key. anthropic-version pins the API version (2023-06-01 is the current stable value). content-type tells the server you are sending JSON. The body has three required fields: model, max_tokens, and messages. That is the whole contract.

The response comes back as a JSON object. The part you care about is content, which is a list of blocks:

{
  "id": "msg_01ABC...",
  "type": "message",
  "role": "assistant",
  "model": "claude-fable-5",
  "content": [
    { "type": "text", "text": "- Predictable, resource-oriented URLs..." }
  ],
  "stop_reason": "end_turn",
  "usage": { "input_tokens": 18, "output_tokens": 96 }
}

content is a list, not a string, because a single response can mix text, tool-use blocks, and thinking blocks. Always loop the list and check each block’s type before you read text. The stop_reason tells you why the model stopped (end_turn is a clean finish), and usage gives you the token counts you will use for cost math later.

Calling Fable 5 from Python

The official Anthropic Python SDK removes the header and JSON boilerplate. Install it first:

pip install anthropic

Here is the basic call. The client reads your key from the environment, so you do not pass it in:

import anthropic

client = anthropic.Anthropic()  # reads ANTHROPIC_API_KEY from env

response = client.messages.create(
    model="claude-fable-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Summarize what makes a good REST API."}],
)

for block in response.content:
    if block.type == "text":
        print(block.text)

The pattern mirrors the curl call. You pass model, max_tokens, and messages, and you get back a response whose content is a list of blocks. The loop guards on block.type == "text" so you never trip over a non-text block.

Adding a system prompt

A system prompt sets the model’s role and ground rules for the whole conversation. Pass it as the system field, separate from messages:

response = client.messages.create(
    model="claude-fable-5",
    max_tokens=2048,
    system="You are a senior backend engineer. Be concise and use code examples.",
    messages=[{"role": "user", "content": "Write a Flask route that validates a JSON body."}],
)

for block in response.content:
    if block.type == "text":
        print(block.text)

The system prompt is the right place for persona, output format rules, and constraints you want to hold across every turn. Keep it stable, because changing it on every request defeats prompt caching if you later add it.

Streaming long outputs

For anything that produces a long answer, stream it. Streaming sends tokens as they are generated, so you show progress immediately and you avoid the request timeouts that hit large non-streaming responses. Fable 5’s long-horizon work makes this the default choice for real workloads:

with client.messages.stream(
    model="claude-fable-5",
    max_tokens=4096,
    messages=[{"role": "user", "content": "Explain idempotency keys for payment APIs."}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)
    final = stream.get_final_message()

print(f"\n\nTokens: {final.usage.output_tokens}")

stream.text_stream yields text chunks as they arrive. The flush=True matters so each chunk prints right away instead of buffering. When the stream finishes, stream.get_final_message() hands you the complete assembled message, including the final usage numbers, so you get the streamed UX and the full object without a second request.

Calling Fable 5 from TypeScript / Node

The Node SDK follows the same shape. Install it:

npm install @anthropic-ai/sdk

Then make the call. The client reads ANTHROPIC_API_KEY from the environment, same as Python:

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic(); // reads ANTHROPIC_API_KEY

const msg = await client.messages.create({
  model: "claude-fable-5",
  max_tokens: 1024,
  messages: [{ role: "user", content: "List 3 common API security mistakes." }],
});

console.log(msg.content);

msg.content is the same list of blocks you saw in Python and curl. To pull out just the text, filter on the block type:

const text = msg.content
  .filter((block) => block.type === "text")
  .map((block) => block.text)
  .join("");

console.log(text);

Streaming works the same way as Python. Use client.messages.stream({...}) and iterate the events, or await finalMessage() for the assembled result. If you are wiring this into a frontend chat, stream from a server route and forward the chunks to the browser. The same testing habits apply whether you build in Node or Python, and a tool like Apidog makes the contract easy to verify before you write any client code, which is the same workflow covered in testing the ChatGPT API with Apidog.

Tool use (function calling) with Fable 5

Tool use lets Fable 5 call functions you define. You describe a tool with a JSON schema, the model decides when to call it, and you run the actual function and feed the result back. Fable 5 is strong at tool use, which is why it fits agent loops well.

Define a tool with a name, a description, and an input_schema:

tools = [
    {
        "name": "get_order_status",
        "description": "Look up the status of a customer order by ID.",
        "input_schema": {
            "type": "object",
            "properties": {"order_id": {"type": "string"}},
            "required": ["order_id"],
        },
    }
]

Pass tools to the request the same way you pass messages:

messages = [{"role": "user", "content": "What's the status of order A1855?"}]

response = client.messages.create(
    model="claude-fable-5",
    max_tokens=1024,
    tools=tools,
    messages=messages,
)

When the model wants to use a tool, the response comes back with stop_reason == "tool_use" and a tool_use block carrying the tool name and the input it chose. The loop is straightforward: append the assistant’s response, run the tool, then send the result back as a tool_result block in a new user turn:

if response.stop_reason == "tool_use":
    tool_use = next(b for b in response.content if b.type == "tool_use")

    # Run your real function with the model's chosen input
    result = lookup_order(tool_use.input["order_id"])  # your code

    messages.append({"role": "assistant", "content": response.content})
    messages.append({
        "role": "user",
        "content": [{
            "type": "tool_result",
            "tool_use_id": tool_use.id,
            "content": result,
        }],
    })

    # Send the result back; the model now answers using it
    followup = client.messages.create(
        model="claude-fable-5",
        max_tokens=1024,
        tools=tools,
        messages=messages,
    )

The key detail is tool_use_id: the tool_result block must reference the exact id from the tool_use block so the model knows which call your result answers. For multi-step agents, you wrap this in a loop that keeps going until stop_reason is end_turn. The Python SDK also ships a tool runner that handles the loop for you, but the manual version above shows what is happening under the hood and gives you a place to add approval gates or logging.

Adaptive thinking and effort

Fable 5 supports adaptive thinking, where the model decides on its own when and how deeply to reason before answering. It is optional. Turn it on by passing thinking, and tune the overall depth and token spend with output_config:

response = client.messages.create(
    model="claude-fable-5",
    max_tokens=4096,
    thinking={"type": "adaptive"},
    output_config={"effort": "high"},  # low | medium | high
    messages=[{"role": "user", "content": "Design a retry strategy for a flaky webhook receiver."}],
)

effort controls how much the model thinks and works: lower effort means terser, faster responses, higher effort means more thorough reasoning at higher token cost. Leave both off for simple lookups and short answers, where the extra reasoning is not worth the tokens. Reach for them on hard, multi-step problems, the kind of long-horizon planning Fable 5 is built for. Keep it simple to start; you can add thinking later once you know a route needs it.

Handling errors and the safeguard fallback

Real integrations have to handle failures cleanly. The SDK raises typed exceptions, so catch the specific class rather than matching error strings. The three you will see most often map to HTTP 401, 429, and 400:

import anthropic

client = anthropic.Anthropic()

try:
    response = client.messages.create(
        model="claude-fable-5",
        max_tokens=1024,
        messages=[{"role": "user", "content": "Explain CORS preflight requests."}],
    )
except anthropic.AuthenticationError:
    # 401: bad or missing API key. Check ANTHROPIC_API_KEY.
    print("Invalid API key. Rotate it in the Console and re-export.")
except anthropic.RateLimitError as e:
    # 429: too many requests. Back off and retry.
    retry_after = e.response.headers.get("retry-after", "60")
    print(f"Rate limited. Retry after {retry_after}s.")
except anthropic.BadRequestError as e:
    # 400: malformed request (bad params, empty messages, wrong shape).
    print(f"Bad request: {e.message}")

Here is what each one means and how to fix it:

Now the safeguard fallback. Fable 5 routes a small set of sensitive queries (cybersecurity, biology and chemistry, and distillation attempts) to Claude Opus 4.8 instead of answering directly. This triggers in fewer than 5% of sessions. It is not an error, and your request still succeeds, but the response may come back tagged with a different model. If you log or assert on response.model, do not hard-fail when it is not claude-fable-5; the request was handled, just by a different model under the hood. If your application strictly needs to know which model answered, read response.model from the returned object rather than assuming it matches what you sent.

Estimating cost per request

Pricing is $10 per million input tokens and $50 per million output tokens. Every response carries the exact counts in usage, so you can compute cost per request precisely instead of guessing:

response = client.messages.create(
    model="claude-fable-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Write a SQL query to find duplicate emails."}],
)

input_tokens = response.usage.input_tokens
output_tokens = response.usage.output_tokens

input_cost = input_tokens / 1_000_000 * 10
output_cost = output_tokens / 1_000_000 * 50
total = input_cost + output_cost

print(f"Input:  {input_tokens} tokens  = ${input_cost:.6f}")
print(f"Output: {output_tokens} tokens = ${output_cost:.6f}")
print(f"Total:  ${total:.6f}")

Output tokens cost five times what input tokens cost, so the cheapest lever you have is keeping responses tight. A request with 2,000 input tokens and 500 output tokens costs 2000 / 1M * $10 + 500 / 1M * $50, which is $0.02 + $0.025 = $0.045. Multiply by your request volume to size a budget. If output cost dominates your bill, cap max_tokens and ask for concise answers in the system prompt. Output pricing is the same math you would run for the Claude Opus 4.8 pricing model, just with Fable 5’s numbers.

Test and debug the Claude Fable 5 API with Apidog

Before you write client code, it pays to send a few requests by hand and watch exactly what comes back. Apidog is an API client built for this: you send real requests to https://api.anthropic.com/v1/messages, inspect the streamed response, and save the request so your whole team works from the same definition. Here is a clean path from zero to a working, saved request.

  1. Create the request. In Apidog, make a new HTTP request, set the method to POST, and paste the URL https://api.anthropic.com/v1/messages. This is the same endpoint every example in this guide hits.
  2. Store your key as an environment variable. Create an Apidog environment variable, name it something like anthropic_api_key, and paste your key as a secret value. Keeping the key in the environment means it stays out of the saved request and out of any export you share.
  3. Set the headers. Add x-api-key with the value {{anthropic_api_key}}, then anthropic-version: 2023-06-01 and content-type: application/json. If you prefer a Bearer-style secret variable, store the token the same way and reference it with the {{...}} syntax so the raw value never appears in the request.
  4. Add the JSON body. Drop in the minimal payload: {"model": "claude-fable-5", "max_tokens": 1024, "messages": [{"role": "user", "content": "Explain idempotency keys for payment APIs."}]}. Send it and read the response. You should see the content blocks, stop_reason, and usage right in the response panel.
  5. View streamed responses. Set "stream": true in the body and send again. Apidog renders the server-sent events as they arrive, so you can watch the tokens stream in and confirm your streaming logic matches what the API actually sends before you build it into an app.
  6. Save and generate code. Save the request into a collection so teammates can reuse it, then use Apidog’s code generation to export a working snippet in Python, JavaScript, curl, or another language. That gives you a tested starting point instead of a blank file.

This flow is the fastest way to learn the API’s exact response shape and to debug a request that misbehaves in your app, since you can compare your code’s request against a known-good one side by side. When you are ready to set it up, Download Apidog and start with the minimal body above.

button

Explore more

Why AI Agents Break in Production (and How to Test for Each Failure Mode)

Why AI Agents Break in Production (and How to Test for Each Failure Mode)

AI agents fail at the API boundary, not the prompt. The five ways agents break in production (tool calls, rate limits, non-determinism, cost, guardrails) and how to test each with mocks.

20 July 2026

How to Use Kimi K3 for Coding with Kimi Code

How to Use Kimi K3 for Coding with Kimi Code

Run Kimi K3 in Kimi Code for agentic coding: repo navigation, tool use, and iterating against tests and logs, plus how it compares to Claude Code and Cursor.

17 July 2026

Kimi K3 Benchmarks: Moonshot's Numbers vs Independent Tests

Kimi K3 Benchmarks: Moonshot's Numbers vs Independent Tests

Kimi K3 scores 57 on Artificial Analysis (rank #4 of 189) but runs slow. See vendor claims vs independent tests and how to benchmark kimi-k3 yourself.

17 July 2026

Practice API Design-first in Apidog

Discover an easier way to build and use APIs

How to Use the Claude Fable 5 API