Connect with the Neon AI Gateway
Neon gives each branch of a project its own AI Gateway. Add the gateway's URL and a Neon token to Mubit as a provider key, and Mubit sends your project's calls on the OpenAI, Anthropic and Gemini prefixes to that gateway, unless the project has its own key for that provider. Your app keeps Mubit's base URL for the provider and your Mubit key.
The Neon AI Gateway is offered in the workspaces on app.mubit.ai, for every organization there. It isn't offered in other workspaces yet. If Neon AI Gateway isn't in the Provider menu under Provider keys, your workspace doesn't offer it.
Before you start
- Your Neon branch's Gateway URL and a Neon token. Provider keys shows where to find both.
- A Neon AI Gateway key in your project. An admin of your organization adds it under Provider keys, as Add a Neon key shows.
- A Mubit key for your project. To create one, follow step 1 of the Quickstart.
Which calls go to Neon
A call goes to Neon when it is on the OpenAI, Anthropic or Gemini prefix, and your project has a Neon key but no key of its own for that prefix's provider. Neon has no prefix in Mubit: your app uses the same base URLs as without Neon.
For each call, Mubit uses the first of these that applies:
- Your key for the provider. A call on
/anthropicuses your Anthropic key, a call on/openai/v1your OpenAI key, and a call on/geminiyour Gemini key. - Your Neon AI Gateway key. Mubit sends the call to your branch's gateway.
With none of these, the call gets 403 provider_key_missing.
- Your own key always comes first. With an OpenAI key and a Neon key, your OpenAI calls go to OpenAI. Delete the OpenAI key to send them to Neon.
- OpenAI-compatible services never go to Neon. A call under
/compat/{service}/v1uses the service's own key. Neon is not one of the services: see OpenAI-compatible services. - A project takes one Neon key, so its calls go to one branch's gateway.
The order holds for every client that calls these prefixes, such as the tools in Coding tools and the libraries in Frameworks.
Where Neon receives the call
Mubit sends the call to the Gateway URL saved with your key. It adds Neon's path for that API, then the rest of your call's path:
| Your call | Mubit sends it to your gateway at |
|---|---|
POST /openai/v1/chat/completions, POST /openai/v1/embeddings, GET /openai/v1/models | /v1/… |
POST /openai/v1/responses | /openai/v1/responses |
POST /anthropic/v1/messages | /anthropic/v1/messages |
POST /gemini/v1beta/models/{model}:generateContent | /gemini/v1beta/models/{model}:generateContent |
Neon's documentation says which of its models each path serves. It says most of its models, Claude and Gemini models included, work on Chat Completions, so the OpenAI prefix reaches the most models.
Send a call
The code is the code on the OpenAI, Anthropic and Gemini pages: Mubit's base URL for the provider, and your Mubit key. Install the SDKs as those pages show. These examples assume your project has no key of its own for the provider.
Only the model changes. Use a model ID from Neon's list, and replace MODEL_ID in the examples with it. To list the IDs your gateway serves, call GET /openai/v1/models. With a Neon key and no OpenAI key, the answer is Neon's list:
curl https://api.mubit.ai/openai/v1/models \
-H "Authorization: Bearer $MUBIT_API_KEY"OpenAI
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.mubit.ai/openai/v1",
api_key=os.environ["MUBIT_API_KEY"],
)
instructions = (
"Sort the support message into one category: "
"billing, bug, account or other. Reply with the category only."
)
response = client.chat.completions.create(
model="MODEL_ID",
messages=[
{"role": "system", "content": instructions},
{"role": "user", "content": "I was charged twice for my October invoice."},
],
)
print(response.choices[0].message.content)Anthropic
import os
from anthropic import Anthropic
client = Anthropic(
base_url="https://api.mubit.ai/anthropic", # no /v1
api_key=os.environ["MUBIT_API_KEY"],
)
instructions = (
"Sort the support message into one category: "
"billing, bug, account or other. Reply with the category only."
)
message = client.messages.create(
model="MODEL_ID",
max_tokens=64,
system=instructions,
messages=[
{"role": "user", "content": "I was charged twice for my October invoice."},
],
)
print(message.content[0].text)Gemini
import os
from google import genai
from google.genai import types
client = genai.Client(
api_key=os.environ["MUBIT_API_KEY"],
http_options=types.HttpOptions(
base_url="https://api.mubit.ai/gemini", # no /v1beta
),
)
instructions = (
"Sort the support message into one category: "
"billing, bug, account or other. Reply with the category only."
)
response = client.models.generate_content(
model="MODEL_ID",
contents="I was charged twice for my October invoice.",
config=types.GenerateContentConfig(system_instruction=instructions),
)
print(response.text)The TypeScript examples use top-level await, so run them as ES modules: save the file with an .mts name, such as neon.mts, and run npx tsx neon.mts, or add "type": "module" to your package.json.
To stream an answer, set the options the provider's page shows: OpenAI, Anthropic or Gemini. Mubit streams Neon's answer back to your app as it arrives.
Neon's documentation lists generateContent and streamGenerateContent for its Gemini path. Another Gemini call, such as countTokens, gets an error from Neon. To call a Gemini model with the OpenAI SDK, use the OpenAI base URL and a Gemini model ID from Neon's list.
What Mubit sends to Neon
- Where: only to the Gateway URL saved with your key, over HTTPS, and only while that URL is under Neon's gateway domain, which is
aws.neon.techtoday. Mubit checks the URL again before each call. A URL it doesn't send keys to gets403 provider_region_unavailable. Mubit connects to public addresses only and follows no redirect: a redirect from Neon gets502 upstream_redirect. - The token: your Neon token goes in the
Authorization: Bearerheader, whichever API the call uses. Mubit takes out your Mubit key and the credentials an SDK sends for its own key:authorization,x-api-key,x-goog-api-keyandkey=in the query. - Other headers: headers such as
anthropic-versionandanthropic-betago on as you sent them. Cookies,x-middleware-storeandx-middleware-recorddon't. - The answer: Neon's answer comes back as Neon sent it, with its
retry-afterandx-ratelimit-*headers. Mubit passes Neon's errors back too. - Recording: Mubit records a call to Neon as it records any call, and you lower it with the same headers: see What Mubit records.
- Adapters: a recorded call can become an example an adapter trains on. A Chat Completions call on
/openai/v1can be answered by an adapter in place of Neon: see Calls answered by an adapter.
See the call in Requests
A call that goes to Neon shows in Requests like any other call. See Find calls in Requests.
If a call fails
The error names its code. Troubleshooting lists the codes and what to do. Each answer carries the call's ID in the x-middleware-request-id header: see Find a call's request ID.
403 provider_region_unavailable: the URL saved with your Neon key isn't one Mubit sends keys to. An admin deletes the key and adds it again under Provider keys.- An error from Neon: an error without the type
middleware_gateway_errorcame from Neon, as Neon sent it. Its message says why, and Neon's documentation lists its codes. A401or403usually means Neon refused the token: an admin rotates the key under Provider keys.