dev.to2 de noviembre de 2026 AFECTA AL EXAMEN
APIPrecio

Per-customer budget caps for Anthropic API calls (with prompt caching priced right)

Price Claude calls from all four usage fields, reserve an estimate before the call so parallel requests can't blow through a cap, and fall back to a cheaper model near the limit.

---

title: Per-customer budget caps for Anthropic API calls (with prompt caching priced right)

published: true

description: Price Claude calls from all four usage fields, reserve an estimate before the call so parallel requests can't blow through a cap, and fall back to a cheaper model near the limit.

tags: anthropic, claude, typescript, redis

---

If your product calls Claude on behalf of your customers, one heavy account can spend a month's margin in a weekend. Anthropic's console limits protect your organization. They don't know which of *your* customers sent the traffic, so they can't stop one of them without stopping everyone.

This post builds a per-customer monthly cap for the Anthropic Messages API in TypeScript:

1. Price each call correctly, including prompt-cache reads **and writes**.

2. Check the budget **before** the call, in a way that holds up under concurrent requests.

3. Switch to a cheaper model near the cap, and refuse at the cap.

It uses `@anthropic-ai/sdk` and Redis (`ioredis`). The ideas carry over to any store with atomic operations.

1. Pricing a Messages API call

A Claude response's `usage` has four token counts that matter for cost:

| Field | What it is | Billed at |

|---|---|---|

| `input_tokens` | input after the last cache breakpoint | base input price |

| `cache_read_input_tokens` | prefix read from the prompt cache | 0.1x base for most models (0.05x for Opus 5.5 and Sonnet 5.5) |

| `cache_creation_input_tokens` | prefix written to the cache this call | 1.25x base (5-minute TTL), 2x (1-hour TTL) |

| `output_tokens` | generated tokens, including thinking | output price |

The trap is that `input_tokens` is **not** the total input. Total input is `input_tokens + cache_read_input_tokens + cache_creation_input_tokens`. If you only price `input_tokens`, a cached chat app looks almost free. And if you ignore cache writes, you under-count the first call of every conversation by 25% or more on its prefix.

When the 1-hour TTL is in play, `usage.cache_creation` splits writes into `ephemeral_5m_input_tokens` and `ephemeral_1h_input_tokens`, so you can price them separately.

ts
// prices.ts: USD per 1M tokens, standard tier.
// From https://docs.anthropic.com/en/docs/about-claude/pricing, read 2026-11-02. Check before relying on these.
type Price = { input: number; output: number; cacheRead: number; cacheWrite5m: number; cacheWrite1h: number };

export const PRICES: Record<string, Price> = {
  "claude-sonnet-5-5": { input: 2.0, output: 10.0, cacheRead: 0.1,  cacheWrite5m: 2.5,   cacheWrite1h: 4.0 },
  // Haiku 5.5 has a higher price for prompts over 100K tokens; this is the up-to-100K tier.
  "claude-haiku-5-5":  { input: 0.1, output: 0.5,  cacheRead: 0.01, cacheWrite5m: 0.125, cacheWrite1h: 0.2 },
};

export interface ClaudeUsage {
  input_tokens: number;
  output_tokens: number;
  cache_read_input_tokens?: number | null;
  cache_creation_input_tokens?: number | null;
  cache_creation?: { ephemeral_5m_input_tokens?: 
Leer artículo completo en dev.to