朝、前の晩に走らせたはずの集計スクリプトの出力が、空っぽでした。ログを開くと、末尾に一行だけ、英語のエラーが残っています。
Your credit balance is too low to access the Anthropic API.
Max プランに入っていて、毎月 API クレジットも付いているはずです。残高が足りないとは、にわかには信じられませんでした。胃のあたりが少し冷えたのを覚えています。
最初にお伝えしたいのは、この文言は「お金が尽きた」とは限らず、「いま呼んだものを支払える財布が空だった」という意味のことが多いという点です。ここからは、私自身が切り分けに使っている3つの勘定と、無人で走らせるスクリプトに入れておく検知コードを書き残します。
財布は1つではなく、少なくとも3つあります
Anthropic の公式ドキュメントとヘルプセンターを読み直すと、API の支払いは次の三つの仕組みが重なって動いていると分かります。
| 勘定 | 何が入っているか | 切れ方 |
|---|---|---|
| 含まれるクレジット | Max 5x は 100 ドル、Max 20x は 200 ドル、Team は席数に応じて最大 500 ドルまで(プールされます)。Console の Billing ページの Promotional credits に出ます | 請求サイクルの終わりに期限切れ。翌月への繰り越しはありません |
| 購入したクレジット | 自分で前払いした分。Billing ページの Credit balance に出ます | 購入から1年で期限切れ。返金はありません |
| 月間の支出上限 | 組織ごとの上限。クレジットで払った分も数えられます | 毎月1日にリセット |
使われる順番は、含まれるクレジットが先、購入分が後です。そしてオートリロードは購入分の残高だけを見て動きます。含まれるクレジットがどれだけ残っていても、購入分がしきい値を下回れば補充が走る、という設計です。支払い方法そのものが通らない場合は、「Claude Pro/Max の課金・支払いエラーを解決する方法:よくある問題と対処法まとめ」が入口になります。
切り分けの順番:まず「何を呼んだか」を見ます
私が最初に確認するのは、残高の数字ではなく、エラーを出した呼び出しの種類です。含まれるクレジットが使えるのは、Claude API、Managed Agents、Agent SDK、Console のプレイグラウンドです。Claude Code と、Claude アプリの追加利用分は対象外になっています。
つまり、含まれるクレジットしか持たない組織で Claude Code を動かすと、次のように表示されます。
Credit balance too low · Add funds: https://platform.claude.com/settings/billingAPI の残高があるのにこの表示が出る場合、原因は残高ではなく「対象外の呼び出しだった」ことにあります。ここで購入を急ぐ前に、次の順で見ていきます。
- Console の Billing ページを開き、Credit balance と Promotional credits のどちらが0か
- 失敗した呼び出しは API/Agent SDK か、Claude Code か
- Cost ページで、今月の支出が月間の上限に近づいていないか
三つ目は見落としやすい点です。上限に達したときの 400 の見分け方は、別の記事「上限に達したのに 400 が返ってきた — 自分で決めた利用上限・階層の月間上限・レート制限を見分ける」に詳しく書きました。残高エラーと上限エラーは、症状が似ていても直し方がまったく違います。
失敗から引いた線引き
以前の私は、夜間に走らせるスクリプトの失敗を「次の朝に気づけばよい」と考えていました。いま思えば、財布は一つだと思い込んでいたのかもしれません。実際には、含まれるクレジットは請求サイクルの終わりで消えるため、月末の夜にだけ残高が落ちるという形で、気づきにくい時間帯に切れます。
いまは、残高の監視はコンソールに任せず、呼び出す側のコードが「財布が空」を自分の言葉で報告するようにしています。次のラッパーは、残高エラーだけを別扱いにして、通知用の終了コードを返すものです。
import sys
import anthropic
client = anthropic.Anthropic() # ANTHROPIC_API_KEY は環境変数から読み込みます
LOW_BALANCE_MARK = "credit balance is too low"
def ask(prompt: str) -> str:
try:
msg = client.messages.create(
model="claude-sonnet-5",
max_tokens=512,
messages=[{"role": "user", "content": prompt}],
)
return msg.content[0].text
except anthropic.APIStatusError as e:
# 残高エラーはリトライしても直らないので、再試行せずに終了コード 3 で止める
if LOW_BALANCE_MARK in str(e).lower():
print("残高不足: Billing ページで Credit balance と Promotional credits を確認", file=sys.stderr)
sys.exit(3)
raise # それ以外のエラーは通常のエラー処理へ渡す
if __name__ == "__main__":
print(ask("今日の集計メモを3行でまとめてください。"))このコードで解決しているのは、「残高が空のときに、リトライを繰り返して夜じゅう失敗し続ける」という状況です。残高エラーは待っても直らないため、再試行の対象から外し、終了コード 3 という決まった目印で止めます。cron やスケジューラ側で、終了コードが 3 のときだけ通知を飛ばせば、他の失敗と混ざりません。
補充のしかたを、先に決めておきます
切れたあとに慌てて買うよりも、先に二つだけ決めておくほうが、はるかに気持ちが楽です。
- オートリロードを使うか:トリガーとなる残高(When credit balance reaches)と、戻す先の残高(Bring credit balance back up to)の二つを決めます。すでにしきい値を下回った状態で有効にすると、その場で補充が走る点に注意が必要です
- 誰が買えるか:クレジットの購入と支払い方法の変更には、Admin か Billing の役割が要ります。一人で運用している方でも、組織を作り直したときは自分の役割を見ておくと安心です
また、プロジェクトごとに使い過ぎを防ぎたい場合は、専用のワークスペースを作り、そのワークスペースに支出上限を設ける方法が公式に案内されています。同じ組織の API キーとワークスペースは、同じ残高から引かれるためです。キー側の失効を予定に変える考え方は、「APIキーに有効期限を付けると、失効は事故ではなく予定になる — 無人運用の鍵カレンダー設計」に書きました。
私の線引き
空になる前に気づく仕組みは、画面ではなくコードに置きます。 画面は見に行かなければ何も教えてくれませんが、終了コードは、見に行かなくても朝には届いています。
まずは、いま動かしているスクリプトのうち、夜間や無人で走るものを一つだけ選び、上のように残高エラーを別の終了コードで止めるところから始めていただければと思います。