AnswersAI security

How to store your OpenAI key server-side

Keep your provider key out of the browser and the app bundle. Paste it once in the dashboard, and your app calls the tool by name with its inputs. The key and the prompt stay on the server.

01 / OVERVIEW

Why the key stays on the server

A provider key in client code is a key anyone can copy. It is included in the app bundle, where anyone who opens the site or app can read it and spend against your account. Obfuscation does not fix that. Gemmein holds the key on the server and gives the browser a named tool to call instead.

02 / WHERE THE KEY GOES

Where the key goes

In the cloud, you paste the key on the dashboard's AI page, never in a file and never in the SDK. On your machine, npx gemmein dev reads the key from an environment variable such as GEMMEIN_AI_KEY_OPENAI. Without one, it answers with a sample reply marked x-gemmein-ai: fake. Keys never sync between the two. You can connect OpenAI, Anthropic, Google, Deepgram, Replicate, fal, AssemblyAI, ElevenLabs or Runway, or any OpenAI-compatible chat provider (OpenRouter, Mistral, Groq).

You can define a tool before you add its key. Calls are refused with ai_not_configured until you paste the key, and then the same tool runs with no further change.
03 / HOW IT WORKS

How it works

A tool is a file in your project: provider, model, instructions, template and inputs. Gemmein builds the provider request from the tool and runs it on your key for a signed-in person, at the tool's price. The browser sends only a tool name and its inputs, and the key is never in a request your app can read.

gemmein/ai/tools/deep-research.jsonTool definition
{
  "label": "Deep Research",
  "provider": "openai",
  "model": "gpt-4o",
  "credits": 20,
  "instructions": "You are a careful research assistant. Answer with sources.",
  "promptTemplate": "Research this question:\n\n{{question}}",
  "inputs": [
    { "name": "question", "type": "text", "required": true, "maxLength": 2000 }
  ]
}
Your app calls the toolJavaScript / Expo
// A name and inputs. No key. No prompt. No provider request.
const answer = await g.ai.runText("deep-research", {
  question: "How can I improve client onboarding?"
});

Upload the tool with npx gemmein sync.

04 / WHY NOT THE BROWSER

Browser calls to the provider

If the browser built the provider request, your prompt would be in the bundle and the caller would control the request. So raw calls from the browser are off for every key until you turn them on for an app that needs them.

05 / OTHER KINDS OF AI

Images, audio, video and embeddings

Image, audio, video and transcript tools run on the same key. For embeddings, call the provider from your own server with your own key. To use your own model, run it behind an external tool at your URL. Gemmein still checks who the person is and what they hold.

06 / FOR YOUR CODING AGENT

Prompt for your coding agent

Paste this into Cursor, Claude, Bolt or Lovable so your agent keeps the key on the server from the start.

Prompt for your coding agentCopy and paste

Read https://docs.gemmein.com/llms.txt and https://docs.gemmein.com/ai. I do not want my OpenAI key in the browser or app bundle. Show me how the provider key stays on the server (pasted in the dashboard) and how my app calls a named AI tool by name with inputs, without sending the key or a prompt. Include the tool definition file and the client call.

Add Gemmein to your AI. Then tell it what you want.

Building is free. No card until you go live.