The API exposed by apps/api (Rust proxy) is compatible with the OpenAI API format. Any client library or tool that supports a custom base URL can use OpenProxy without code changes.

Base URL

| Environment | URL | | --- | --- | | Local development | http://localhost:5060 | | Production (Docker) | https://api.example.com (after reverse proxy) |

Authentication

All endpoints except /health require a Bearer token issued by the apps/server backend:

Authorization: Bearer op_xxxxxxxxxxxxxxxxxxxxxxxxxxxx

Each API key can be scoped to specific models, have rate limits, a usage quota, and expiry settings configured in the admin panel.

Endpoints

| Method | Path | Auth required | Description | | --- | --- | --- | --- | | GET | /health | No | Liveness probe | | GET | /v1/models | Yes | List models the key can access | | POST | /v1/chat/completions | Yes | OpenAI-compatible chat (streaming supported) | | POST | /v1/messages | Yes | Anthropic-compatible messages | | POST | /v1/embeddings | Yes | Embeddings |


GET /health

Returns 200 OK with a plain-text body when the proxy is running.

curl http://localhost:5060/health
# → 200 OK

GET /v1/models

Returns all models the authenticated API key is permitted to access.

curl http://localhost:5060/v1/models \
  -H "Authorization: Bearer <your-api-key>"

Response

{
  "object": "list",
  "data": [
    { "id": "gpt-4o", "object": "model", "created": 0, "owned_by": "openai" },
    { "id": "claude-3-5-sonnet", "object": "model", "created": 0, "owned_by": "anthropic" }
  ]
}

POST /v1/chat/completions

OpenAI-compatible chat completions. The proxy selects a provider + upstream key, forwards the request, and returns the response transparently.

Request

curl http://localhost:5060/v1/chat/completions \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o",
    "messages": [
      { "role": "system", "content": "You are a helpful assistant." },
      { "role": "user", "content": "Hello!" }
    ],
    "stream": false
  }'

Set "stream": true to receive a Server-Sent Events (SSE) stream.

Response (non-streaming)

{
  "id": "chatcmpl-xxx",
  "object": "chat.completion",
  "created": 1700000000,
  "model": "gpt-4o",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "Hello! How can I help?" },
      "finish_reason": "stop"
    }
  ],
  "usage": { "prompt_tokens": 19, "completion_tokens": 10, "total_tokens": 29 }
}

POST /v1/messages

Anthropic-compatible messages endpoint for models such as claude-3-5-sonnet.

curl http://localhost:5060/v1/messages \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-3-5-sonnet",
    "max_tokens": 1024,
    "messages": [
      { "role": "user", "content": "Summarize quantum entanglement in one paragraph." }
    ]
  }'

POST /v1/embeddings

curl http://localhost:5060/v1/embeddings \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "text-embedding-3-small",
    "input": "The food was delicious."
  }'

Using with client libraries

Python (openai)

from openai import OpenAI

client = OpenAI(
    api_key="op_xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    base_url="http://localhost:5060/v1",
)

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

TypeScript (openai)

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: "op_xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  baseURL: "http://localhost:5060/v1",
});

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

Error responses

| HTTP Status | Meaning | | --- | --- | | 401 Unauthorized | Missing or invalid API key | | 403 Forbidden | Key does not have access to the requested model | | 400 Bad Request | Malformed request body | | 429 Too Many Requests | Rate limit or quota exceeded | | 502 Bad Gateway | All upstream providers failed for this request | | 5xx | Internal error or upstream unreachable |

Error body format

{
  "error": {
    "message": "You do not have access to model gpt-4o",
    "type": "permission_error",
    "code": 403
  }
}

Troubleshooting

| Symptom | Likely cause | Fix | | --- | --- | --- | | 401 | Key missing or wrong format | Include Authorization: Bearer op_... header | | 403 | Model not in key's allowlist | Add model access in admin panel | | 429 | Quota exhausted | Increase quota or use a different key | | 502 | All providers down or keys exhausted | Check provider API status; add working provider keys | | Slow initial response | Cold start or key decryption first time | The proxy caches decrypted keys — subsequent calls are faster |