Docs>REST API>OpenAI Compatible

OpenAI-Compatible Proxy

AI Pass exposes an OpenAI-compatible endpoint. Point any OpenAI SDK, agent framework, or tool at https://aipass.one/v1 and it just works. No code changes are needed beyond swapping the base URL and API key.

Base URL

https://aipass.one/v1

Use your AI Pass API key (starts with sk-aikey-) as the Bearer token. Get one from the Developer Dashboard. Existing /apikey/v1 base URLs remain supported.

Quick start

Send a chat completion with curl:

curl https://aipass.one/v1/chat/completions \
  -H "Authorization: Bearer sk-aikey-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o-mini",
    "messages": [{"role": "user", "content": "Hello!"}]
  }'

The response is identical to the OpenAI response format, so your existing parsing code works as-is.

Authentication

Pass your AI Pass API key in the Authorization header as a Bearer token:

Authorization: Bearer sk-aikey-YOUR_KEY

Your key is validated against your account balance. Requests are rejected with 403 if the key is invalid, revoked, or your balance is exhausted.

Create and manage keys in the Developer Dashboard. Each key maps to a LiteLLM virtual key internally. The model provider never sees your AI Pass key.

Supported endpoints

The proxy allowlists these paths. Requests to any other path return 403 Endpoint not allowed.

MethodPathDescription
POST/v1/decisionsTyped decisions with probabilities (JSON only)
GET/v1/modelsList available models
POST/v1/chat/completionsChat completions (streaming supported)
POST/v1/completionsText completions (legacy)
POST/v1/embeddingsText embeddings
POST/v1/images/generationsImage generation (DALL-E, Fal)
POST/v1/images/editsImage editing
POST/v1/audio/transcriptionsSpeech to text (Whisper)
POST/v1/audio/speechText to speech
POST/v1/responsesResponses API
POST/v1/videosVideo generation
GET/v1/videos/{id}Poll video generation status

Decisions

Decision models return typed answers and probabilities for routing, triage, moderation, scoring, yes/no checks, or picking a tool. Use a chat model when you need generated text or an explanation. State can be a string, JSON object, or array. Named questions use choice, score, or noul. Responses are JSON and never streamed.

Discover models at runtime with catalog type: "decision", capability decision, and method: "decisions", or type=decision&method=decisions. TypeSafe Jev 1.13 (jev-1.13, example ID) is live at $0.042 per 1M input tokens with free output. It accepts text-only input: up to 64k tokens per request, and 32k for state plus the longest question. Never hardcode a model list.

Instructions can be a string, object, or array. Choice criteria is an object with 2..255 options. Score criteria is an ordered array with 2..10 levels, never a levels field. Noul criteria is optional, or an object with true and false descriptions.

curl https://aipass.one/apikey/v1/decisions \
  -H "Authorization: Bearer $AI_PASS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '
  {
    "model": "jev-1.13",
    "state": "My integration is broken and I am unhappy.",
    "questions": {
      "team": {"type":"choice","instructions":"Pick a team","criteria":{"billing":"Payments","technical":"Bugs"}},
      "happy": {"type":"score","instructions":"Rate happiness","criteria":["Unhappy","Neutral","Happy"]},
      "angry": {"type":"noul","instructions":"Is the customer angry?"}
    }
  }
  '

For app users, use an OAuth2 token with api:access and the app client ID:

curl https://aipass.one/oauth2/v1/decisions \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "X-AIPass-OAuth-Client-Id: CLIENT_ID" \
  -H "Content-Type: application/json" \
  -d '
  {
    "model": "jev-1.13",
    "state": "My integration is broken and I am unhappy.",
    "questions": {
      "team": {"type":"choice","instructions":"Pick a team","criteria":{"billing":"Payments","technical":"Bugs"}},
      "happy": {"type":"score","instructions":"Rate happiness","criteria":["Unhappy","Neutral","Happy"]},
      "angry": {"type":"noul","instructions":"Is the customer angry?"}
    }
  }
  '

Ask many questions in one call against one state instead of chaining calls (speculative fan-out). Choice and score confidence is separate from probability; use low confidence to fall back to an LLM or a human. Score is 0-based against its response legend and can fall between levels. Noul is the probability of yes. Responses include model, answers, usage.input_tokens, and usage.output_tokens. Invalid requests return 4xx with an error.message or gateway error string; 402 uses existing SDK budget handling.

The /apikey/decisions and /oauth2/decisions aliases accept the same body. Browser and React Native apps can call AiPass.decide({ model, state, questions, signal, timeout }). See the SDK examples.

Available models

Fetch the live model list from the proxy. This reflects exactly what your key can access:

curl https://aipass.one/v1/models \
  -H "Authorization: Bearer sk-aikey-YOUR_KEY"

// Response:
{
  "object": "list",
  "data": [
    { "id": "gpt-4o",      "object": "model", "owned_by": "openai" },
    { "id": "gpt-4o-mini", "object": "model", "owned_by": "openai" },
    { "id": "claude-sonnet-4-6", "object": "model", "owned_by": "openai" },
    ...
  ]
}

Models are routed through LiteLLM. Claude, Gemini, and other providers are listed using their LiteLLM model IDs.

Streaming

Set "stream": true in the request body. The proxy detects this automatically and returns a standard SSE stream:

curl https://aipass.one/v1/chat/completions \
  -H "Authorization: Bearer sk-aikey-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o-mini",
    "stream": true,
    "messages": [{"role": "user", "content": "Count to 5"}]
  }'

// Response (SSE):
data: {"choices":[{"delta":{"content":"1"},...}]}
data: {"choices":[{"delta":{"content":","},...}]}
...
data: [DONE]

Integration examples

Python (openai SDK)

from openai import OpenAI

client = OpenAI(
    base_url="https://aipass.one/v1",
    api_key="sk-aikey-YOUR_KEY",
)

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "Hello!"}],
)
print(response.choices[0].message.content)

JavaScript / TypeScript (openai SDK)

import OpenAI from 'openai'

const client = new OpenAI({
  baseURL: 'https://aipass.one/v1',
  apiKey: 'sk-aikey-YOUR_KEY',
})

const response = await client.chat.completions.create({
  model: 'gpt-4o-mini',
  messages: [{ role: 'user', content: 'Hello!' }],
})
console.log(response.choices[0].message.content)

LangChain (Python)

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model="gpt-4o-mini",
    base_url="https://aipass.one/v1",
    api_key="sk-aikey-YOUR_KEY",
)

result = llm.invoke("What is the capital of France?")
print(result.content)

Cursor, Claude Code, and other agent tools

Any tool that accepts a custom OpenAI base URL works. Set:

OPENAI_BASE_URL=https://aipass.one/v1
OPENAI_API_KEY=sk-aikey-YOUR_KEY

Most tools (LiteLLM, LlamaIndex, Vercel AI SDK, CrewAI, AutoGen, etc.) read these environment variables automatically.

Need OAuth2 for user-facing apps instead of API keys? See the REST API / OAuth2 guide. To manage API keys programmatically, see the Management API.

Want a fresh agent brief?

Choose your agent and copy one secure brief. It inspects the project, requests narrow setup approval, and creates only the public configuration it needs.

Run one-click setup

Stuck? We're happy to help on Discord

Active Discord community with the AI Pass team. Get unblocked on integration, ask about models, share what you're building.

Join AI Pass Discord