Claude API Documentation Chatbot Tutorial
If you're searching for a Claude API documentation chatbot tutorial, you're probably trying to do one of two things: build a chatbot that answers questions using your own docs, or understand Anthropic's API documentation well enough to build a working chatbot in the first place. This tutorial covers both — it walks through the Messages API structure, shows a working chatbot loop in JavaScript, and explains how to feed your own documentation into Claude's context so it answers accurately instead of guessing.
By the end you'll have a chatbot that takes a user question, injects relevant documentation text into the prompt, streams a response back, and keeps track of conversation history across turns. This works whether you're building an internal support bot, a docs-site widget, or a Slack-adjacent helper for your product.
What you need before you start
- An Anthropic API key, or an API key from a proxy service like SubToAPI if you're already paying for Claude through a subscription and want a standard HTTPS API instead of managing raw Anthropic billing
- Your documentation in plain text or markdown — doesn't need to be in a vector database for this tutorial, a simple file-based approach works for small-to-medium doc sets
- Node.js or any language that can make HTTPS requests
- Basic familiarity with JSON request bodies
If you're not sure which key to use, SubToAPI gives you a sub_live_... key, usage metadata, and streaming support without you having to set up Anthropic billing separately. You can grab one from /signup, and /pricing lists what each plan includes.
Step 1: Understand the Messages API shape
Every Claude request, regardless of provider, follows the same basic shape: a system prompt (instructions and context), and a list of messages with alternating user and assistant roles. For a documentation chatbot, the system prompt is where your docs context typically lives.
{
"model": "claude-sonnet-4-5",
"max_tokens": 1024,
"system": "You are a documentation assistant. Answer only using the context below. If the answer isn't in the context, say you don't know.\n\n<docs>...</docs>",
"messages": [
{ "role": "user", "content": "How do I rotate my API key?" }
]
}
This is the core pattern you'll reuse for every request. The quality of your chatbot depends almost entirely on what you put in system, not on clever prompt engineering tricks.
Step 2: Build a minimal retrieval step
You don't need a full RAG pipeline to get useful results from a small documentation set. A simple keyword or section-match lookup against your markdown files is often enough to start.
import fs from "fs";
const docs = fs.readFileSync("./docs/all.md", "utf8");
function getRelevantSection(question, docText, maxChars = 4000) {
// naive example: grab the chunk around the first keyword match
const keyword = question.split(" ").find(w => w.length > 4) || question;
const idx = docText.toLowerCase().indexOf(keyword.toLowerCase());
const start = Math.max(0, idx - 500);
return docText.slice(start, start + maxChars);
}
For larger doc sets, swap this for embeddings and a vector store — but for a tutorial-level bot answering questions about one product's docs, this naive approach is enough to prove the concept.
Step 3: Call the API
Here's a full request against SubToAPI's endpoint, which mirrors the standard Messages format:
curl https://api.subtoapi.app/v1/messages \
-H "Authorization: Bearer $SUBTOAPI_KEY" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-4-5",
"max_tokens": 1024,
"system": "You are a documentation assistant. Answer only using the context provided.",
"messages": [
{ "role": "user", "content": "What is the rate limit on the free plan?" }
]
}'
See /docs/messages for the full request and response schema, and /docs/quickstart if you want the minimal setup path with a single curl command.
Step 4: Add streaming for a real chatbot feel
A docs chatbot that returns a block of text after a 4-second wait feels broken. Streaming fixes that by sending tokens as they're generated.
const res = await fetch("https://api.subtoapi.app/v1/messages", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
"content-type": "application/json"
},
body: JSON.stringify({
model: "claude-sonnet-4-5",
max_tokens: 1024,
stream: true,
system: systemPrompt,
messages: [{ role: "user", content: question }]
})
});
for await (const chunk of res.body) {
process.stdout.write(chunk.toString());
}
Streaming details, including how to parse server-sent events chunk by chunk, are covered in /docs/streaming.
Step 5: Keep conversation history
A documentation chatbot usually gets follow-up questions ("what about on the Team plan?") that only make sense with prior context. Store the message array per session and append to it on each turn:
let history = [];
function ask(question) {
history.push({ role: "user", content: question });
// call the API with { system, messages: history }
// after response, push { role: "assistant", content: answerText } to history
}
Trim or summarize history once it gets long — documentation context plus a growing conversation can eat into your token budget fast.
Step 6: Decide if you need tool use
If your chatbot needs to do more than answer from static text — fetching live status, searching a ticket system, running a search API — you'll want function calling. That's a separate build; /docs/tools covers the request format for defining and handling tool calls if your chatbot grows beyond simple Q&A.
Common pitfalls with documentation chatbots
- Context bloat: dumping your entire docs folder into every request wastes tokens and increases latency. Chunk or retrieve only relevant sections.
- No "I don't know" instruction: without an explicit instruction to admit uncertainty, Claude will sometimes extrapolate beyond what's in your docs. Say it directly in the system prompt.
- Ignoring usage metadata: track token consumption per request so you know when a user's docs set is pushing costs up. SubToAPI includes usage metadata on every response, visible in your dashboard.
- Treating streaming as optional: for chat UIs, a non-streamed response feels noticeably slower even if total time is similar.
questions
Do I need Anthropic's own API key to follow this tutorial? No. Any key that implements the same Messages request format works, including a SubToAPI key, which also adds streaming, usage tracking, and team seats on top of the standard format.
How much documentation can I fit into the system prompt? It depends on the model's context window and your max_tokens setting, but a few thousand words of relevant text per request is typical. For larger doc sets, retrieve only the relevant section rather than sending everything.
Does this approach work for multi-turn conversations? Yes — store the full messages array per session and append each new user question and assistant reply to it before sending the next request, trimming older turns once the history grows too large.