[BUG] Raw SDK calls with OAuth token bill to plan allowance instead of extra usage — blocklist gap
Summary
Direct API calls made with the public @anthropic-ai/sdk using an OAuth token from ~/.claude/.credentials.json are silently billed against the Max plan's included allowance instead of extra usage. The anthropic-ratelimit-unified-overage-utilization header stays at 0.0 despite multiple successful calls.
This appears to be because the third-party detection system is blocklist-based (flagging known tools like OpenClaw by signature) rather than allowlist-based (requiring valid cch attestation). Raw SDK calls fall into an unclassified gap — no valid attestation, but no third-party fingerprint either — and default to plan allowance.
I am reporting this because I want to be billed correctly. I am not attempting to bypass billing.
Environment
- Plan: Max x20
- SDK:
@anthropic-ai/sdkv0.86.0 (MIT license, public npm package) - Token: OAuth token (
sk-ant-oat01-*) from~/.claude/.credentials.json, obtained viaclaude auth login - Runtime: Bun 1.3.11 on AWS Ubuntu
- Use case: A personal daemon that makes lightweight API calls (Haiku classification, Sonnet learning extraction) alongside Claude Code CLI sessions
Reproduction
- Have a Max plan with extra usage enabled
- Install the public SDK:
npm install @anthropic-ai/sdk - Read the OAuth token from
~/.claude/.credentials.json - Make a direct API call:
import Anthropic from "@anthropic-ai/sdk";
import { readFileSync } from "fs";
import { join } from "path";
const creds = JSON.parse(readFileSync(join(process.env.HOME, ".claude", ".credentials.json"), "utf-8"));
const token = creds.claudeAiOauth.accessToken;
const client = new Anthropic({ apiKey: token });
const msg = await client.messages.create({
model: "claude-haiku-4-5-20251001",
max_tokens: 100,
messages: [{ role: "user", content: "Hello" }],
});
- Check the response headers:
anthropic-ratelimit-unified-overage-status: allowed
anthropic-ratelimit-unified-overage-utilization: 0.0 ← should be >0 for third-party
anthropic-ratelimit-unified-5h-utilization: 0.37 ← plan allowance increasing
anthropic-ratelimit-unified-7d-utilization: 0.78 ← plan allowance increasing
Outgoing request headers (what the SDK sends)
accept: application/json
anthropic-version: 2023-06-01
content-type: application/json
user-agent: Anthropic/JS 0.86.0
x-api-key: sk-ant-oat01-...
x-stainless-arch: x64
x-stainless-lang: js
x-stainless-os: Linux
x-stainless-package-version: 0.86.0
x-stainless-runtime: node
x-stainless-runtime-version: v24.3.0
No x-anthropic-billing-header, no cch attestation hash, no x-app header. These calls are not from Claude Code's binary — they're raw SDK calls from a third-party process.
Expected behavior
Per the April 4, 2026 policy change: third-party usage of OAuth tokens should bill against extra usage, not plan allowance. These raw SDK calls should be classified as third-party since they:
- Do not include the
cchattestation hash - Do not come from the Claude Code binary
- Have a generic SDK user-agent (
Anthropic/JS 0.86.0), notclaude-cli/...
Actual behavior
Calls succeed and are billed against the plan's included allowance (5h/7d utilization increases, overage stays at 0.0). The detection system appears to only flag known third-party tools by signature rather than requiring proof of first-party origin.
Request
Please provide one of:
- A documented header or parameter for honest third-party clients to self-declare (e.g.,
x-client-type: third-party) - Switch detection to allowlist-based — require valid
cchattestation for plan allowance, route everything else to extra usage - Guidance on the correct way to make programmatic API calls with an OAuth token that bills to the right lane
I'm happy to add whatever header or identifier is needed to ensure correct billing. The public SDK, the public API endpoint, and the OAuth token are all legitimately obtained — I just want the billing to be accurate.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗