Not every team runs on Next.js. Plenty of startups still ship Express APIs behind a React or Vue SPA, mobile clients, or webhook workers. The integration pattern is the same as other stacks: keep the API key on the server, forward JSON to your AI provider, and stream tokens back to the client.
This tutorial targets Node 20+ with Express. For App Router examples, see Next.js AI API integration.
Setup
npm install express dotenv.env:
DAYMORA_API_KEY=your_key_here
PORT=3001Never commit .env. Rotate keys using the workflow in Managing API keys securely.
Basic JSON route
import express from "express";
import "dotenv/config";
const app = express();
app.use(express.json({ limit: "1mb" }));
app.post("/api/chat", async (req, res) => {
const upstream = await fetch("https://daymora.com/api/v1/chat", {
method: "POST",
headers: {
"Content-Type": "application/json",
API_SECRET: process.env.DAYMORA_API_KEY,
},
body: JSON.stringify({
model: req.body.model ?? "gpt-5",
messages: req.body.messages,
stream: false,
}),
});
const text = await upstream.text();
res.status(upstream.status).send(text);
});
app.listen(process.env.PORT ?? 3001);Streaming route
Pipe the upstream body through without buffering the full completion:
app.post("/api/chat/stream", async (req, res) => {
const upstream = await fetch("https://daymora.com/api/v1/chat", {
method: "POST",
headers: {
"Content-Type": "application/json",
API_SECRET: process.env.DAYMORA_API_KEY,
},
body: JSON.stringify({
model: req.body.model ?? "gpt-5",
messages: req.body.messages,
stream: true,
}),
});
if (!upstream.ok) {
res.status(upstream.status).end(await upstream.text());
return;
}
res.setHeader("Content-Type", "text/event-stream");
res.setHeader("Cache-Control", "no-cache");
res.setHeader("Connection", "keep-alive");
const reader = upstream.body.getReader();
const pump = async () => {
while (true) {
const { done, value } = await reader.read();
if (done) break;
res.write(value);
}
res.end();
};
pump().catch(() => res.end());
});Understand transport tradeoffs in SSE vs WebSockets for AI streaming.
CORS for SPAs
If your React app runs on localhost:5173 and API on localhost:3001, enable CORS only for known origins — not * with credentials. Rate-limit by user id or session to prevent abuse.
Deploy notes
- Use platform secrets for
DAYMORA_API_KEY - Set request timeouts above your p95 model latency
- Log
statusandduration_ms, not raw prompts in production
Cost planning
Express services often power high-volume webhooks (support tickets, email ingest). Token bills scale with every message. Estimate with How much does an AI chatbot cost? or consider flat-rate if AI is always on (pricing comparison).
Summary
Express is a thin, proven proxy layer for AI APIs: JSON for simple clients, streamed responses for chat UIs, keys in environment variables only. Pair it with a frontend streaming pattern from our React chatbot guide and you have a stack familiar to most JavaScript teams.