Apps from Replit, Lovable, Bolt and v0
Use RouterPlus in apps built with Replit, Lovable, Bolt and v0.
Use this page when an app that you build in Replit, Lovable, Bolt or v0 has its own AI features, for example a chat box, a summary button or an agent. The app calls RouterPlus with your key. You select the model, and RouterPlus bills every call to one balance.
The builder's own agent cannot use RouterPlus. Replit Agent, Lovable, Bolt and v0 run on the builder's models, and the builder bills for them.
Before you start
- 01
- 02Create a key for the app in the console, under Access > API keys (API keys). A key looks like
tm_vk_.... - 03Set a monthly spend cap on the key with Set cap. Then a bug or a loop in the app cannot spend all of your balance.
- 04Select a model id from
/api/models.json.claude-sonnet-5-5is a good default.gpt-6-lunaandclaude-haiku-5-5cost less.
The prompt
Paste this text into the builder's chat:
Use my own API key. Call AI through RouterPlus: OpenAI-compatible, base URL https://demo-api.routerplus.com/v1, model claude-sonnet-5-5, key in a secret named TM_API_KEY.The builder writes code that calls the gateway with the OpenAI SDK. Then it asks you for the secret. If the builder offers its own AI service instead, say no. The builder bills that service.
For an app with more AI features, add these rules:
Rules for every AI call:
- Use the official OpenAI SDK with baseURL https://demo-api.routerplus.com/v1 and apiKey from the TM_API_KEY secret.
- Call it only from server-side code (an API route, a server action or a backend function). Never put the key in browser code.
- Send max_tokens on every request. Stream answers that a person reads as they arrive.
- Copy model ids from https://demo.routerplus.com/api/models.json. Never invent one.
- On an error, read error.metadata.error_type. On rate_limit, wait retry-after seconds, then retry, at most twice. On insufficient_quota, show "AI is unavailable" and do not retry.
- Docs for the gateway: https://demo.routerplus.com/llms.txtStore the key as a secret
Keep the key in the builder's secret store, with the name TM_API_KEY. Do not paste the key into the chat or into code.
| Builder | Where the secret goes |
|---|---|
| Replit | Tools → Setup → Secrets → New Secret, key TM_API_KEY, then Add Secret. The app reads it as an environment variable. A published app does not get workspace secrets: add the secret again under Publishing → Adjust settings → Production app secrets. |
| Lovable | More → Cloud → Secrets → Add secret, or the secure form that Lovable shows in the chat when it asks for the key. Only the app's server code (its backend functions) can read it. |
| Bolt | The Secrets page of Bolt Cloud (the database icon at the top): name TM_API_KEY, the key as its value, then Create secret. The app's server functions read it. |
| v0 | The project's Settings → Environment Variables (the Vars panel), for the environments that need it. The v0 preview reads the Development value. |
Keep the key on the server. The gateway accepts calls from any web page. Thus anyone who opens the app can copy a key from browser code. Some builders put a variable into browser code when its name starts with VITE_ or NEXT_PUBLIC_. Do not give the key such a name.
What the code looks like
The builder writes code like this. Use it to check the builder's work.
TypeScript, a server route with the official openai package:
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://demo-api.routerplus.com/v1",
apiKey: process.env.TM_API_KEY,
});
export async function POST(req: Request) {
const { question } = await req.json();
const reply = await client.chat.completions.create({
model: "claude-sonnet-5-5",
max_tokens: 1024,
messages: [{ role: "user", content: question }],
});
return Response.json({ answer: reply.choices[0]?.message.content });
}Python, a server with the official openai package:
import os
from openai import OpenAI
client = OpenAI(base_url="https://demo-api.routerplus.com/v1", api_key=os.environ["TM_API_KEY"])
reply = client.chat.completions.create(
model="claude-sonnet-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Summarize this note in one line."}],
)
print(reply.choices[0].message.content)Every chat model in the catalog, Claude and GPT, answers on /v1/chat/completions. GPT models also work with the OpenAI SDK's Responses API (client.responses.create, with model: "gpt-6-luna"). See POST /v1/responses. Claude models are a preview on that API, so call Claude on /v1/chat/completions.
Limits
- The builder's agent keeps its own models and pricing. Your RouterPlus balance pays only for the calls that your app makes.
- Each call bills at the model's price.
usage.costin each answer gives the amount. On the Responses API, it is inresponse.usage. GET /v1/usage and the console show what the app spent. - Rate limits and spend caps apply to the app's key. See Rate limits & spend caps.
Where next
- Coding agents: Claude Code, Codex, Cursor, Cline and more, on your own machine
- Agent integration guide: what a coding agent needs to build the gateway into an app
- POST /v1/chat/completions: the request and the answer, field by field
- Errors: each error class, and what the app should do
For agents: /docs/app-builders.md and /llms.txt