The insufficient_quota error in the OpenAI API: causes and fixes
insufficient_quota arrives with a 429 status, but it's not a rate limit — it's money or a spend cap. Causes, exact codes, and handling in Python.
5 min · · errors · payments
The insufficient_quota OpenAI error arrives with status 429, and many people's first move is to retry, as with an ordinary rate limit. That won't help: the error is about money or a spend cap, not speed. Below: what insufficient_quota means, how to find the exact cause from the error code, how to handle it in Python, and what the same situation looks like in the Zukko gateway.
What insufficient_quota means in OpenAI
According to OpenAI's docs, errors related to billing and spend limits come with HTTP status 429. The general error type, error.type, can be insufficient_quota, and OpenAI advises checking the error.code field for the specific cause. The classic message text is "You exceeded your current quota, please check your plan and billing details".
The response looks roughly like this:
{
"error": {
"message": "You exceeded your current quota, please check your plan and billing details. ...",
"type": "insufficient_quota",
"code": "credit_balance_exhausted"
}
}The key point from the docs: retrying such requests won't restore access. You need to top up or change the limit first.
Why the error happens: codes from OpenAI's docs
error.code | Cause | How to fix |
|---|---|---|
credit_balance_exhausted | The organization's prepaid credits ran out | Add credits in billing settings |
organization_spend_limit_exceeded | The organization hit the monthly spend limit you set | Raise or remove the limit, or wait for the monthly reset |
project_spend_limit_exceeded | The project hit its own monthly limit; other projects keep working | Raise the limit in project settings or wait for the reset |
organization_usage_limit_exceeded | The organization reached its OpenAI-assigned usage limit | Request a higher limit or contact support |
A few more common everyday causes:
- A ChatGPT subscription doesn't include API credits. ChatGPT and the API are billed separately, so a paid ChatGPT Plus won't save you from insufficient_quota.
- The key is from the wrong project. The key belongs to a project or organization with no money, while you topped up a different one.
- A forgotten project limit. There's money in the account, but the project hit its own cap.
Telling these apart from a regular rate limit is easy: a rate limit clears after a pause (OpenAI advises waiting at least as long as the Retry-After header says). Billing errors have the codes from the table above, and a pause changes nothing.
How to fix insufficient_quota, step by step
- Look at
error.code, not just the status. It tells you right away whether credits ran out or a limit kicked in. - Check which key your code uses. An environment variable may be left over from an old project.
- Check the balance and limits of the organization and project in OpenAI's billing settings.
- Stop the retries. In the OpenAI Python SDK, a 429 becomes
openai.RateLimitError, and the SDK retries it twice by default. For billing errors those are wasted requests: catch them separately and stop the job with a clear message.
The Zukko equivalent: 402 and key limits
In the Zukko gateway there's one balance for all models, in dollars. The situations from the table look like this:
| OpenAI | Zukko | What to do |
|---|---|---|
429 credit_balance_exhausted | 402, code insufficient_balance | Top up from $1 |
429 project_spend_limit_exceeded | 429 key_daily_limit_reached or key_monthly_limit_reached | Raise the key's limit in the dashboard or wait for the reset |
| 429 rate limit | 429 without those codes — a limit at the model's provider | Retry with a pause |
Two differences from OpenAI worth reflecting in your code:
- Insufficient balance is a 402, not a 429. The gateway checks the balance before sending the request to the model. In the OpenAI Python SDK, a 402 arrives as a generic
openai.APIStatusError, and the SDK doesn't retry it — no wasted requests. - Limits are set per key, not per project. Each key has a daily and monthly dollar limit and a list of allowed models. A separate key per project gives you the same isolation as OpenAI's project spend limit. Details in the key limits docs.
From Russia you can top up via SBP or a Russian card (in rubles at the market rate at the time of payment), or with cryptocurrency. Step by step in the article on paying via SBP. You can check the remaining balance in advance via the API — see the balance reference.
How far $5 goes
Prices as of October 7, 2026. Take a request with 2,000 input and 500 output tokens; formula: (2000 × input + 500 × output) / 1,000,000.
| Model | Input / output, $ per 1M | One request | Requests per $5 |
|---|---|---|---|
deepseek-v4.1-flash | 0.013 / 0.038 | $0.000045 | about 111,111 |
gpt-6.1-sol | 0.27 / 1.32 | $0.0012 | about 4,166 |
claude-sonnet-5 | 0.4 / 2 | $0.0018 | about 2,777 |
Checking the second row: (2,000 × 0.27 + 500 × 1.32) / 1,000,000 = (540 + 660) / 1,000,000 = $0.0012; 5 / 0.0012 ≈ 4,166. This is an example calculation: prices change; for the current list and prices, call GET https://api.zukko.pro/v1/models or open the Models page in the dashboard.
Handling billing errors in Python
The code below works both with OpenAI directly and through Zukko: it catches billing errors by status, type, and code, and leaves transient errors to the SDK's built-in retries. Note that the OpenAI SDK retries a 429 twice on its own before handing the exception to your code; it doesn't retry a 402 from Zukko.
import openai
from openai import OpenAI
client = OpenAI(base_url="https://api.zukko.pro/v1", api_key="fetch_your_key")
BILLING_CODES = {
# OpenAI
"insufficient_quota",
"credit_balance_exhausted",
"organization_spend_limit_exceeded",
"project_spend_limit_exceeded",
"organization_usage_limit_exceeded",
# Zukko
"insufficient_balance",If you're moving a project from OpenAI, only the base_url, the key, and the model names change; the rest of the code stays the same. Details in the article on migrating from the OpenAI API; replacing the key step by step is covered in an OpenAI API key in Russia.
To try it, create a key in the dashboard, top up any convenient amount, and set a daily limit on the key.
FAQ
I topped up my OpenAI balance, but insufficient_quota is still there. Why?
Look at error.code. If it says project_spend_limit_exceeded or organization_spend_limit_exceeded, the problem is the spend limit, not credits. Also check that the key belongs to the project and organization you topped up.
Does a ChatGPT Plus subscription give access to the API?
No. ChatGPT and the API are billed separately; the API needs its own credits.
What does Zukko return when the balance runs out?
Status 402 with code insufficient_balance. The request doesn't reach the model, so retrying before you top up is pointless.
Why is it a 429 at OpenAI but a 402 at Zukko?
That's each service's own design. OpenAI groups billing errors with rate limits under 429 and tells them apart by code; Zukko puts insufficient balance under its own 402 status, while 429 means a key limit or a provider limit.
zukko
Pay 25×
less
for Claude Code & ChatGPT
One fetch_* key and base URL api.zukko.pro — for Cursor, Claude Code, Codex, and any SDK.
Related articles
- "Your card was declined" in OpenRouter: why a card gets rejectedWhy a card payment can be rejected on a foreign service, what you can check yourself and how to connect models when payment does not go through.
- OpenAI API Keys in the Open: Why You Should Not Use ThemWhere free keys on GitHub come from, why using them is dangerous for you and for the owner, and how to protect your own key from the same leak.
- GLM API Errors: Why the Request Fails and How to Fix ItA wrong model id, an overflowing 128K context, the key, the balance, limits: the typical causes of GLM API errors and a quick way to find yours.
- This organization has been disabled in the Claude API: What to DoAn Anthropic key suddenly answers "organization has been disabled". What the error is, what to check, and how to move the SDK and Claude Code to another provider.