Blog

How to call Claude, GPT and Gemini with one API key

Most teams end up with three provider accounts, three keys, three bills, and three SDKs. You can drop to one key if your gateway speaks both the OpenAI and the Anthropic formats. This guide shows how to do that with AIKeys, using the SDKs you already have.

What you need

  • An AIKeys account with a positive balance. You top up once and each request draws from it. There is no monthly plan.
  • An inference key from the keys page. The secret is shown once, so copy it into an environment variable:
export AIKEYS_CO_KEY="paste-your-key-here"
  • A model id. Ids look like upstream/model, for example cc/claude-opus-4-7 or cx/gpt-5.6-terra. The full list, with prices, is on the models page.

The two base URLs

SDK Base URL Auth header it sends
OpenAI SDK https://api.aikeys.co/v1 Authorization: Bearer …
Anthropic SDK https://api.aikeys.co x-api-key: …

The Anthropic SDK adds /v1/messages to its base URL itself, so leave /v1 off. Both headers are accepted, so either SDK works with the same key.

Python with the OpenAI SDK

import os
from openai import OpenAI

client = OpenAI(base_url="https://api.aikeys.co/v1", api_key=os.environ["AIKEYS_CO_KEY"])

for model in ["cc/claude-opus-4-7", "cx/gpt-5.6-terra", "ag/gemini-3.1-pro-high"]:
    reply = client.chat.completions.create(
        model=model,
        messages=[{"role": "user", "content": "One sentence: what is a token?"}],
    )
    print(model, "→", reply.choices[0].message.content)

The loop is the point: switching between Claude, GPT and Gemini is a change to one string.

Python with the Anthropic SDK

import os
from anthropic import Anthropic

client = Anthropic(base_url="https://api.aikeys.co", api_key=os.environ["AIKEYS_CO_KEY"])

message = client.messages.create(
    model="cc/claude-sonnet-4-6",
    max_tokens=512,
    messages=[{"role": "user", "content": "One sentence: what is a token?"}],
)
print(message.content[0].text)

max_tokens is required in the Messages format. You can send a GPT or Gemini id here too. The proxy converts the request for the upstream.

TypeScript

import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://api.aikeys.co/v1", apiKey: process.env.AIKEYS_CO_KEY });

const reply = await client.chat.completions.create({
  model: "cc/claude-haiku-4-5-20251001",
  messages: [{ role: "user", content: "One sentence: what is a token?" }],
});
console.log(reply.choices[0].message.content);

cURL

curl https://api.aikeys.co/v1/chat/completions \
  -H "Authorization: Bearer $AIKEYS_CO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"cc/claude-haiku-4-5-20251001","messages":[{"role":"user","content":"Hello"}]}'

List the models your key can call

curl https://api.aikeys.co/v1/models -H "Authorization: Bearer $AIKEYS_CO_KEY"

The id of each entry is exactly what you send as model. Ids must match exactly: cc/claude-haiku-4-5 and cc/claude-haiku-4-5-20251001 are different strings, and only listed ids work.

Errors you may see

Status Code What it means
401 invalid_api_key The key is wrong, revoked, or missing.
403 insufficient_key_scope The key is a config key. Use an inference key.
402 insufficient_quota The balance is too low. Top up.
404 model_not_found The model id is not listed. Check /v1/models.
429 rate_limit_exceeded Too many requests. The default is 60 a minute per key.
503 no_capacity No publisher is serving the model at or below the cap. You are not charged.

A 503 no_capacity is worth handling in code: retry later, or fall back to another model id.

What it costs

AIKeys is a marketplace. Publishers list capacity with an ask, and each request goes to the cheapest live ask. An ask is never more than half the official price. Live prices for every model are on the pricing page, and how per-token pricing works walks through the arithmetic.