Why the browser call fails
A browser sends a preflight OPTIONS request before any cross-site request that carries an Authorization header. luv13 only approves that preflight for origins it allows. For other origins it answers 400, and the browser never sends the real request. The browser console shows a CORS error.
Check it yourself:
curl -s -o /dev/null -w "%{http_code}\n" -X OPTIONS \
https://api.luv13.ai/v1/chat/completions \
-H "Origin: https://example.com" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Headers: authorization,content-type"This printed 400 on 2026-09-30.
The fix: a small server route
Your page calls your server; your server adds the key and calls luv13. A minimal Node.js 18+ server with no dependencies:
// server.mjs — run with: LUV13_API_KEY=sk-luv13-... node server.mjs
import http from "node:http";
http.createServer(async (req, res) => {
if (req.method !== "POST" || req.url !== "/api/chat") {
res.writeHead(404).end();
return;
}
let body = "";
for await (const chunk of req) body += chunk;
const { message } = JSON.parse(body);
const upstream = await fetch("https://api.luv13.ai/v1/chat/completions", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.LUV13_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "luv13/glm-5.3-flash",
messages: [{ role: "user", content: String(message) }],
}),
});
res.writeHead(upstream.status, { "Content-Type": "application/json" });
res.end(await upstream.text());
}).listen(3000);The server fixes the model, so visitors can't pick what runs on your balance. In production, also add your own login or rate limit, since anyone who can reach /api/chat spends your credit.
