Your quota stays yours
OpenRouter, Pollinations, Cloudflare, Groq, Mistral, or your own endpoint. Every request uses your connected account.
BRING YOUR OWN ACCOUNTS
Connect your AI accounts, choose easy, medium or hard, and keep building. Streaming, automatic failover, and a clear view of your usage.
Create an accountOpenRouter, Pollinations, Cloudflare, Groq, Mistral, or your own endpoint. Every request uses your connected account.
easy for speed, medium for everyday work, hard for coding and reasoning. auto selects medium.
We record usage metadata. We never store or log prompts or completions. Provider policies still apply.
Create an account, connect a provider in your dashboard, and create an API key. Or install the CLI:
curl -fsSL https://ai.safetyvibe.eu/install.sh | sh aip login aip connect openrouter aip chat "Write a Python merge sort" eval "$(aip env --create-key --shell bash)"
Browser login uses OAuth with PKCE. On a headless machine, run aip login --device. aip env --create-key creates a stable API key for other tools; login tokens refresh automatically inside aip.
export OPENAI_BASE_URL="https://ai.safetyvibe.eu/v1" export OPENAI_API_KEY="aip_your_key"
Use an explicit model such as openrouter/meta-llama/llama-3.3-70b-instruct:free to select a fixed provider. List currently available models at GET /v1/models.
curl -N "$OPENAI_BASE_URL/chat/completions" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"model":"medium","messages":[{"role":"user","content":"Hello"}],"stream":true}'import os
from openai import OpenAI
client = OpenAI(base_url=os.environ["OPENAI_BASE_URL"],
api_key=os.environ["OPENAI_API_KEY"])
for chunk in client.chat.completions.create(
model="hard", messages=[{"role": "user", "content": "Explain binary search"}],
stream=True,
):
if chunk.choices:
print(chunk.choices[0].delta.content or "", end="", flush=True)import OpenAI from "openai";
const client = new OpenAI({
baseURL: process.env.OPENAI_BASE_URL,
apiKey: process.env.OPENAI_API_KEY,
});
const stream = await client.chat.completions.create({
model: "hard", messages: [{role: "user", content: "Explain binary search"}],
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}export OPENAI_API_BASE="$OPENAI_BASE_URL" aider --model openai/hard
aider uses OPENAI_API_BASE for its endpoint. aider configuration.
In your local Continue configuration, use the OpenAI provider with the same URL and key. Store the key in Continue secrets rather than in a shared repository.
name: aip
version: 1.0.0
schema: v1
models:
- name: aip hard
provider: openai
model: hard
apiBase: https://ai.safetyvibe.eu/v1
apiKey: ${{ secrets.OPENAI_API_KEY }}
Export OPENAI_API_KEY using aip env --create-key, then put this in ~/.codex/config.toml:
model = "gpt-5.5" model_provider = "aip" model_context_window = 32768 [model_providers.aip] name = "aip" base_url = "https://ai.safetyvibe.eu/v1" env_key = "OPENAI_API_KEY" wire_api = "responses" requires_openai_auth = false supports_websockets = false
The service translates Responses text, function tools and freeform custom tools to your provider's Chat Completions API. Send conversation history on each request; response storage, previous_response_id, background mode, and WebSockets are not supported. Hosted and unsupported tools (including web_search, file_search and multi_agent namespaces) are stripped; no Codex feature overrides are needed. Level names easy, medium, hard and auto are routing aliases without built-in Codex metadata. Use gpt-5.5 as the Codex metadata-compatible alias for hard; it selects your own connected upstreams, not an OpenAI subscription. The explicit context limit above is a conservative example; set it to the smallest context supported by every upstream model serving hard. Tool capability depends on your chosen upstream model. Custom-tool grammar constraints are sent as instructions, not enforced by the adapter. Official Codex configuration reference.
export ANTHROPIC_BASE_URL="https://ai.safetyvibe.eu" export ANTHROPIC_AUTH_TOKEN="$OPENAI_API_KEY" export ANTHROPIC_DEFAULT_HAIKU_MODEL="easy" export ANTHROPIC_DEFAULT_SONNET_MODEL="medium" export ANTHROPIC_DEFAULT_OPUS_MODEL="hard" claude --model medium
The base URL has no /v1 suffix. Messages text, images, tool_use and tool_result are translated to Chat Completions. Claude model names containing haiku, sonnet or opus map to easy, medium or hard respectively. You can also use an explicit provider/model. Anthropic prompt caching and extended thinking are not forwarded. Claude Code gateway documentation.
with client.responses.stream(model="hard", input="Explain binary search") as stream:
for event in stream:
if event.type == "response.output_text.delta":
print(event.delta, end="", flush=True)Discover endpoints at /.well-known/oauth-authorization-server (also available at /.well-known/openid-configuration). This is OAuth authorization with api and account scopes, not an OpenID issuer: no openid scope or ID tokens. Register a public client:
curl https://ai.safetyvibe.eu/oauth/register \
-H 'Content-Type: application/json' \
-d '{"client_name":"My tool","redirect_uris":["http://127.0.0.1/callback"],"grant_types":["authorization_code","refresh_token"],"token_endpoint_auth_method":"none"}'Generate a random 43–128 character PKCE verifier and use base64url(SHA256(verifier)) without padding as the challenge. Open /oauth/authorize?response_type=code&client_id=YOUR_ID&redirect_uri=YOUR_URI&scope=api%20account&state=RANDOM_STATE&code_challenge=CHALLENGE&code_challenge_method=S256. After login and consent, check state in the callback and exchange the code:
curl https://ai.safetyvibe.eu/oauth/token \ -d grant_type=authorization_code -d client_id=YOUR_ID \ --data-urlencode redirect_uri=YOUR_URI -d code=CODE -d code_verifier=VERIFIER
Use the bearer access token on /v1/* (api scope) or /api/* and /oauth/userinfo (account scope). Access tokens last one hour; refresh tokens last at most 30 days. Refresh with grant_type=refresh_token, client_id, and refresh_token; atomically save both new tokens. Reusing a refresh token revokes its entire family. Revoke with form fields client_id and token at /oauth/revoke. HTTPS redirects match exactly. Loopback HTTP redirects allow any port but must retain the registered host, path, and query. Device clients register the urn:ietf:params:oauth:grant-type:device_code grant, then use the metadata's device endpoint with client_id and scope. Poll /oauth/token at the returned interval, increasing it by five seconds after every slow_down response.
Default limits are 32 concurrent requests and 600 requests per minute per user. HTTP 429 includes Retry-After. Failover happens only before the first response byte; after a stream begins, an interrupted stream must be retried by your client. Provider model access, prices and free quotas can change. Model discovery is cached for one hour.