Home → Help

429 from an API gateway means two different things

Read the body, not the status code. A 429 caused by an empty balance will never succeed on retry, no matter how long you back off. A 429 caused by upstream congestion usually clears in seconds.

What you are seeing

Why it happens

H

T

T

P

h

a

s

n

o

s

t

a

t

u

s

t

h

a

t

m

e

a

n

s

y

o

u

a

r

e

o

u

t

o

f

m

o

n

e

y

.

4

0

2

P

a

y

m

e

n

t

R

e

q

u

i

r

e

d

e

x

i

s

t

s

b

u

t

i

s

a

l

m

o

s

t

n

e

v

e

r

u

s

e

d

,

s

o

g

a

t

e

w

a

y

s

o

v

e

r

l

o

a

d

4

2

9

f

o

r

b

o

t

h

b

i

l

l

i

n

g

a

n

d

t

h

r

o

t

t

l

i

n

g

.

T

h

e

t

w

o

a

r

e

o

p

p

o

s

i

t

e

i

n

e

v

e

r

y

p

r

a

c

t

i

c

a

l

w

a

y

:

o

n

e

i

s

p

e

r

m

a

n

e

n

t

u

n

t

i

l

y

o

u

a

c

t

,

t

h

e

o

t

h

e

r

i

s

t

r

a

n

s

i

e

n

t

a

n

d

c

l

e

a

r

s

o

n

i

t

s

o

w

n

.

T

h

i

s

m

a

t

t

e

r

s

b

e

c

a

u

s

e

m

o

s

t

S

D

K

r

e

t

r

y

h

e

l

p

e

r

s

k

e

y

o

f

f

t

h

e

s

t

a

t

u

s

c

o

d

e

a

l

o

n

e

.

O

p

e

n

A

I

'

s

P

y

t

h

o

n

c

l

i

e

n

t

r

e

t

r

i

e

s

4

2

9

b

y

d

e

f

a

u

l

t

.

P

o

i

n

t

i

t

a

t

a

g

a

t

e

w

a

y

w

i

t

h

a

n

e

m

p

t

y

b

a

l

a

n

c

e

a

n

d

i

t

w

i

l

l

b

u

r

n

i

t

s

f

u

l

l

r

e

t

r

y

b

u

d

g

e

t

o

n

a

r

e

q

u

e

s

t

t

h

a

t

c

a

n

n

o

t

s

u

c

c

e

e

d

,

t

h

e

n

s

u

r

f

a

c

e

a

t

i

m

e

o

u

t

w

h

i

c

h

s

e

n

d

s

y

o

u

l

o

o

k

i

n

g

f

o

r

a

n

e

t

w

o

r

k

p

r

o

b

l

e

m

t

h

a

t

i

s

n

o

t

t

h

e

r

e

.

Confirm it is this

Make one request and look at the body rather than the status:

curl -s -o /tmp/r.json -w '%{http_code}\n' \
  'YOUR_BASE_URL/chat/completions' \
  -H 'Authorization: Bearer YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"model":"YOUR_MODEL","messages":[{"role":"user","content":"hi"}],"max_tokens":1}'

cat /tmp/r.json

A code or message mentioning quota, balance or credit means billing. Anything mentioning rate, busy or upstream means throttling. If the body is empty, check for a Retry-After header — its presence points at throttling.

How to fix it

  1. Branch on the body before retryingParse the JSON and treat billing 429s as fatal. Retrying them wastes your retry budget and hides the real cause behind a timeout.
  2. Honour Retry-After when it is thereThrottling responses often carry it. When absent, exponential backoff starting near one second is a reasonable default; retrying immediately usually makes congestion worse.
  3. Alert on balance separately from errorsAn empty balance is a business event, not an incident. Most gateways expose the balance through their own API or a dashboard — watch that number, and you will never meet this 429 in production.
  4. Do not raise concurrency to fix a throttling 429More parallel requests against a congested upstream produces more 429s, not more throughput. Lower concurrency and let backoff work.
On APICLAN the two are distinguishable without guessing. An empty balance returns {"code":"API_KEY_QUOTA_EXHAUSTED"}; upstream congestion returns {"error":{"type":"api_error","message":"Upstream rate limit exceeded, please retry later"}}. Your balance is on the dashboard, and top-ups apply immediately.

Related

Unexpected token '<' when calling an OpenAI-compatible API401 invalid API key — when the key looks right but still fails

Last checked 2026-09-09. Written from problems diagnosed on a live OpenAI-compatible gateway, not collected from other sites.