How to Integrate Claude: A Step-by-Step Guide
Integrating Claude into a product means giving your application the ability to send prompts to Claude and receive responses programmatically, usually over HTTPS. There are two common paths: using Anthropic's API directly with an API key, or using a proxy service that sits on top of an existing Claude subscription and exposes it as an API. Both end up with the same result in your code — a request to an endpoint, a JSON payload, and a text or streamed response.
This guide walks through the practical steps: getting credentials, making your first call, handling streaming and tool use, and deciding which integration path fits your situation.
Step 1: Decide how you'll get API access
Before writing any code, you need a way to authenticate requests. There are two realistic options:
- Anthropic's API directly. You create an account, generate an API key, and pay per token based on usage. This is the standard path if you're building a product from scratch and want direct billing with Anthropic.
- A subscription-to-API bridge like SubToAPI. If you or your team already have Claude access through a subscription, SubToAPI turns that into a standard HTTPS API with its own application keys (
sub_live_...), so you don't need to set up separate API billing to start building.
Both approaches give you an HTTP endpoint and a key. The integration code in your app looks almost identical either way — the difference is mostly in billing and account setup.
Step 2: Get your API key
For SubToAPI, this takes about a minute:
- Sign up at /signup.
- Generate an application key from the dashboard — it starts with
sub_live_. - Store it as an environment variable, never in client-side code.
export SUBTOAPI_KEY="sub_live_xxxxxxxxxxxxxxxx"
Treat this key like any other secret: don't commit it, don't log it, and rotate it if it leaks.
Step 3: Send your first request
The core of integrating Claude is the messages endpoint. You send a role-based conversation array and get back a response object.
curl https://api.subtoapi.app/v1/messages \
-H "Authorization: Bearer $SUBTOAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4",
"max_tokens": 512,
"messages": [
{ "role": "user", "content": "Summarize this changelog in two sentences." }
]
}'
In JavaScript, this is a straightforward fetch call:
const response = 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",
max_tokens: 512,
messages: [
{ role: "user", content: "Summarize this changelog in two sentences." }
]
})
});
const data = await response.json();
console.log(data);
Full request and response shapes are covered in /docs/messages, and a runnable end-to-end example is in /docs/quickstart.
Step 4: Add streaming for interactive UIs
If you're building a chat interface or anything where users wait on output, integrate streaming instead of waiting for the full response. Set stream: true and read the response as server-sent events, appending each chunk to the UI as it arrives.
const response = 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",
max_tokens: 512,
stream: true,
messages: [{ role: "user", content: "Write a short release note." }]
})
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
process.stdout.write(decoder.decode(value));
}
See /docs/streaming for event types and reconnection handling.
Step 5: Wire up tool use if your app needs actions
Many integrations aren't just "ask Claude a question" — they need Claude to call functions in your app, like looking up a record or hitting an internal API. This is done by defining tools (name, description, JSON schema for inputs) in your request, then handling the tool_use response by executing your function and sending the result back as a tool_result message.
{
"model": "claude-sonnet-4",
"max_tokens": 512,
"tools": [
{
"name": "get_order_status",
"description": "Look up an order's status by ID",
"input_schema": {
"type": "object",
"properties": { "order_id": { "type": "string" } },
"required": ["order_id"]
}
}
],
"messages": [
{ "role": "user", "content": "What's the status of order 4521?" }
]
}
Details on the full tool-use loop are in /docs/tools.
Step 6: Handle errors, retries, and usage tracking
A production integration needs more than the happy path:
- Retry on 429 and 5xx with exponential backoff.
- Set sane
max_tokenslimits to control cost and latency. - Track usage per key if multiple team members or app features share access — SubToAPI's dashboard shows usage metadata per key without extra instrumentation.
- Rotate keys on a schedule or immediately if one is exposed.
Step 7: Add teammates without sharing raw credentials
If more than one person or service needs access, avoid sharing a single key across your whole team. Create separate application keys per developer or per environment (staging vs. production), so you can revoke one without breaking everything else. Team and Scale plans on SubToAPI support seat-based access for this — see /pricing for how seats map to usage.
questions
Do I need Anthropic API access to integrate Claude? You need some form of authenticated access — either a direct Anthropic API key or a bridge service like SubToAPI that turns an existing Claude subscription into an HTTPS API with its own keys.
What's the fastest way to test an integration before building the full app? Use curl with a single messages request against a test key, confirm you get a valid response, then move that same request into your application code. The /docs/quickstart walks through this in under a few minutes.
Should I use streaming for every integration? No. Streaming matters for interactive UIs like chat, where perceived latency counts. For background jobs, batch processing, or one-off summarization, a standard non-streaming request is simpler to implement and debug.