Bring your own LLM provider
Call any OpenAI-compatible API with your own key — no platform setup
Your app can talk to any AI provider that speaks the standard OpenAI API — a hosted service or a server you run — using your own account and your own key. No Percher setup is needed, and the request never touches Percher's managed-inference service.
Use this when you already have a provider account, need a specific model, or want inference under a particular jurisdiction. Use managed inference instead when you want no provider account at all — there Percher holds the key and meters the cost.
Two env vars, then publish:
bunx percher env set LLM_API_KEY --from-file ./key.txt bunx percher env set LLM_BASE_URL=https://your-provider.example/v1 bunx percher publish
Keep the key server-side
LLM_API_KEY matches no public build prefix, so it is not forwarded to the build and will not reach the client bundle. That is the default you want. Two platform mechanisms can override it — renaming the key to VITE_*, NEXT_PUBLIC_*, or another public prefix, and listing it in [build] pass_env — so do neither. Your own code can still leak it: don't serialize it into a response, a client bundle, or a custom Dockerfile layer. Call the provider from a server route, API handler, or server action — a key shipped to the browser is readable by every visitor, and browser-side calls bypass the egress proxy entirely. LLM_BASE_URL and LLM_MODEL are not secrets and may be public if your framework needs them at build time.
Point the OpenAI SDK at your provider
import OpenAI from "openai";
const ai = new OpenAI({
apiKey: process.env.LLM_API_KEY,
baseURL: process.env.LLM_BASE_URL,
});
const res = await ai.chat.completions.create({
model: process.env.LLM_MODEL ?? "your-provider-model-id",
messages: [{ role: "user", content: prompt }],
});Use your provider's documented base URL verbatim — some publish it with a /v1 suffix and some without, and the SDK appends the route path to whatever you give it.
How the call leaves Percher (proxy, HTTPS, 30-second timeout)
The request leaves through Percher's egress proxy, like other server-side outbound traffic — use an HTTPS endpoint. The proxy has a 30-second idle timeout: stream long completions, or a slow non-streaming call can be cut.
Apps reach the public internet through the forward proxy Percher injects — seven variables: HTTP_PROXY, HTTPS_PROXY, NO_PROXY=localhost,127.0.0.1,.local, each one's lowercase twin, and NODE_USE_ENV_PROXY=1. The proxy does not filter destinations, so any public provider hostname works without configuration. Bun and Node 22.21+/24+ honor it automatically; Python and Go honor the proxy variables natively; Node 20 and the 21/23 lines need setGlobalDispatcher(new ProxyAgent(process.env.HTTPS_PROXY)) from undici at startup.
Anonymous apps can't call out
An unclaimed app has no outbound access at all — it runs on an isolated network the proxy is not attached to. Claim it, or publish while signed in, before expecting a provider call to connect. On a claimed app an ENETUNREACH means the runtime is not using the proxy; on an anonymous app it is expected.
Catch a missing key before the build
Declare the keys so a missing value is caught at upload time instead of 90 seconds into a build:
[env] required = ["LLM_API_KEY", "LLM_BASE_URL"] optional = ["LLM_MODEL"]
A missing required key returns REQUIRED_ENV_MISSING with the exact key list.
Which providers work — and which don't
Anything speaking the OpenAI chat-completions format: hosted providers, EU- or Sweden-based endpoints such as staik, aggregator gateways, and self-hosted servers like Ollama or vLLM reachable over the public internet. Percher does not operate, vet, or have a commercial relationship with these providers — the list is illustrative of the API shape, not a recommendation. An endpoint on your own private network is not reachable: your app runs on Percher's infrastructure, not yours, so the provider needs a public hostname.
Data protection: who can read what
You remain the controller for prompt content, and you contract directly with the inference provider in addition to your agreement with Percher — Percher still hosts the process and handles the key. These calls do not go through Percher's managed-inference path, so its approval gate does not apply.
Two things to be precise about. Outbound traffic traverses Percher's egress proxy — with an HTTPS endpoint the proxy carries an opaque tunnel and cannot read request or response bodies, which is the reason to insist on HTTPS. And your key is encrypted at rest, but Percher's control plane necessarily handles it in plaintext when you set it and again when it is injected at deploy time: it is a secret shared with the platform, exactly like any other env var. Check where your provider processes data and what it retains before sending personal data.