This is a localhost demo only. Do not use in production. Try the live demo at test-client.infer0.com.

Build a chat app in 5 minutes

Get up and running with infer0. Pick the API format that fits your stack: OpenAI Chat Completions, Anthropic Messages, or OpenAI Responses. infer0 translates behind the scenes.

Prerequisites

  • Node.js 18+ installed
  • A terminal and your favorite editor

Step 1: Create your project

mkdir infer0-chat
cd infer0-chat

Step 2: Sign in and register an OAuth app

Go to infer0.com and sign in with Google or GitHub. Then go to OAuth Apps and create a new app. Set the redirect URI to http://localhost:3000/callback. Copy your client_id and client_secret.

Step 3: Set environment variables

export CLIENT_ID="your-client-id"
export CLIENT_SECRET="your-client-secret"
export REDIRECT_URI="http://localhost:3000/callback"
export PORT=3000

Step 4: Create the server

Save this as server.mjs:

import { randomUUID } from "crypto";
import http from "http";
import { URL } from "url";

const PORT = process.env.PORT;
const CLIENT_ID = process.env.CLIENT_ID;
const CLIENT_SECRET = process.env.CLIENT_SECRET;
const REDIRECT_URI = process.env.REDIRECT_URI;

const tokens = {};
const stateStore = new Map();

http.createServer(async (req, res) => {
  const url = new URL(req.url, `http://${req.headers.host}`);

  if (url.pathname === "/login") {
    const state = randomUUID();
    stateStore.set(state, true);
    res.writeHead(302, { Location: "https://infer0.com/oauth/authorize?client_id=" + CLIENT_ID + "&redirect_uri=" + REDIRECT_URI + "&response_type=code&state=" + state });
    return res.end();
  }

  if (url.pathname === "/callback") {
    const code = url.searchParams.get("code");
    const state = url.searchParams.get("state");
    if (!state || !stateStore.has(state)) {
      res.writeHead(400);
      return res.end("State mismatch - possible CSRF attack");
    }
    stateStore.delete(state);

    const params = new URLSearchParams({
      grant_type: "authorization_code",
      code: code,
      client_id: CLIENT_ID,
      client_secret: CLIENT_SECRET,
      redirect_uri: REDIRECT_URI,
    });

    const tokenRes = await fetch("https://infer0.com/v1/oauth/token", {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: params,
    });

    const data = await tokenRes.json();
    tokens.access = data.access_token;
    tokens.refresh = data.refresh_token;
    return res.end("Authorized! You can close this tab and use the chat.");
  }

  if (url.pathname === "/chat") {
    if (!tokens.access) {
      res.writeHead(302, { Location: "/login" });
      return res.end();
    }

    const chatRes = await fetch("https://infer0.com/v1/chat/completions", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": "Bearer " + tokens.access,
      },
      body: JSON.stringify({
        model: "ignored",
        messages: [{ role: "user", content: url.searchParams.get("q") || "Hello" }],
      }),
    });

    const chat = await chatRes.json();
    res.writeHead(200, { "Content-Type": "application/json" });
    return res.end(JSON.stringify(chat));
  }

  res.writeHead(404);
  res.end();
}).listen(PORT, () => console.log("Server running on http://localhost:" + PORT));

The model field is ignored. infer0 uses the model your user has configured.

Step 5: Run the server

node server.mjs

Step 6: Authorize your app

Open http://localhost:3000/login to start the OAuth flow. You'll sign in, select a provider, and approve the request.

Step 7: Make an inference

Visit http://localhost:3000/chat?q=What+is+the+capital+of+France to see a non-streaming response from the user's configured model.

Expected output

{
  "id": "chatcmpl-...",
  "object": "chat.completion",
  "created": 1717000000,
  "model": "gpt-4o-mini",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "The capital of France is Paris."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 14,
    "completion_tokens": 7,
    "total_tokens": 21
  }
}

Troubleshooting

Issue Fix
redirect_uri_mismatch Make sure the redirect URI in your OAuth App settings matches http://localhost:3000/callback exactly.
invalid_client Double-check your CLIENT_ID and CLIENT_SECRET environment variables.
invalid_grant The auth code expired (10 min). Go through /login again to get a fresh code.
No provider configured The user hasn't added an AI provider yet. Have them visit https://infer0.com/providers to add one.
Provider error with 401 The user's provider API key is expired or invalid. They need to update it on AI Providers.