Recipe: backend for frontend
Keeping the integration key on your server while a browser UI does the talking.
Reach for this when the browser needs something an embed key cannot do — cross-project access, per-user authorisation, or your own rate limiting and logging in front of chat.
import { createClient, OpragError } from "@oprag/sdk";
const oprag = createClient({
apiUrl: process.env.OPRAG_API_URL!,
apiKey: process.env.OPRAG_SECRET_KEY!,
});
app.post("/api/ask", async (req, res) => {
// Your auth, your rules — the integration key never leaves this process.
const user = await requireUser(req);
try {
const answer = await oprag.chat.ask({
question: req.body.question,
// Return these to the client so the next turn keeps its context.
sessionId: req.body.sessionId,
conversationId: req.body.conversationId,
visitorId: user.id,
});
if (answer.type === "lead_capture_prompt") {
return res.json({ kind: "lead", prompt: answer.promptMessage, fields: answer.fields });
}
return res.json({ kind: "answer", answer: answer.answer, sources: answer.sources ?? [] });
} catch (err) {
if (err instanceof OpragError) {
return res.status(err.status).json({ error: err.message });
}
throw err;
}
}); If you do not need any of that, an embed key straight from the browser is fewer moving parts — see keys & security.
Ready to ship?
Get started free