Neon is expanding into a backend: Object Storage, Functions, and AI Gateway now in beta
/AI Gateway/Chat completions

Chat completions

The OpenAI-compatible unified endpoint

Beta

The Neon AI Gateway is in Beta. Share your feedback on Discord or via the Neon Console.

The chat completions endpoint is the recommended way to use Neon AI Gateway. It's fully compatible with the OpenAI Chat Completions API and works with every model in the AI Gateway catalog. Switch models by changing a single field.

Base URL: https://<branch-host>/v1

This endpoint is also reachable at the longer /ai-gateway/mlflow/v1/chat/completions path. Both behave identically and neither is deprecated. See Shorter /v1 paths for the full list of aliases.

If you're using an OpenRouter-compatible client that asks for a base URL, set it to https://<branch-host>/v1 and call /chat/completions.

Setup

Set these environment variables. See Get started for how to obtain them.

NEON_AI_GATEWAY_TOKEN=nt_live_...
NEON_AI_GATEWAY_BASE_URL=https://br-winter-pond-aptw82ef-api.ai.c-2.us-east-2.aws.neon.tech

Basic request

import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: process.env.NEON_AI_GATEWAY_TOKEN,
  baseURL: `${process.env.NEON_AI_GATEWAY_BASE_URL}/v1`,
});

const response = await client.chat.completions.create({
  model: 'gpt-5-mini',
  messages: [
    { role: 'system', content: 'You are a helpful assistant.' },
    { role: 'user', content: 'What is Neon?' },
  ],
  max_tokens: 256,
});

console.log(response.choices[0].message.content);

Streaming

Add stream: true to receive a server-sent events response.

import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: process.env.NEON_AI_GATEWAY_TOKEN,
  baseURL: `${process.env.NEON_AI_GATEWAY_BASE_URL}/v1`,
});

const stream = await client.chat.completions.create({
  model: 'gpt-5-mini',
  messages: [{ role: 'user', content: 'Explain branching in Postgres.' }],
  stream: true,
});

for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? '');
}

Switching models

Change the model field to use a different provider. Everything else stays the same.

// OpenAI
model: 'gpt-5-4'

// Google
model: 'gemini-3-flash'

// Alibaba
model: 'qwen3-next-80b-a3b-instruct'

For a few models, message.content comes back as an array of content blocks instead of a plain string. See Content shape varies by model before swapping in a model you haven't used yet.

See Models for the full list.

Rate limiting

There are two separate rate limit tiers:

  • Neon account quota: enforced by Neon. Returns 429 with error code REQUEST_LIMIT_EXCEEDED. See Rate limits for current limits.
  • Upstream provider limit: enforced by the Databricks workspace serving the model. Returns 429 with forwarded rate limit headers.

When the upstream provider rate-limits a request, AI Gateway forwards the relevant headers so your client can back off correctly:

HeaderDescription
Retry-AfterSeconds to wait before retrying (RFC 9110)
X-Ratelimit-Limit-RequestsRequest limit
X-Ratelimit-Remaining-RequestsRemaining requests
X-Ratelimit-Reset-RequestsTime until request limit resets
X-Ratelimit-Limit-TokensToken limit
X-Ratelimit-Remaining-TokensRemaining tokens
X-Ratelimit-Reset-TokensTime until token limit resets

Error handling

StatusMeaningCommon cause
400 Bad RequestInvalid requestUnknown model ID, or model used on the wrong endpoint
413 Request Entity Too LargeBody too largeRequest body exceeds 32 MiB. Reduce the size of your request.
401 UnauthorizedAuthentication failedMissing or invalid NEON_AI_GATEWAY_TOKEN
403 ForbiddenAccess deniedCredential lacks ai_gateway:invoke scope, or branch not in credential lineage
429 Too Many RequestsAccount quota exceededYour account's AI Gateway quota is blocked. Error code: REQUEST_LIMIT_EXCEEDED. Check Retry-After for when to retry, or contact support.
429 Too Many RequestsUpstream rate limitedUpstream provider rate limit. Check the Retry-After and X-Ratelimit-* headers.
502 Bad GatewayUpstream errorTemporary issue with the upstream workspace. Retry the request.

Error responses are a JSON object with an error.message field:

{
  "error": {
    "message": "unknown model \"<model-id>\""
  }
}

Next steps

Need help?

Join our Discord Server to ask questions or see what others are doing with Neon. For paid plan support options, see Support.

Was this page helpful?
Edit on GitHub