Trimming prompts helps a little. These levers help a lot, listed in the order of how much they usually save:
- Run the smallest model that still passes your own tests. Across OpenAI's GPT-5.6 and GPT-6 models, output prices range from $0.50 to $50.00 per million tokens.
- Cache the part of the prompt that never changes. On those models a cache read costs 10% of the input price, or 5% on gpt-6.1-sol and gpt-6.1-terra. Set it up wrong and caching costs you more, not less.
- Send anything that can wait to the Batch API, or mark it Flex. Both are half price.
- Spend fewer reasoning tokens. They're billed as output.
Aight's 10% extra on every recharge takes about 6% more off real-time traffic, but it doesn't combine with Batch or Flex. The details are below, with code for each lever and one workload costed step by step, from $10,200 a month to $137.25.
OpenAI API prices on 31 October 2026
Standard prices per million tokens, for prompts up to 272K input tokens, from OpenAI's pricing page:
| Model | Input | Cached input | Cache write | Output | Batch or Flex, in / out | On Aight |
|---|---|---|---|---|---|---|
| gpt-6-astra | $10.00 | $1.00 | $12.50 | $50.00 | $5.00 / $25.00 | Yes |
| gpt-5.6-sol | $4.00 | $0.40 | $5.00 | $20.00 | $2.00 / $10.00 | Yes |
| gpt-5.6-terra | $2.00 | $0.20 | $2.50 | $12.00 | $1.00 / $6.00 | Yes |
| gpt-6-sol | $2.00 | $0.20 | $2.50 | $10.00 | $1.00 / $5.00 | Yes |
| gpt-6.1-sol | $2.00 | $0.10 | $2.50 | $10.00 | $1.00 / $5.00 | Yes |
| gpt-6.1-terra | $1.00 | $0.05 | $1.25 | $5.00 | $0.50 / $2.50 | No |
| gpt-5.6-luna | $0.20 | $0.02 | $0.25 | $1.20 | $0.10 / $0.60 | Yes |
| gpt-6-luna | $0.10 | $0.01 | $0.125 | $0.50 | $0.05 / $0.25 | Yes |
How to read it:
- The cache write column is the default 30-minute write, at 1.25x the input price. A 12-hour write, available only in the Responses API, costs 2.5x.
- A prompt over 272K input tokens is charged 2x input and cache rates and 1.5x output, for the whole request.
- Batch and Flex prices apply to cached input and cache writes too, at half the Standard rate.
- gpt-5.6-sol's $4.00 / $20.00 is a promotion that runs "at least through November 21, 2026." OpenAI describes it as 20% off input and 33% off output, which puts the undiscounted price at $5.00 / $30.00.
The GPT-6 generation undercuts GPT-5.6 at every tier. gpt-6.1-sol costs half of gpt-5.6-sol, and gpt-6-luna half of gpt-5.6-luna. If you're still on a GPT-5.6 model, moving within the same tier is the easiest saving available. Check two things first: gpt-6.1-sol and gpt-6.1-terra need the Responses API for tool calling, and gpt-6-luna and gpt-6-sol accept function calls in Chat Completions only with reasoning_effort set to none.

Lever 1: the smallest model that passes your tests
Model choice moves the bill more than everything else combined. In the worked example below, the same month of requests costs $10,200 on gpt-6.1-sol and $510 on gpt-6-luna, before any other change. No caching setting comes close to a 20x difference.
The catch is in "passes your tests." A lower price doesn't help if the model gets 3% more answers wrong and a person has to fix them. So measure it:
- Pull 200 to 500 real requests from your logs, with answers you know are right. Outputs from your current model that someone has reviewed work fine.
- Run them through the candidate with the settings you'd use in production, including reasoning effort.
- Score the results the same way you score the current model, and compare cost per correct answer, not cost per token.
Try the candidates from the bottom up: gpt-6-luna first, then gpt-6.1-terra, then gpt-6.1-sol. You can also split traffic: send most requests to the small model and route only the hard cases, or the ones it marks as uncertain, to a larger one.
OpenAI's own session on measuring cost against quality before switching is worth the hour. It was published on 24 July, before the 30 July price cuts to Luna and Terra, so ignore the prices in it.
Lever 2: prompt caching, set up so it saves money
On GPT-5.6 and later, caching has a price on both sides. A cache read costs 0.1x the input price (0.05x on the 6.1 models), but a cache write costs 1.25x. A prefix must be at least 1,024 tokens to be cached.
Here's the part that catches people out. In the default implicit mode, OpenAI places the cache breakpoint at the end of the latest eligible message, which in a single-turn app is the user message: the part that changes on every request. So each request pays the 1.25x write rate on its whole prompt, including text no later request will ever match. OpenAI's caching guide points out that explicit mode avoids this, because it leaves the changing part after the last breakpoint, where it isn't charged a cache write. In the worst case, where every request writes its full prompt, the example workload below goes from $510 a month to $600 on gpt-6-luna, and from $10,200 to $12,000 on gpt-6.1-sol.
The fix is to mark where the reusable part ends and tell OpenAI to write only there:
import os
from openai import OpenAI
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
# Everything that is identical on every request: instructions, categories,
# labeled examples, output format. Needs at least 1,024 tokens to be cached.
with open("triage_prefix.md") as f:
STATIC_PREFIX = f.read()
def triage(ticket_text: str) -> str:
response = client.chat.completions.create(
model="gpt-6-luna",
reasoning_effort="low",
prompt_cache_options={"mode": "explicit"}, # write only at marked breakpoints
messages=[
{
"role": "developer",
"content": [{
"type": "text",
"text": STATIC_PREFIX,
"prompt_cache_breakpoint": {"mode": "explicit"}, # cache ends here
}],
},
{"role": "user", "content": ticket_text}, # changes every time, so it goes last
],
)
usage = response.usage
details = usage.prompt_tokens_details
print("input:", usage.prompt_tokens,
"| cache reads:", details.cached_tokens,
"| cache writes:", details.cache_write_tokens,
"| reasoning:", usage.completion_tokens_details.reasoning_tokens)
return response.choices[0].message.content
This uses openai-python 3.42.0, current on 31 October. If an older version rejects prompt_cache_options, pass it in extra_body instead. Watch the two counters. If cache_write_tokens is close to prompt_tokens on most requests, you're paying to write a cache that nobody reads.
To turn usage into dollars, count each kind of input token at its own rate:
PRICES = {"gpt-6-luna": (0.10, 0.01, 0.125, 0.50)} # input, cached, 30-min write, output per 1M
def request_cost(model, usage):
inp, cached, write, out = PRICES[model]
d = usage.prompt_tokens_details
reads = (d.cached_tokens or 0) if d else 0
writes = (d.cache_write_tokens or 0) if d else 0
plain = usage.prompt_tokens - reads - writes
return (plain * inp + reads * cached + writes * write
+ usage.completion_tokens * out) / 1_000_000
A few more rules from OpenAI's caching guide:
- Some settings are part of the cached prefix, so changing them between requests can break the match: the model, the tool list and its order, a structured output schema, reasoning effort and verbosity. Keep them fixed for requests that share a cache.
- Multi-turn chats and agents are different. Each turn extends the previous prompt, so implicit mode works well there. OpenAI reports a token hit rate above 90% for one agent deployment.
- A 30-minute entry stays valid for at least 30 minutes, and each read refreshes it. The 12-hour option (Responses API only) costs 2.5x to write, so it pays off only if, with 30-minute entries, you'd end up writing the same prefix more than twice in 12 hours.
- Cached tokens still count toward your tokens-per-minute rate limit.
Lever 3: the Batch API and Flex
The Batch API halves every price, including cached input and cache writes, in exchange for an answer that can take up to 24 hours. It also has its own rate-limit pool, so a large job doesn't eat into your live traffic's limits. One batch holds up to 50,000 requests and 200 MB, and each input file can use only one model.
import json
from openai import OpenAI
client = OpenAI()
def batch_line(ticket_id, ticket_text):
return {
"custom_id": ticket_id,
"method": "POST",
"url": "/v1/chat/completions",
"body": {
"model": "gpt-6-luna",
"reasoning_effort": "low",
"prompt_cache_options": {"mode": "explicit"},
"messages": [
{"role": "developer", "content": [{
"type": "text", "text": STATIC_PREFIX,
"prompt_cache_breakpoint": {"mode": "explicit"}}]},
{"role": "user", "content": ticket_text},
],
},
}
with open("tickets.jsonl", "w") as f:
for ticket_id, text in tickets:
f.write(json.dumps(batch_line(ticket_id, text)) + "\n")
upload = client.files.create(file=open("tickets.jsonl", "rb"), purpose="batch")
batch = client.batches.create(
input_file_id=upload.id,
endpoint="/v1/chat/completions",
completion_window="24h",
)
print(batch.id, batch.status) # "validating", then "in_progress"
Later, collect the results. They don't come back in input order, so match on custom_id:
batch = client.batches.retrieve(batch.id)
if batch.status == "completed":
for line in client.files.content(batch.output_file_id).text.splitlines():
row = json.loads(line)
answer = row["response"]["body"]["choices"][0]["message"]["content"]
save(row["custom_id"], answer)
Failed requests go to a separate file at error_file_id, and OpenAI deletes the output file 30 days after the batch completes.
Flex gives you the same half price on ordinary Chat Completions or Responses calls. You add service_tier="flex" and accept slower responses and an occasional 429 when OpenAI is short of capacity. You aren't charged for those 429s. It's in beta with a limited list of models, which currently includes all eight in the table above.
from openai import OpenAI, RateLimitError
client = OpenAI(timeout=900.0) # Flex is slower; the SDK default is 10 minutes
def classify(messages):
try:
return client.chat.completions.create(
model="gpt-6-luna", messages=messages, service_tier="flex")
except RateLimitError:
# No Flex capacity right now: wait and retry, or pay the Standard price
return client.chat.completions.create(model="gpt-6-luna", messages=messages)
Use Batch for big jobs on a schedule, like nightly classification, evals and backfills. Use Flex when the code is easier to write as normal calls and a few minutes of delay is fine.
Lever 4: fewer reasoning and output tokens
Reasoning tokens never appear in the reply, but they're billed as output. Most GPT-5.6 and GPT-6 models default to medium effort. For classification, extraction and short answers, start lower:
- Try
reasoning_effort="low", or"none"where the model allows it. gpt-6-luna, gpt-6-sol, gpt-6.1-terra and the GPT-5.6 models acceptnone. gpt-6.1-sol and gpt-6-astra don't. - Set
verbosity="low"when you want short visible answers. - Read
completion_tokens_details.reasoning_tokensbefore and after the change, and rerun your test set to check quality held. - If you cap output with
max_completion_tokens, remember that the cap includes reasoning. Set it too low and you pay for the reasoning and get an empty answer. OpenAI suggests leaving at least 25,000 tokens while you experiment.
A worked month: 600,000 support tickets
Here's one realistic workload, costed at OpenAI's list prices. A support team classifies and summarizes 600,000 tickets a month, about 20,000 a day. Each request sends a 5,000-token fixed prefix (instructions, category definitions, labeled examples, output schema) and a 1,000-token ticket, and gets back about 500 tokens, reasoning included. That's 3.6 billion input tokens and 300 million output tokens a month.
For caching, assume 90% of requests read the prefix from the cache and 10% write it. That's a 75% token hit rate, close to the roughly 70% OpenAI reports for a similar single-turn setup.
| Step | What changes | Input | Output | Month |
|---|---|---|---|---|
| 1 | gpt-6.1-sol, every input token at full price | $7,200.00 | $3,000.00 | $10,200.00 |
| 2 | Switch to gpt-6-luna | $360.00 | $150.00 | $510.00 |
| 3 | Cache the 5,000-token prefix | $124.50 | $150.00 | $274.50 |
| 4a | Batch API or Flex, on OpenAI directly | $62.25 | $75.00 | $137.25 |
| 4b | Or real time through Aight, with 10% extra | $116.58 | $140.45 | $257.03 |
Step 3's input line breaks down like this: 2.7 billion cached reads at $0.01 ($27.00), 300 million cache writes at $0.125 ($37.50), and 600 million ticket tokens at $0.10 ($60.00).

Two things stand out. First, the model switch saved $9,690, and everything after it saved less than $375. Second, the order you apply levers in changes the dollar amounts, not the end result. If your tests say you need gpt-6.1-sol, caching alone takes it from $10,200 to $5,220, because cache reads on that model cost 5% of input, and Batch halves that again to $2,610. Caching and Batch are worth far more in dollars on a large model than on a small one.
Where Aight fits
Aight adds 10% extra to every recharge. Outside India, a $100 recharge costs $103 with the 3% processing fee and adds $110 to your balance, so each dollar of list-price usage costs about $0.94. Aight lists gpt-6-luna, gpt-6-sol, gpt-6.1-sol, gpt-6-astra and the GPT-5.6 models at OpenAI's list prices, including cached input and cache writes, so the extra stacks with model choice and caching.
It doesn't stack with Batch or Flex. Aight documents three endpoints (chat completions, embeddings and the models list), so there's no Batch API, and its reference doesn't mention service_tier. gpt-6.1-terra isn't on Aight's models page either.
The honest summary: if the work can wait, OpenAI's Batch API at half price beats Aight's roughly 6% by a wide margin, so send that work to OpenAI directly. For traffic where a user is waiting and Batch or Flex don't fit, Aight takes about 6% off the list price. You also get a monthly cap and an allowed-model list per key, and one balance shared with Claude, Gemini and the rest.
One more check before you rely on caching through Aight. Its API reference documents only model, messages and stream in the request body. So send a few requests with the breakpoint code above and confirm that cached_tokens and cache_write_tokens come back as you expect.
Switching an existing OpenAI client is two lines:
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.getaight.ai/v1",
api_key=os.environ["AIGHT_API_KEY"],
)
For more on using one key across makers, see one API key for Claude, GPT, Gemini, DeepSeek and Grok. For capping what each key can spend, see OpenAI API key spending limits.
Settings that raise the bill quietly
- Fast mode costs 2x Standard. If a project's service tier is set to Fast in its settings, every request that doesn't name a tier runs at 2x. Check the
service_tierfield in your responses. Since 21 October, you can also restrict which tiers a project may use. - Regional processing (data residency) endpoints add 10% for models released on or after 5 March 2026. From 1 November 2026, FedRAMP endpoints add 10% too.
- A prompt over 272K input tokens doubles the input price and raises output by half, for the whole request. Trim or summarize long context before it crosses that line.
- The web search tool costs $10 per 1,000 calls, plus the search content tokens at the model's rates.
- Implicit caching on single-turn prompts, as covered in Lever 2.
Two smaller savings
If you already pay for ChatGPT Pro or Business, OpenAI has, since 28 October, included up to $500 a month of API usage at no charge. You claim it by linking an API organization you own. Pro tiers get $100, $200 or $500 a month, and Business workspaces get $20 or $100 per paid seat, capped at $500. It expires at the end of each billing cycle, and it doesn't cover Codex usage through API keys.
The only data-sharing discount on OpenAI's pricing page is for a fine-tuned o4-mini, which shut down with its base model on 23 October. There's nothing equivalent for current models. If you're still cleaning up after that shutdown, see what replaced each retired model.
The order to do it in
- Build a test set of a few hundred real requests and score your current model on it.
- Try gpt-6-luna, then gpt-6.1-terra, against the same set. Keep the smallest one that passes.
- Move the fixed part of every prompt to the front, add an explicit breakpoint, and watch
cache_write_tokens. - Move anything that can wait to the Batch API or Flex.
- Lower reasoning effort and check that quality held.
- Check the project's service tier, your regional endpoints and your longest prompts.
Then run the numbers again with your real token counts. For a fuller month-by-month estimate across providers, see what an LLM API costs per month.
Sources
- OpenAI, Pricing: Standard, Batch, Flex, Fast and Ultrafast prices, long-context rule, regional and FedRAMP uplift, the GPT-5.6 Sol promotion, fine-tuning data-sharing prices
- OpenAI model pages: gpt-6-astra, gpt-6.1-sol, gpt-6.1-terra, gpt-6-sol, gpt-6-luna, gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna
- OpenAI, Prompt caching: write and read rates, implicit and explicit modes, the shared-prefix gotcha, cache lifetimes, example hit rates
- OpenAI, Batch API, Flex processing and Fast mode
- OpenAI, Reasoning models and Create chat completion: reasoning effort, verbosity,
max_completion_tokens,prompt_cache_options, usage fields - OpenAI, Changelog: GPT-6.1 Terra release, price cuts, the Sol promotion, 12-hour caching, service tier controls
- OpenAI, Usage for ChatGPT subscribers and Deprecations
- openai-python 3.42.0 on PyPI
- Aight, Models and pricing, Quickstart, API reference and Refund policy
Checked on 31 October 2026. Prices are OpenAI list prices in US dollars per million tokens.