Python LLM API quickstart: Claude and GPT with the OpenAI SDK
If your Python code already uses the openai package, you don't need a new SDK to call Claude, GPT, DeepSeek, Grok or Kimi models. apillms exposes an OpenAI-compatible endpoint at https://apillms.com/v1, so you just change the base URL and the API key — the rest of your code stays the same.
What you need
- Python 3.8+ with
pip install openai - An apillms account — sign-up gives you free starter credits, and one API key is created automatically
- Your key from the API keys page (click Show key)
There's no "create new key" button to look for — each account has exactly one key. If you ever suspect it leaked, use Roll key on the same page; that disables the old key immediately and issues a new one.
Minimal chat completion
Install the SDK and set two environment variables:
pip install openai
export APILLMS_API_KEY="your-key-here"
export APILLMS_BASE_URL="https://apillms.com/v1"
Then call it like any other OpenAI-compatible client:
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["APILLMS_API_KEY"],
base_url=os.environ["APILLMS_BASE_URL"],
)
response = client.chat.completions.create(
model="claude-sonnet-5",
messages=[
{"role": "user", "content": "Explain what a context window is, in two sentences."}
],
)
print(response.choices[0].message.content)
That's the whole integration. The model field is the only thing that changes which provider handles the request — there's no separate SDK for Anthropic models when you use the OpenAI-compatible path. (If you specifically want the Anthropic SDK or the /v1/messages shape instead, apillms also serves an Anthropic-compatible base URL at https://apillms.com, without the /v1 suffix — but for OpenAI SDK code, stick with the base URL above.)
Adding a system prompt, temperature, and max tokens
These parameters work exactly as they do against OpenAI's own API:
response = client.chat.completions.create(
model="claude-opus-5-5",
messages=[
{"role": "system", "content": "You are a terse code reviewer. No praise, just issues."},
{"role": "user", "content": "def add(a,b): return a+b"},
],
temperature=0.2,
max_tokens=300,
)
print(response.choices[0].message.content)
If you want to try different temperature or max-token settings before committing them to a script, the Playground lets you set the same parameters interactively — model, system prompt, temperature, max output tokens, streaming on/off — and has a Code button that generates a snippet matching whatever you just ran.
Switching models
All models on apillms share the same /v1/chat/completions endpoint, so switching is a one-line change. Some ids currently on sale: claude-sonnet-5, claude-opus-5-5, gpt-5.5, gpt-6-astra, deepseek-v4-flash, grok-4.7, kimi-k3. Check the full, filterable list on the Models & API page.
def ask(model, prompt):
resp = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}],
)
return resp.choices[0].message.content
for model in ["claude-sonnet-5", "gpt-5.5", "deepseek-v4-flash"]:
print(model, "->", ask(model, "What's 17 * 23?")[:80])
This is useful for A/B testing a prompt across models, or for routing cheap, high-volume calls to a lower-cost model like deepseek-v4-flash while keeping a stronger model like claude-opus-5-5 or gpt-6-astra for harder tasks.
Streaming responses
Streaming works the same way it does on OpenAI's own API:
stream = client.chat.completions.create(
model="gpt-6-astra",
messages=[{"role": "user", "content": "Write a haiku about caching."}],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta.content
if delta:
print(delta, end="", flush=True)
Async requests
For scripts that fire off many prompts concurrently, use AsyncOpenAI instead of changing anything else:
import asyncio
import os
from openai import AsyncOpenAI
client = AsyncOpenAI(
api_key=os.environ["APILLMS_API_KEY"],
base_url="https://apillms.com/v1",
)
async def ask(prompt):
resp = await client.chat.completions.create(
model="deepseek-v4-flash",
messages=[{"role": "user", "content": prompt}],
)
return resp.choices[0].message.content
async def main():
prompts = ["Summarize HTTP in one line.", "Summarize TCP in one line."]
results = await asyncio.gather(*(ask(p) for p in prompts))
for r in results:
print(r)
asyncio.run(main())
This is the same pattern you'd use against OpenAI directly — concurrency limits and retry logic in your own code apply the same way.
Troubleshooting common errors
A handful of issues cover most setup problems:
- 401 / authentication error — the key is wrong, missing, or wasn't exported in the current shell session. Re-check it on the API keys page (Show key), and confirm
os.environ["APILLMS_API_KEY"]actually resolves in your script with a quickprint. - 404 or model-not-found — the
modelstring is misspelled or not currently offered. Copy the exact id from the Models & API page rather than typing it from memory. - Connection errors / wrong host — double-check the base URL has the
/v1suffix for the OpenAI SDK path; the Anthropic-compatible URL (no/v1) is only for Anthropic-style clients and won't accept OpenAI SDK requests. - Request succeeded but no charge shows — failed requests aren't billed, so if a call errored out it correctly won't appear in Usage. Successful calls should show up within the same day's spend on the Overview page.
Before writing any of this into a larger app, the Connect page in the console lets you test your key directly and links out to the integration guides for other tools if you want to compare setups, for example the Cursor guide or Claude Code guide.
Pricing while you code
apillms bills per token, pay-as-you-go, and a credit purchase never expires. Claude and GPT prices per 1M tokens, compared to OpenRouter's list prices:
| Model | apillms input | apillms output | OpenRouter input/output |
|---|---|---|---|
| claude-sonnet-5 | $0.274 | $1.37 | $2 / $10 |
| claude-opus-5-5 | $0.639 | $3.19 | $4 / $20 |
| gpt-5.5 | $0.532 | $3.19 | $5 / $30 |
| gpt-6-astra | $1.06 | $5.32 | $10 / $50 |
| deepseek-v4-flash | $0.047 | $0.047 | $0.03 / $1.28 |
apillms is cheaper than OpenRouter's list prices for these models. Prompt caching is also on automatically for every request — repeated context (like a long system prompt in a loop) is billed at the lower cache-read rate, with no extra setup in your Python code. See the full live numbers at /compare or model-by-model detail at /pricing.
For a single chat-style message (roughly 1,000 input + 500 output tokens), the cost per call and per 1,000 calls looks like this:
| Model | One message | 1,000 messages |
|---|---|---|
| claude-sonnet-5 | $0.002 | $2.24 |
| deepseek-v4-flash | $0.0 | $0.14 |
| claude-opus-5-5 | $0.004 | $4.47 |
| gpt-5.5 | $0.004 | $4.26 |
| gpt-6-astra | $0.007 | $7.45 |
If your script is a long-running agent loop that reads a large cached context repeatedly rather than one-off chat messages, the economics change further — see prompt caching explained for the agent-turn numbers.
Checking usage after you run requests
Once your script has made a few calls, open the console to confirm what it cost. The Usage page breaks down spend by today, 7 days, or 30 days, lets you filter by model and status, and has an Export CSV button if you want to pull the data into a spreadsheet or your own billing dashboard. The Overview page also shows your current balance and spend for today at a glance, which is a quick way to sanity-check a script before leaving it running unattended — for example, a batch job calling the API in a loop overnight.
A small batch example
Here's a script that processes a list of prompts and prints a running total of calls made — useful as a starting point for a classification or summarization job:
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["APILLMS_API_KEY"],
base_url="https://apillms.com/v1",
)
prompts = [
"Summarize: Python is a dynamically typed language.",
"Summarize: HTTP is a stateless protocol.",
]
for i, prompt in enumerate(prompts, start=1):
resp = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[{"role": "user", "content": prompt}],
)
print(f"[{i}/{len(prompts)}]", resp.choices[0].message.content)
Since failed requests aren't billed, you can retry on exceptions without worrying about being charged twice for the same failed call. A simple retry wrapper looks like this:
import time
def ask_with_retry(model, prompt, retries=3):
for attempt in range(retries):
try:
resp = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}],
)
return resp.choices[0].message.content
except Exception as e:
if attempt == retries - 1:
raise
time.sleep(2 ** attempt)
Funding the account
New accounts start with 50 free credits, which is enough to run the examples above while you test the setup. When you need more, credit packs on the Billing page run from a $5 Starter pack (1,000 credits) up to a $100 Scale pack (23,000 credits), paid by PayPal or card; credits never expire, so there's no pressure to use them by a deadline. 1 credit equals $0.005, which is what the dollar figures above translate from.
Takeaway
Switching an existing OpenAI SDK project to apillms is two lines: change base_url to https://apillms.com/v1 and swap in your apillms key. From there, picking a model is just a string — the same request shape works for Claude, GPT, DeepSeek, Grok and Kimi — and you can watch exact spend per request on the Billing and Usage pages as you go. If you're weighing apillms against calling these models through OpenRouter instead, the price comparison is on /compare.
Try apillms
One API key for Claude, GPT, Grok, DeepSeek and Kimi. OpenAI- and Anthropic-compatible, prompt caching included, pay-as-you-go from $5 with PayPal or card. Credits never expire.
FAQ
Do I need the Anthropic SDK to call Claude models?
No. apillms exposes Claude models through the same OpenAI-compatible endpoint (https://apillms.com/v1), so the standard openai Python package works for both Claude and GPT models.
How many API keys do I get?
One. It's created automatically at sign-up, and on the API keys page you can only Show it or Roll it (rolling disables the old key) — there's no multi-key feature.
Does prompt caching require code changes?
No, caching is on automatically with per-user cache keys. Cache reads are simply billed at the lower cache-read price shown for each model.
How do I see what my Python script cost?
Open the Usage page in the console — it breaks down spend by today, 7, or 30 days, filterable by model and status, with a CSV export option. The Overview page also shows today's spend at a glance.