How to Add Claude to an Existing SaaS App
Adding Claude to an existing SaaS app comes down to three decisions: how you'll authenticate and route requests, how you'll stream responses into your existing UI, and how you'll track usage per customer so you can bill for it. Everything else — prompts, tool use, model selection — is easier to iterate on once those foundations are in place.
This guide walks through the actual integration path, not just "call the API." If you already have users, a database, and a billing system, the goal is to bolt Claude on without rebuilding your backend or your auth model.
Step 1: Decide where Claude calls live
You have two structural options:
- Server-side proxy — your backend calls Claude, your frontend never sees the API key. This is almost always the right choice for a SaaS app.
- Direct client calls — only viable for local dev tools or desktop apps where the key belongs to the end user.
For a multi-tenant SaaS app, route every Claude call through your own API layer:
Browser → Your backend (auth, rate limits, logging) → Claude → Your backend → Browser
This gives you a single point to enforce per-customer quotas, log usage for billing, and swap providers later without touching frontend code.
Step 2: Wire up the API call
At the core, a Claude integration is a POST request with a model, messages, and a max token limit:
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-sonnet-4-5",
"max_tokens": 1024,
"messages": [
{"role": "user", "content": "Summarize this support ticket: ..."}
]
}'
Wrap this in a single internal function — askClaude(prompt, options) — so every feature in your app (summaries, chat, classification) goes through one code path. That's where you'll later add retries, logging, and usage tracking without touching each feature individually.
If you'd rather skip managing raw Anthropic API keys, rate limits, and billing plumbing yourself, SubToAPI turns your existing Claude access into a standard HTTPS API with application keys (sub_live_...), so your backend just calls https://api.subtoapi.app/v1/messages with a Bearer token instead of managing provider credentials directly. See the quickstart for the exact request shape.
Step 3: Add streaming to match your UI
Most SaaS apps that add AI features want streamed responses — users expect text to appear token by token, not after a 10-second wait. Claude supports server-sent events for this:
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-5",
max_tokens: 1024,
stream: true,
messages: [{ role: "user", content: userMessage }],
}),
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
// parse SSE events, append text deltas to your UI
}
On the frontend, this maps naturally onto whatever chat or notification component you already have — you're just appending text as it arrives instead of rendering a static blob. Details on event types and chunk formats are in the streaming docs.
Step 4: Track usage per customer, not per API key
This is the part teams skip and regret. If Claude powers a feature inside a paid product, you need to know which customer, workspace, or seat generated which tokens — otherwise you can't debug cost spikes or gate usage by plan.
Two practical approaches:
- Tag requests in your own logs. Every call to your
askClaude()wrapper should logcustomer_id, token counts from the response, and the feature that triggered it. - Use per-application keys. If multiple products or environments (staging, production, different customer tiers) call Claude, issue separate keys for each so usage and rate limits don't bleed into each other. SubToAPI's dashboard shows usage metadata per key out of the box, which saves you from building this logging layer from scratch — see pricing for how seats and keys map to plans.
Either way, decide this before launch. Retrofitting usage attribution after a feature is live means reconstructing costs from incomplete logs.
Step 5: Handle tool use if the feature needs it
If Claude needs to call your internal functions — looking up an order, querying a database, triggering a webhook — use tool calling rather than trying to parse free text for structured actions:
{
"model": "claude-sonnet-4-5",
"max_tokens": 1024,
"tools": [
{
"name": "get_order_status",
"description": "Look up the status of a customer order",
"input_schema": {
"type": "object",
"properties": { "order_id": { "type": "string" } },
"required": ["order_id"]
}
}
],
"messages": [{ "role": "user", "content": "Where is order #4521?" }]
}
Claude returns a structured tool_use block with the arguments, your backend executes the actual lookup, and you send the result back in a follow-up message. This pattern is what makes Claude integrations feel like real product features instead of a chatbot bolted onto the side. Full request/response shapes are in the tool use docs and the general messages reference.
Step 6: Roll it out behind a flag
Add the feature behind your existing feature-flag or plan-gating system rather than shipping it to every user at once:
- Start with a small percentage of accounts or a specific plan tier.
- Monitor latency and token costs against real usage, not synthetic tests.
- Set a hard
max_tokensand a per-customer daily cap so a runaway loop doesn't turn into a surprise bill.
Once you're confident in cost and reliability, widen the rollout. This is also when per-key usage tracking from Step 4 pays off — you'll have real numbers instead of guesses.
Getting started
If you already have Claude access and want to skip provider key management, sign up for a free trial, generate an application key, and point your existing askClaude() wrapper at https://api.subtoapi.app/v1/messages. The request format matches the standard Claude Messages API, so the integration work described above doesn't change — you're just adding auth, streaming, and usage tracking on top without building it yourself.
FAQ
Do I need to change my backend architecture to add Claude? No. A single server-side wrapper function that calls the Messages API is enough for most SaaS apps. Keep the call server-side, never expose keys to the browser, and route every feature through that one function.
Should I stream responses or wait for the full reply? Stream if the output is longer than a sentence or two and the user is watching it happen (chat, summaries, drafts). Use a single non-streamed call for background jobs like classification or tagging where no one is waiting on the response in real time.
How do I control per-customer Claude costs in a SaaS app? Set a max_tokens ceiling on every request, log token usage against customer_id in your own database, and enforce a daily or monthly cap per plan tier before the request reaches Claude. Per-application API keys make this easier to isolate and audit.