usage-tab 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +560 -0
- package/dist/index.cjs +2173 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +420 -0
- package/dist/index.d.ts +420 -0
- package/dist/index.js +2150 -0
- package/dist/index.js.map +1 -0
- package/package.json +73 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2173 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
AmbiguousAliasError: () => AmbiguousAliasError,
|
|
24
|
+
InvalidLookupDateError: () => InvalidLookupDateError,
|
|
25
|
+
InvalidRateError: () => InvalidRateError,
|
|
26
|
+
InvalidTokenCountError: () => InvalidTokenCountError,
|
|
27
|
+
InvalidUsageError: () => InvalidUsageError,
|
|
28
|
+
MODEL_REGISTRY: () => MODEL_REGISTRY,
|
|
29
|
+
NoPricingPeriodError: () => NoPricingPeriodError,
|
|
30
|
+
REGISTRY_VERSION: () => REGISTRY_VERSION,
|
|
31
|
+
UnknownModelError: () => UnknownModelError,
|
|
32
|
+
calculateCost: () => calculateCost,
|
|
33
|
+
createPriceCalculator: () => createPriceCalculator,
|
|
34
|
+
createPriceOverride: () => createPriceOverride,
|
|
35
|
+
normalizeAnthropicUsage: () => normalizeAnthropicUsage,
|
|
36
|
+
normalizeGoogleUsage: () => normalizeGoogleUsage,
|
|
37
|
+
normalizeOpenAICompatibleUsage: () => normalizeOpenAICompatibleUsage,
|
|
38
|
+
normalizeOpenAIUsage: () => normalizeOpenAIUsage,
|
|
39
|
+
resolveModel: () => resolveModel2
|
|
40
|
+
});
|
|
41
|
+
module.exports = __toCommonJS(index_exports);
|
|
42
|
+
|
|
43
|
+
// ../../internal/model-registry/src/errors.ts
|
|
44
|
+
function formatCandidates(candidates) {
|
|
45
|
+
return candidates.map((c) => `${c.provider}:${c.canonicalId}`).join(", ");
|
|
46
|
+
}
|
|
47
|
+
var UnknownModelError = class extends Error {
|
|
48
|
+
code = "UNKNOWN_MODEL";
|
|
49
|
+
requestedId;
|
|
50
|
+
provider;
|
|
51
|
+
/**
|
|
52
|
+
* Set only when the lookup was provider-qualified and `requestedId` exists
|
|
53
|
+
* under one or more *other* providers — the single most actionable fact
|
|
54
|
+
* for this failure. Sorted, deduplicated, and never the full registry:
|
|
55
|
+
* just the providers that actually carry this id.
|
|
56
|
+
*/
|
|
57
|
+
otherProviders;
|
|
58
|
+
constructor(requestedId, provider, otherProviders) {
|
|
59
|
+
super(
|
|
60
|
+
provider === void 0 ? `No model matches "${requestedId}". Pass a provider to qualify the lookup, register a custom override, or configure an explicit fallback.` : otherProviders !== void 0 && otherProviders.length > 0 ? `No model matches "${requestedId}" for provider "${provider}" \u2014 it exists under ${otherProviders.join(", ")} instead. Pass one of those as the provider, register a custom override, or configure an explicit fallback.` : `No model matches "${requestedId}" for provider "${provider}". Check the provider spelling, register a custom override, or configure an explicit fallback.`
|
|
61
|
+
);
|
|
62
|
+
this.name = "UnknownModelError";
|
|
63
|
+
this.requestedId = requestedId;
|
|
64
|
+
this.provider = provider;
|
|
65
|
+
if (otherProviders !== void 0 && otherProviders.length > 0) {
|
|
66
|
+
this.otherProviders = otherProviders;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
var AmbiguousAliasError = class extends Error {
|
|
71
|
+
code = "AMBIGUOUS_ALIAS";
|
|
72
|
+
requestedId;
|
|
73
|
+
candidates;
|
|
74
|
+
constructor(requestedId, candidates) {
|
|
75
|
+
super(
|
|
76
|
+
`"${requestedId}" matches more than one model (${formatCandidates(candidates)}). Pass a provider qualifier or a custom override to disambiguate \u2014 this id is never resolved by guessing.`
|
|
77
|
+
);
|
|
78
|
+
this.name = "AmbiguousAliasError";
|
|
79
|
+
this.requestedId = requestedId;
|
|
80
|
+
this.candidates = candidates;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
var AmbiguousPricingPeriodError = class extends Error {
|
|
84
|
+
code = "AMBIGUOUS_PRICING_PERIOD";
|
|
85
|
+
at;
|
|
86
|
+
effectiveFrom;
|
|
87
|
+
count;
|
|
88
|
+
canonicalId;
|
|
89
|
+
provider;
|
|
90
|
+
constructor(at, effectiveFrom, count, identity) {
|
|
91
|
+
const canonicalId = identity?.canonicalId;
|
|
92
|
+
const provider = identity?.provider;
|
|
93
|
+
const modelLabel = canonicalId !== void 0 && provider !== void 0 ? ` for model "${canonicalId}" (provider "${provider}")` : canonicalId !== void 0 ? ` for model "${canonicalId}"` : provider !== void 0 ? ` for provider "${provider}"` : "";
|
|
94
|
+
super(
|
|
95
|
+
`${String(count)} pricing periods share effectiveFrom "${effectiveFrom}"${modelLabel}, all covering the lookup date "${at}". Run this override through validateModelDescriptor (or give each period a distinct effectiveFrom, or remove the duplicate) \u2014 the registry never guesses between two prices for the same date.`
|
|
96
|
+
);
|
|
97
|
+
this.name = "AmbiguousPricingPeriodError";
|
|
98
|
+
this.at = at;
|
|
99
|
+
this.effectiveFrom = effectiveFrom;
|
|
100
|
+
this.count = count;
|
|
101
|
+
if (canonicalId !== void 0) {
|
|
102
|
+
this.canonicalId = canonicalId;
|
|
103
|
+
}
|
|
104
|
+
if (provider !== void 0) {
|
|
105
|
+
this.provider = provider;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
var InvalidLookupDateError = class extends Error {
|
|
110
|
+
code = "INVALID_LOOKUP_DATE";
|
|
111
|
+
value;
|
|
112
|
+
constructor(value) {
|
|
113
|
+
super(`"${value}" is not a valid date. Pass an ISO date string or a Date instance.`);
|
|
114
|
+
this.name = "InvalidLookupDateError";
|
|
115
|
+
this.value = value;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// ../../internal/model-registry/src/resolve.ts
|
|
120
|
+
function toCandidate(descriptor) {
|
|
121
|
+
return { provider: descriptor.provider, canonicalId: descriptor.canonicalId };
|
|
122
|
+
}
|
|
123
|
+
function matchExact(pool, id, provider) {
|
|
124
|
+
if (provider !== void 0) {
|
|
125
|
+
const canonical = pool.find((d) => d.provider === provider && d.canonicalId === id);
|
|
126
|
+
if (canonical !== void 0) return { unique: canonical };
|
|
127
|
+
const scoped = pool.filter((d) => d.provider === provider && d.aliases.includes(id));
|
|
128
|
+
if (scoped.length === 1) return { unique: scoped[0] };
|
|
129
|
+
if (scoped.length > 1) return { ambiguous: scoped };
|
|
130
|
+
return {};
|
|
131
|
+
}
|
|
132
|
+
const global = pool.filter((d) => d.canonicalId === id || d.aliases.includes(id));
|
|
133
|
+
if (global.length === 1) return { unique: global[0] };
|
|
134
|
+
if (global.length > 1) return { ambiguous: global };
|
|
135
|
+
return {};
|
|
136
|
+
}
|
|
137
|
+
function resolveModel(requestedId, registry, options = {}) {
|
|
138
|
+
const provider = options.provider;
|
|
139
|
+
if (options.overrides !== void 0 && options.overrides.length > 0) {
|
|
140
|
+
const overrideMatch = matchExact(options.overrides, requestedId, provider);
|
|
141
|
+
if (overrideMatch.ambiguous !== void 0) {
|
|
142
|
+
throw new AmbiguousAliasError(requestedId, overrideMatch.ambiguous.map(toCandidate));
|
|
143
|
+
}
|
|
144
|
+
if (overrideMatch.unique !== void 0) {
|
|
145
|
+
return {
|
|
146
|
+
descriptor: overrideMatch.unique,
|
|
147
|
+
matchedBy: "override",
|
|
148
|
+
requestedId,
|
|
149
|
+
requestedProvider: provider
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (provider !== void 0) {
|
|
154
|
+
const canonical = registry.find(
|
|
155
|
+
(d) => d.provider === provider && d.canonicalId === requestedId
|
|
156
|
+
);
|
|
157
|
+
if (canonical !== void 0) {
|
|
158
|
+
return {
|
|
159
|
+
descriptor: canonical,
|
|
160
|
+
matchedBy: "canonical-qualified",
|
|
161
|
+
requestedId,
|
|
162
|
+
requestedProvider: provider
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
const scoped = registry.filter(
|
|
166
|
+
(d) => d.provider === provider && d.aliases.includes(requestedId)
|
|
167
|
+
);
|
|
168
|
+
if (scoped.length === 1) {
|
|
169
|
+
const descriptor = scoped[0];
|
|
170
|
+
if (descriptor !== void 0) {
|
|
171
|
+
return { descriptor, matchedBy: "alias-scoped", requestedId, requestedProvider: provider };
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (scoped.length > 1) {
|
|
175
|
+
throw new AmbiguousAliasError(requestedId, scoped.map(toCandidate));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (provider === void 0) {
|
|
179
|
+
const global = registry.filter(
|
|
180
|
+
(d) => d.canonicalId === requestedId || d.aliases.includes(requestedId)
|
|
181
|
+
);
|
|
182
|
+
if (global.length === 1) {
|
|
183
|
+
const descriptor = global[0];
|
|
184
|
+
if (descriptor !== void 0) {
|
|
185
|
+
return { descriptor, matchedBy: "alias-global", requestedId, requestedProvider: provider };
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (global.length > 1) {
|
|
189
|
+
throw new AmbiguousAliasError(requestedId, global.map(toCandidate));
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (options.fallback !== void 0) {
|
|
193
|
+
const fallback = registry.find((d) => d.canonicalId === options.fallback);
|
|
194
|
+
if (fallback !== void 0) {
|
|
195
|
+
return {
|
|
196
|
+
descriptor: fallback,
|
|
197
|
+
matchedBy: "fallback",
|
|
198
|
+
requestedId,
|
|
199
|
+
requestedProvider: provider
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (provider !== void 0) {
|
|
204
|
+
const otherProviders = [
|
|
205
|
+
...new Set(
|
|
206
|
+
registry.filter((d) => d.canonicalId === requestedId || d.aliases.includes(requestedId)).map((d) => d.provider)
|
|
207
|
+
)
|
|
208
|
+
].sort();
|
|
209
|
+
if (otherProviders.length > 0) {
|
|
210
|
+
throw new UnknownModelError(requestedId, provider, otherProviders);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
throw new UnknownModelError(requestedId, provider);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// ../../internal/model-registry/src/pricing-period.ts
|
|
217
|
+
function toTimestamp(value) {
|
|
218
|
+
const ms = value instanceof Date ? value.getTime() : Date.parse(value);
|
|
219
|
+
if (Number.isNaN(ms)) {
|
|
220
|
+
throw new InvalidLookupDateError(value instanceof Date ? value.toISOString() : value);
|
|
221
|
+
}
|
|
222
|
+
return ms;
|
|
223
|
+
}
|
|
224
|
+
function selectPricingPeriod(periods, at, identity) {
|
|
225
|
+
const atMs = toTimestamp(at);
|
|
226
|
+
let best;
|
|
227
|
+
let bestFromMs = Number.NEGATIVE_INFINITY;
|
|
228
|
+
let tieCount = 0;
|
|
229
|
+
for (const period of periods) {
|
|
230
|
+
const fromMs = toTimestamp(period.effectiveFrom);
|
|
231
|
+
if (fromMs > atMs) continue;
|
|
232
|
+
if (period.effectiveTo !== void 0 && atMs >= toTimestamp(period.effectiveTo)) continue;
|
|
233
|
+
if (fromMs > bestFromMs) {
|
|
234
|
+
best = period;
|
|
235
|
+
bestFromMs = fromMs;
|
|
236
|
+
tieCount = 1;
|
|
237
|
+
} else if (fromMs === bestFromMs) {
|
|
238
|
+
tieCount += 1;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
if (best !== void 0 && tieCount > 1) {
|
|
242
|
+
throw new AmbiguousPricingPeriodError(
|
|
243
|
+
at instanceof Date ? at.toISOString() : at,
|
|
244
|
+
best.effectiveFrom,
|
|
245
|
+
tieCount,
|
|
246
|
+
identity
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
return best;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// ../../internal/model-registry/src/generated/registry.ts
|
|
253
|
+
var REGISTRY_VERSION = "registry-5af85ce1a47be918";
|
|
254
|
+
var MODEL_REGISTRY = [
|
|
255
|
+
{
|
|
256
|
+
canonicalId: "claude-fable-5",
|
|
257
|
+
provider: "anthropic",
|
|
258
|
+
aliases: [],
|
|
259
|
+
family: "fable",
|
|
260
|
+
contextWindow: 1e6,
|
|
261
|
+
pricing: [
|
|
262
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "10.00", "output": "50.00", "cachedInput": "1.00", "cacheWrite": "12.50", "batchMultiplier": "0.5", "sourceUrl": "https://platform.claude.com/docs/en/about-claude/models/overview", "observedAt": "2026-08-05", "notes": ["Anthropic did not publish an explicit effective date for this rate as observed; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "cacheWrite reflects the 5-minute cache TTL (1.25x input). The 1-hour TTL write multiplier is 2x input and is not separately modeled by this schema (a single cacheWrite field)."] }
|
|
263
|
+
],
|
|
264
|
+
source: { "url": "https://platform.claude.com/docs/en/about-claude/models/overview", "observedAt": "2026-08-05" }
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
canonicalId: "claude-haiku-4-5-20251001",
|
|
268
|
+
provider: "anthropic",
|
|
269
|
+
aliases: ["claude-haiku-4-5"],
|
|
270
|
+
family: "haiku",
|
|
271
|
+
contextWindow: 2e5,
|
|
272
|
+
pricing: [
|
|
273
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.00", "output": "5.00", "cachedInput": "0.10", "cacheWrite": "1.25", "batchMultiplier": "0.5", "sourceUrl": "https://platform.claude.com/docs/en/about-claude/models/overview", "observedAt": "2026-08-05", "notes": ["Anthropic did not publish an explicit effective date for this rate as observed; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "cacheWrite reflects the 5-minute cache TTL (1.25x input). The 1-hour TTL write multiplier is 2x input and is not separately modeled by this schema (a single cacheWrite field)."] }
|
|
274
|
+
],
|
|
275
|
+
source: { "url": "https://platform.claude.com/docs/en/about-claude/models/overview", "observedAt": "2026-08-05", "notes": ['canonicalId is the full dated snapshot id; "claude-haiku-4-5" is the short alias Anthropic documents alongside it \u2014 a genuine alias/canonical-ID resolution case.'] }
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
canonicalId: "claude-opus-4-6",
|
|
279
|
+
provider: "anthropic",
|
|
280
|
+
aliases: [],
|
|
281
|
+
family: "opus",
|
|
282
|
+
contextWindow: 1e6,
|
|
283
|
+
pricing: [
|
|
284
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "5.00", "output": "25.00", "cachedInput": "0.50", "cacheWrite": "6.25", "batchMultiplier": "0.5", "sourceUrl": "https://platform.claude.com/docs/en/about-claude/models/overview", "observedAt": "2026-08-05", "notes": ["Anthropic did not publish an explicit effective date for this rate as observed; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "cacheWrite reflects the 5-minute cache TTL (1.25x input). The 1-hour TTL write multiplier is 2x input and is not separately modeled by this schema (a single cacheWrite field)."] }
|
|
285
|
+
],
|
|
286
|
+
source: { "url": "https://platform.claude.com/docs/en/about-claude/models/overview", "observedAt": "2026-08-05" }
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
canonicalId: "claude-opus-4-7",
|
|
290
|
+
provider: "anthropic",
|
|
291
|
+
aliases: [],
|
|
292
|
+
family: "opus",
|
|
293
|
+
contextWindow: 1e6,
|
|
294
|
+
pricing: [
|
|
295
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "5.00", "output": "25.00", "cachedInput": "0.50", "cacheWrite": "6.25", "batchMultiplier": "0.5", "sourceUrl": "https://platform.claude.com/docs/en/about-claude/models/overview", "observedAt": "2026-08-05", "notes": ["Anthropic did not publish an explicit effective date for this rate as observed; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "cacheWrite reflects the 5-minute cache TTL (1.25x input). The 1-hour TTL write multiplier is 2x input and is not separately modeled by this schema (a single cacheWrite field)."] }
|
|
296
|
+
],
|
|
297
|
+
source: { "url": "https://platform.claude.com/docs/en/about-claude/models/overview", "observedAt": "2026-08-05" }
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
canonicalId: "claude-opus-4-8",
|
|
301
|
+
provider: "anthropic",
|
|
302
|
+
aliases: [],
|
|
303
|
+
family: "opus",
|
|
304
|
+
contextWindow: 1e6,
|
|
305
|
+
pricing: [
|
|
306
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "5.00", "output": "25.00", "cachedInput": "0.50", "cacheWrite": "6.25", "batchMultiplier": "0.5", "sourceUrl": "https://platform.claude.com/docs/en/about-claude/models/overview", "observedAt": "2026-08-05", "notes": ["Anthropic did not publish an explicit effective date for this rate as observed; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "cacheWrite reflects the 5-minute cache TTL (1.25x input). The 1-hour TTL write multiplier is 2x input and is not separately modeled by this schema (a single cacheWrite field)."] }
|
|
307
|
+
],
|
|
308
|
+
source: { "url": "https://platform.claude.com/docs/en/about-claude/models/overview", "observedAt": "2026-08-05" }
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
canonicalId: "claude-opus-5",
|
|
312
|
+
provider: "anthropic",
|
|
313
|
+
aliases: [],
|
|
314
|
+
family: "opus",
|
|
315
|
+
contextWindow: 1e6,
|
|
316
|
+
pricing: [
|
|
317
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "5.00", "output": "25.00", "cachedInput": "0.50", "cacheWrite": "6.25", "batchMultiplier": "0.5", "sourceUrl": "https://platform.claude.com/docs/en/about-claude/models/overview", "observedAt": "2026-08-05", "notes": ["Anthropic did not publish an explicit effective date for this rate as observed; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "cacheWrite reflects the 5-minute cache TTL (1.25x input). The 1-hour TTL write multiplier is 2x input and is not separately modeled by this schema (a single cacheWrite field)."] }
|
|
318
|
+
],
|
|
319
|
+
source: { "url": "https://platform.claude.com/docs/en/about-claude/models/overview", "observedAt": "2026-08-05" }
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
canonicalId: "claude-sonnet-4-6",
|
|
323
|
+
provider: "anthropic",
|
|
324
|
+
aliases: [],
|
|
325
|
+
family: "sonnet",
|
|
326
|
+
contextWindow: 1e6,
|
|
327
|
+
pricing: [
|
|
328
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "3.00", "output": "15.00", "cachedInput": "0.30", "cacheWrite": "3.75", "batchMultiplier": "0.5", "sourceUrl": "https://platform.claude.com/docs/en/about-claude/models/overview", "observedAt": "2026-08-05", "notes": ["Anthropic did not publish an explicit effective date for this rate as observed; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "cacheWrite reflects the 5-minute cache TTL (1.25x input). The 1-hour TTL write multiplier is 2x input and is not separately modeled by this schema (a single cacheWrite field)."] }
|
|
329
|
+
],
|
|
330
|
+
source: { "url": "https://platform.claude.com/docs/en/about-claude/models/overview", "observedAt": "2026-08-05" }
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
canonicalId: "claude-sonnet-5",
|
|
334
|
+
provider: "anthropic",
|
|
335
|
+
aliases: [],
|
|
336
|
+
family: "sonnet",
|
|
337
|
+
contextWindow: 1e6,
|
|
338
|
+
pricing: [
|
|
339
|
+
{ "effectiveFrom": "2026-01-01", "effectiveTo": "2026-09-01", "currency": "USD", "unit": "per-million-tokens", "input": "2.00", "output": "10.00", "cachedInput": "0.20", "cacheWrite": "2.50", "batchMultiplier": "0.5", "sourceUrl": "https://platform.claude.com/docs/en/about-claude/models/overview", "observedAt": "2026-08-05", "notes": ["Introductory rate, confirmed active through 2026-08-31. This is the golden fixture for effective-date selection (see test/pricing-period.test.ts): a lookup dated 2026-08-15 must select this period.", "effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true introductory-rate start date; only the 2026-08-31 end date was observed.", "cacheWrite reflects the 5-minute cache TTL (1.25x input). The 1-hour TTL write multiplier is 2x input and is not separately modeled by this schema (a single cacheWrite field)."] },
|
|
340
|
+
{ "effectiveFrom": "2026-09-01", "currency": "USD", "unit": "per-million-tokens", "input": "3.00", "output": "15.00", "cachedInput": "0.30", "cacheWrite": "3.75", "batchMultiplier": "0.5", "sourceUrl": "https://platform.claude.com/docs/en/about-claude/models/overview", "observedAt": "2026-08-05", "notes": ["Standard rate, effective 2026-09-01 immediately after the introductory-rate window (through 2026-08-31) ends. A lookup dated 2026-09-15 must select this period.", "cacheWrite reflects the 5-minute cache TTL (1.25x input). The 1-hour TTL write multiplier is 2x input and is not separately modeled by this schema (a single cacheWrite field)."] }
|
|
341
|
+
],
|
|
342
|
+
source: { "url": "https://platform.claude.com/docs/en/about-claude/models/overview", "observedAt": "2026-08-05", "notes": ["Two pricing periods on purpose: an introductory rate ($2.00/$10.00) through 2026-08-31, then the standard rate ($3.00/$15.00) from 2026-09-01."] }
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
canonicalId: "amazon-nova-lite",
|
|
346
|
+
provider: "aws-bedrock",
|
|
347
|
+
aliases: [],
|
|
348
|
+
family: "amazon-nova",
|
|
349
|
+
pricing: [
|
|
350
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.60", "output": "2.40", "sourceUrl": "https://aws.amazon.com/bedrock/pricing/", "observedAt": "2026-08-05", "notes": ["No explicit effective date published for this rate; effectiveFrom is set conservatively to 2026-01-01.", "Same cross-region/in-region caveat as amazon-nova-micro."] }
|
|
351
|
+
],
|
|
352
|
+
source: { "url": "https://aws.amazon.com/bedrock/pricing/", "observedAt": "2026-08-05" }
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
canonicalId: "amazon-nova-micro",
|
|
356
|
+
provider: "aws-bedrock",
|
|
357
|
+
aliases: [],
|
|
358
|
+
family: "amazon-nova",
|
|
359
|
+
pricing: [
|
|
360
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.30", "output": "1.20", "sourceUrl": "https://aws.amazon.com/bedrock/pricing/", "observedAt": "2026-08-05", "notes": [`AWS's own first-party model (Amazon publishes both Bedrock and Nova), so "aws-bedrock" is effectively first-party pricing here, unlike the resold third-party models in this file.`, "No explicit effective date published for this specific rate (unlike the Claude 3.5 Sonnet rows above, which do carry a stated Dec 2025 date); effectiveFrom is set conservatively to 2026-01-01.", `Bedrock's pricing page also distinguishes "Global cross-region" vs "in-region" inference pricing for Nova; this rate was not confirmed to be specifically the in-region (vs cross-region) figure \u2014 treat as the headline on-demand rate observed.`] }
|
|
361
|
+
],
|
|
362
|
+
source: { "url": "https://aws.amazon.com/bedrock/pricing/", "observedAt": "2026-08-05" }
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
canonicalId: "amazon-nova-pro",
|
|
366
|
+
provider: "aws-bedrock",
|
|
367
|
+
aliases: [],
|
|
368
|
+
family: "amazon-nova",
|
|
369
|
+
pricing: [
|
|
370
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.20", "output": "4.80", "sourceUrl": "https://aws.amazon.com/bedrock/pricing/", "observedAt": "2026-08-05", "notes": ["No explicit effective date published for this rate; effectiveFrom is set conservatively to 2026-01-01.", "Same cross-region/in-region caveat as amazon-nova-micro."] }
|
|
371
|
+
],
|
|
372
|
+
source: { "url": "https://aws.amazon.com/bedrock/pricing/", "observedAt": "2026-08-05" }
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
canonicalId: "claude-3.5-sonnet",
|
|
376
|
+
provider: "aws-bedrock",
|
|
377
|
+
aliases: [],
|
|
378
|
+
family: "anthropic-claude",
|
|
379
|
+
pricing: [
|
|
380
|
+
{ "effectiveFrom": "2025-12-01", "currency": "USD", "unit": "per-million-tokens", "input": "6.00", "output": "30.00", "batchMultiplier": "0.5", "sourceUrl": "https://aws.amazon.com/bedrock/pricing/", "observedAt": "2026-08-05", "notes": [`AWS Bedrock's own rate card for this Anthropic model, explicitly labeled "Effective 1 Dec 2025" on the pricing page \u2014 a real, confirmed effective date, not the conservative default used elsewhere in this file.`, "Batch: $3.00/$15.00 (confirmed 0.5x standard) as observed on the same page.", "This is Bedrock's own price for an older Claude generation (3.5 Sonnet), not the current claude-sonnet-5 model in anthropic.json \u2014 no comparable first-party entry exists in this registry for the same model, so no direct parity claim is possible or intended. Bedrock and Azure resell other vendors' models under their own rate cards, so a first-party price is never a safe proxy for theirs."] }
|
|
381
|
+
],
|
|
382
|
+
source: { "url": "https://aws.amazon.com/bedrock/pricing/", "observedAt": "2026-08-05" }
|
|
383
|
+
},
|
|
384
|
+
{
|
|
385
|
+
canonicalId: "claude-3.5-sonnet-v2",
|
|
386
|
+
provider: "aws-bedrock",
|
|
387
|
+
aliases: [],
|
|
388
|
+
family: "anthropic-claude",
|
|
389
|
+
pricing: [
|
|
390
|
+
{ "effectiveFrom": "2025-12-01", "currency": "USD", "unit": "per-million-tokens", "input": "6.00", "output": "30.00", "cachedInput": "0.60", "cacheWrite": "7.50", "batchMultiplier": "0.5", "sourceUrl": "https://aws.amazon.com/bedrock/pricing/", "observedAt": "2026-08-05", "notes": [`AWS Bedrock's own rate card, explicitly labeled "Effective 1 Dec 2025" on the pricing page.`, "Batch: $3.00/$15.00 (confirmed 0.5x standard) as observed on the same page.", "Bedrock's own price for an older Claude generation; not comparable to any first-party entry currently in anthropic.json (which covers 4.x/5.x models only)."] }
|
|
391
|
+
],
|
|
392
|
+
source: { "url": "https://aws.amazon.com/bedrock/pricing/", "observedAt": "2026-08-05" }
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
canonicalId: "gemma-4-31b",
|
|
396
|
+
provider: "aws-bedrock",
|
|
397
|
+
aliases: [],
|
|
398
|
+
family: "google-gemma",
|
|
399
|
+
pricing: [
|
|
400
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.14", "output": "0.40", "sourceUrl": "https://aws.amazon.com/bedrock/pricing/", "observedAt": "2026-08-05", "notes": ["No explicit effective date published for this rate; effectiveFrom is set conservatively to 2026-01-01.", 'Cross-provider alias/canonicalId collision (allowed, not an error): Together AI also lists "Gemma 4 31B" (together.json: gemma-4-31b) at a different, higher rate ($0.39/$0.97 as observed) \u2014 same underlying Google open-weight model, independently priced by each reseller; do not assume parity.'] }
|
|
401
|
+
],
|
|
402
|
+
source: { "url": "https://aws.amazon.com/bedrock/pricing/", "observedAt": "2026-08-05" }
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
canonicalId: "mistral-large-3",
|
|
406
|
+
provider: "aws-bedrock",
|
|
407
|
+
aliases: [],
|
|
408
|
+
family: "mistral",
|
|
409
|
+
pricing: [
|
|
410
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.50", "output": "1.50", "sourceUrl": "https://aws.amazon.com/bedrock/pricing/", "observedAt": "2026-08-05", "notes": ["No explicit effective date published for this rate; effectiveFrom is set conservatively to 2026-01-01.", "Cross-provider alias/canonicalId collision (allowed, not an error): Mistral's own first-party pricing (mistral.json: mistral-large-3) shows the identical $0.50/$1.50 figure as independently observed \u2014 coincidental agreement between the two independently fetched sources, not assumed; both were confirmed directly."] }
|
|
411
|
+
],
|
|
412
|
+
source: { "url": "https://aws.amazon.com/bedrock/pricing/", "observedAt": "2026-08-05" }
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
canonicalId: "nemotron-nano-2",
|
|
416
|
+
provider: "aws-bedrock",
|
|
417
|
+
aliases: [],
|
|
418
|
+
family: "nvidia-nemotron",
|
|
419
|
+
pricing: [
|
|
420
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.06", "output": "0.23", "sourceUrl": "https://aws.amazon.com/bedrock/pricing/", "observedAt": "2026-08-05", "notes": ["No explicit effective date published for this rate; effectiveFrom is set conservatively to 2026-01-01."] }
|
|
421
|
+
],
|
|
422
|
+
source: { "url": "https://aws.amazon.com/bedrock/pricing/", "observedAt": "2026-08-05" }
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
canonicalId: "gpt-3.5-turbo",
|
|
426
|
+
provider: "azure-openai",
|
|
427
|
+
aliases: [],
|
|
428
|
+
family: "gpt-3.5",
|
|
429
|
+
pricing: [
|
|
430
|
+
{ "effectiveFrom": "2025-03-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.50", "output": "1.50", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["Azure's Retail Prices API quotes this meter per 1K tokens; converted to per-million-tokens by shifting the decimal point 3 places as exact string manipulation (never float multiplication).", "The Retail Prices API returned exactly one row for this legacy SKU (a single primary-meter-region price, no per-region breakdown) rather than the ~24-28 region-duplicated rows seen for actively-priced SKUs \u2014 a single global list price, which is consistent with (not contradictory to) Global-deployment region-independence, but could not be cross-region spot-checked the way other entries were.", "No Batch API meter was found for this model/SKU in the Retail Prices API response; batchMultiplier is intentionally omitted rather than assumed.", `Matches OpenAI's own first-party rate for "gpt-3.5-turbo" in openai.json exactly as observed ($0.50/$1.50) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "gpt-3.5-turbo" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
431
|
+
],
|
|
432
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
canonicalId: "gpt-4",
|
|
436
|
+
provider: "azure-openai",
|
|
437
|
+
aliases: [],
|
|
438
|
+
family: "gpt-4",
|
|
439
|
+
pricing: [
|
|
440
|
+
{ "effectiveFrom": "2025-03-01", "currency": "USD", "unit": "per-million-tokens", "input": "30.00", "output": "60.00", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["Azure's Retail Prices API quotes this meter per 1K tokens; converted to per-million-tokens by shifting the decimal point 3 places as exact string manipulation (never float multiplication).", "The Retail Prices API returned exactly one row for this legacy SKU (a single primary-meter-region price, no per-region breakdown) rather than the ~24-28 region-duplicated rows seen for actively-priced SKUs \u2014 a single global list price, which is consistent with (not contradictory to) Global-deployment region-independence, but could not be cross-region spot-checked the way other entries were.", "No Batch API meter was found for this model/SKU in the Retail Prices API response; batchMultiplier is intentionally omitted rather than assumed.", `No comparable first-party entry exists in openai.json's 2026-08-05 snapshot for "gpt-4" (it is either a legacy/superseded model no longer on OpenAI's current pricing page, or a variant OpenAI does not sell directly) \u2014 Azure's own resale rate is recorded as observed with no parity claim possible or intended.`] }
|
|
441
|
+
],
|
|
442
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
443
|
+
},
|
|
444
|
+
{
|
|
445
|
+
canonicalId: "gpt-4-32k",
|
|
446
|
+
provider: "azure-openai",
|
|
447
|
+
aliases: [],
|
|
448
|
+
family: "gpt-4",
|
|
449
|
+
pricing: [
|
|
450
|
+
{ "effectiveFrom": "2025-03-01", "currency": "USD", "unit": "per-million-tokens", "input": "60.00", "output": "120.00", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["Azure's Retail Prices API quotes this meter per 1K tokens; converted to per-million-tokens by shifting the decimal point 3 places as exact string manipulation (never float multiplication).", "The Retail Prices API returned exactly one row for this legacy SKU (a single primary-meter-region price, no per-region breakdown) rather than the ~24-28 region-duplicated rows seen for actively-priced SKUs \u2014 a single global list price, which is consistent with (not contradictory to) Global-deployment region-independence, but could not be cross-region spot-checked the way other entries were.", "No Batch API meter was found for this model/SKU in the Retail Prices API response; batchMultiplier is intentionally omitted rather than assumed.", `No comparable first-party entry exists in openai.json's 2026-08-05 snapshot for "gpt-4-32k" (it is either a legacy/superseded model no longer on OpenAI's current pricing page, or a variant OpenAI does not sell directly) \u2014 Azure's own resale rate is recorded as observed with no parity claim possible or intended.`] }
|
|
451
|
+
],
|
|
452
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
canonicalId: "gpt-4-turbo",
|
|
456
|
+
provider: "azure-openai",
|
|
457
|
+
aliases: [],
|
|
458
|
+
family: "gpt-4-turbo",
|
|
459
|
+
pricing: [
|
|
460
|
+
{ "effectiveFrom": "2024-06-01", "currency": "USD", "unit": "per-million-tokens", "input": "10.00", "output": "30.00", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["Azure's Retail Prices API quotes this meter per 1K tokens; converted to per-million-tokens by shifting the decimal point 3 places as exact string manipulation (never float multiplication).", "retailPrice confirmed identical across all 23 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "No Batch API meter was found for this model/SKU in the Retail Prices API response; batchMultiplier is intentionally omitted rather than assumed.", `No comparable first-party entry exists in openai.json's 2026-08-05 snapshot for "gpt-4-turbo" (it is either a legacy/superseded model no longer on OpenAI's current pricing page, or a variant OpenAI does not sell directly) \u2014 Azure's own resale rate is recorded as observed with no parity claim possible or intended.`] }
|
|
461
|
+
],
|
|
462
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
canonicalId: "gpt-4.1",
|
|
466
|
+
provider: "azure-openai",
|
|
467
|
+
aliases: [],
|
|
468
|
+
family: "gpt-4.1",
|
|
469
|
+
pricing: [
|
|
470
|
+
{ "effectiveFrom": "2025-04-01", "currency": "USD", "unit": "per-million-tokens", "input": "2.00", "output": "8.00", "cachedInput": "0.50", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["Azure's Retail Prices API quotes this meter per 1K tokens; converted to per-million-tokens by shifting the decimal point 3 places as exact string manipulation (never float multiplication).", "retailPrice confirmed identical across all 28 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "gpt-4.1" in openai.json exactly as observed ($2.00/$8.00/$0.50 cached) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "gpt-4.1" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
471
|
+
],
|
|
472
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
canonicalId: "gpt-4.1-mini",
|
|
476
|
+
provider: "azure-openai",
|
|
477
|
+
aliases: [],
|
|
478
|
+
family: "gpt-4.1",
|
|
479
|
+
pricing: [
|
|
480
|
+
{ "effectiveFrom": "2025-04-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.40", "output": "1.60", "cachedInput": "0.10", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["Azure's Retail Prices API quotes this meter per 1K tokens; converted to per-million-tokens by shifting the decimal point 3 places as exact string manipulation (never float multiplication).", "retailPrice confirmed identical across all 28 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "gpt-4.1-mini" in openai.json exactly as observed ($0.40/$1.60/$0.10 cached) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "gpt-4.1-mini" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
481
|
+
],
|
|
482
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
483
|
+
},
|
|
484
|
+
{
|
|
485
|
+
canonicalId: "gpt-4.1-nano",
|
|
486
|
+
provider: "azure-openai",
|
|
487
|
+
aliases: [],
|
|
488
|
+
family: "gpt-4.1",
|
|
489
|
+
pricing: [
|
|
490
|
+
{ "effectiveFrom": "2025-04-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.10", "output": "0.40", "cachedInput": "0.025", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["Azure's Retail Prices API quotes this meter per 1K tokens; converted to per-million-tokens by shifting the decimal point 3 places as exact string manipulation (never float multiplication).", "retailPrice confirmed identical across all 28 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "gpt-4.1-nano" in openai.json exactly as observed ($0.10/$0.40/$0.025 cached) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "gpt-4.1-nano" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
491
|
+
],
|
|
492
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
canonicalId: "gpt-4o",
|
|
496
|
+
provider: "azure-openai",
|
|
497
|
+
aliases: [],
|
|
498
|
+
family: "gpt-4o",
|
|
499
|
+
pricing: [
|
|
500
|
+
{ "effectiveFrom": "2024-12-01", "currency": "USD", "unit": "per-million-tokens", "input": "2.50", "output": "10.00", "cachedInput": "1.25", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["Azure's Retail Prices API quotes this meter per 1K tokens; converted to per-million-tokens by shifting the decimal point 3 places as exact string manipulation (never float multiplication).", "retailPrice confirmed identical across all 27 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "gpt-4o" in openai.json exactly as observed ($2.50/$10.00/$1.25 cached) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "gpt-4o" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
501
|
+
],
|
|
502
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
503
|
+
},
|
|
504
|
+
{
|
|
505
|
+
canonicalId: "gpt-4o-mini",
|
|
506
|
+
provider: "azure-openai",
|
|
507
|
+
aliases: [],
|
|
508
|
+
family: "gpt-4o",
|
|
509
|
+
pricing: [
|
|
510
|
+
{ "effectiveFrom": "2024-07-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.15", "output": "0.60", "cachedInput": "0.075", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["Azure's Retail Prices API quotes this meter per 1K tokens; converted to per-million-tokens by shifting the decimal point 3 places as exact string manipulation (never float multiplication).", "retailPrice confirmed identical across all 28 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "gpt-4o-mini" in openai.json exactly as observed ($0.15/$0.60/$0.075 cached) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "gpt-4o-mini" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
511
|
+
],
|
|
512
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
canonicalId: "gpt-5",
|
|
516
|
+
provider: "azure-openai",
|
|
517
|
+
aliases: [],
|
|
518
|
+
family: "gpt-5",
|
|
519
|
+
pricing: [
|
|
520
|
+
{ "effectiveFrom": "2025-08-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.25", "output": "10.00", "cachedInput": "0.125", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["retailPrice confirmed identical across all 24 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "gpt-5" in openai.json exactly as observed ($1.25/$10.00/$0.125 cached) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "gpt-5" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
521
|
+
],
|
|
522
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
523
|
+
},
|
|
524
|
+
{
|
|
525
|
+
canonicalId: "gpt-5-mini",
|
|
526
|
+
provider: "azure-openai",
|
|
527
|
+
aliases: [],
|
|
528
|
+
family: "gpt-5",
|
|
529
|
+
pricing: [
|
|
530
|
+
{ "effectiveFrom": "2025-08-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.25", "output": "2.00", "cachedInput": "0.025", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["retailPrice confirmed identical across all 27 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "gpt-5-mini" in openai.json exactly as observed ($0.25/$2.00/$0.025 cached) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "gpt-5-mini" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
531
|
+
],
|
|
532
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
canonicalId: "gpt-5-nano",
|
|
536
|
+
provider: "azure-openai",
|
|
537
|
+
aliases: [],
|
|
538
|
+
family: "gpt-5",
|
|
539
|
+
pricing: [
|
|
540
|
+
{ "effectiveFrom": "2025-08-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.05", "output": "0.40", "cachedInput": "0.005", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["retailPrice confirmed identical across all 27 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "gpt-5-nano" in openai.json exactly as observed ($0.05/$0.40/$0.005 cached) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "gpt-5-nano" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
541
|
+
],
|
|
542
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
543
|
+
},
|
|
544
|
+
{
|
|
545
|
+
canonicalId: "gpt-5-pro",
|
|
546
|
+
provider: "azure-openai",
|
|
547
|
+
aliases: [],
|
|
548
|
+
family: "gpt-5",
|
|
549
|
+
pricing: [
|
|
550
|
+
{ "effectiveFrom": "2025-10-01", "currency": "USD", "unit": "per-million-tokens", "input": "15.00", "output": "120.00", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["Azure's Retail Prices API quotes this meter per 1K tokens; converted to per-million-tokens by shifting the decimal point 3 places as exact string manipulation (never float multiplication).", "retailPrice confirmed identical across all 24 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "gpt-5-pro" in openai.json exactly as observed ($15.00/$120.00) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "gpt-5-pro" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
551
|
+
],
|
|
552
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
553
|
+
},
|
|
554
|
+
{
|
|
555
|
+
canonicalId: "gpt-5.1",
|
|
556
|
+
provider: "azure-openai",
|
|
557
|
+
aliases: [],
|
|
558
|
+
family: "gpt-5.1",
|
|
559
|
+
pricing: [
|
|
560
|
+
{ "effectiveFrom": "2025-11-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.25", "output": "10.00", "cachedInput": "0.125", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["retailPrice confirmed identical across all 25 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "gpt-5.1" in openai.json exactly as observed ($1.25/$10.00/$0.125 cached) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "gpt-5.1" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
561
|
+
],
|
|
562
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
563
|
+
},
|
|
564
|
+
{
|
|
565
|
+
canonicalId: "gpt-5.2",
|
|
566
|
+
provider: "azure-openai",
|
|
567
|
+
aliases: [],
|
|
568
|
+
family: "gpt-5.2",
|
|
569
|
+
pricing: [
|
|
570
|
+
{ "effectiveFrom": "2025-12-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.75", "output": "14.00", "cachedInput": "0.175", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["retailPrice confirmed identical across all 24 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "gpt-5.2" in openai.json exactly as observed ($1.75/$14.00/$0.175 cached) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "gpt-5.2" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
571
|
+
],
|
|
572
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
573
|
+
},
|
|
574
|
+
{
|
|
575
|
+
canonicalId: "gpt-5.2-pro",
|
|
576
|
+
provider: "azure-openai",
|
|
577
|
+
aliases: [],
|
|
578
|
+
family: "gpt-5.2",
|
|
579
|
+
pricing: [
|
|
580
|
+
{ "effectiveFrom": "2025-12-01", "currency": "USD", "unit": "per-million-tokens", "input": "21.00", "output": "168.00", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["retailPrice confirmed identical across all 24 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "gpt-5.2-pro" in openai.json exactly as observed ($21.00/$168.00) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "gpt-5.2-pro" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
581
|
+
],
|
|
582
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
583
|
+
},
|
|
584
|
+
{
|
|
585
|
+
canonicalId: "gpt-5.4",
|
|
586
|
+
provider: "azure-openai",
|
|
587
|
+
aliases: [],
|
|
588
|
+
family: "gpt-5.4",
|
|
589
|
+
pricing: [
|
|
590
|
+
{ "effectiveFrom": "2026-03-01", "currency": "USD", "unit": "per-million-tokens", "input": "2.50", "output": "15.00", "cachedInput": "0.25", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["retailPrice confirmed identical across all 25 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "gpt-5.4" in openai.json exactly as observed ($2.50/$15.00/$0.25 cached) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "gpt-5.4" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
591
|
+
],
|
|
592
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
593
|
+
},
|
|
594
|
+
{
|
|
595
|
+
canonicalId: "gpt-5.4-mini",
|
|
596
|
+
provider: "azure-openai",
|
|
597
|
+
aliases: [],
|
|
598
|
+
family: "gpt-5.4",
|
|
599
|
+
pricing: [
|
|
600
|
+
{ "effectiveFrom": "2026-03-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.75", "output": "4.50", "cachedInput": "0.075", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["retailPrice confirmed identical across all 25 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "gpt-5.4-mini" in openai.json exactly as observed ($0.75/$4.50/$0.075 cached) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "gpt-5.4-mini" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
601
|
+
],
|
|
602
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
603
|
+
},
|
|
604
|
+
{
|
|
605
|
+
canonicalId: "gpt-5.4-nano",
|
|
606
|
+
provider: "azure-openai",
|
|
607
|
+
aliases: [],
|
|
608
|
+
family: "gpt-5.4",
|
|
609
|
+
pricing: [
|
|
610
|
+
{ "effectiveFrom": "2026-03-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.20", "output": "1.25", "cachedInput": "0.02", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["retailPrice confirmed identical across all 25 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "gpt-5.4-nano" in openai.json exactly as observed ($0.20/$1.25/$0.02 cached) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "gpt-5.4-nano" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
611
|
+
],
|
|
612
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
canonicalId: "gpt-5.4-pro",
|
|
616
|
+
provider: "azure-openai",
|
|
617
|
+
aliases: [],
|
|
618
|
+
family: "gpt-5.4",
|
|
619
|
+
pricing: [
|
|
620
|
+
{ "effectiveFrom": "2026-03-01", "currency": "USD", "unit": "per-million-tokens", "input": "30.00", "output": "180.00", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["retailPrice confirmed identical across all 25 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "gpt-5.4-pro" in openai.json exactly as observed ($30.00/$180.00) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "gpt-5.4-pro" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
621
|
+
],
|
|
622
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
canonicalId: "gpt-5.5",
|
|
626
|
+
provider: "azure-openai",
|
|
627
|
+
aliases: [],
|
|
628
|
+
family: "gpt-5.5",
|
|
629
|
+
pricing: [
|
|
630
|
+
{ "effectiveFrom": "2026-05-01", "currency": "USD", "unit": "per-million-tokens", "input": "5.00", "output": "30.00", "cachedInput": "0.50", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["retailPrice confirmed identical across all 25 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "gpt-5.5" in openai.json exactly as observed ($5.00/$30.00/$0.50 cached) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "gpt-5.5" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
631
|
+
],
|
|
632
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
canonicalId: "gpt-5.6-luna",
|
|
636
|
+
provider: "azure-openai",
|
|
637
|
+
aliases: [],
|
|
638
|
+
family: "gpt-5.6",
|
|
639
|
+
pricing: [
|
|
640
|
+
{ "effectiveFrom": "2026-07-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.00", "output": "6.00", "cachedInput": "0.10", "cacheWrite": "1.25", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["retailPrice confirmed identical across all 24 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "No Batch API meter was found for this model/SKU in the Retail Prices API response; batchMultiplier is intentionally omitted rather than assumed.", `DIFFERS from OpenAI's own first-party rate recorded in openai.json for the same canonicalId "gpt-5.6-luna": OpenAI first-party is $0.20/$1.20 input/output (cached $0.02), Azure Global is $1.00/$6.00 (cached $0.10). Both independently observed on 2026-08-05; this is a genuine, confirmed pricing divergence between the two channels for the same named model, not a transcription error \u2014 this is exactly the kind of difference this provider file exists to capture.`, `canonicalId "gpt-5.6-luna" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
641
|
+
],
|
|
642
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
643
|
+
},
|
|
644
|
+
{
|
|
645
|
+
canonicalId: "gpt-5.6-sol",
|
|
646
|
+
provider: "azure-openai",
|
|
647
|
+
aliases: [],
|
|
648
|
+
family: "gpt-5.6",
|
|
649
|
+
pricing: [
|
|
650
|
+
{ "effectiveFrom": "2026-07-01", "currency": "USD", "unit": "per-million-tokens", "input": "5.00", "output": "30.00", "cachedInput": "0.50", "cacheWrite": "6.25", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["retailPrice confirmed identical across all 24 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "No Batch API meter was found for this model/SKU in the Retail Prices API response; batchMultiplier is intentionally omitted rather than assumed.", `Matches OpenAI's own first-party rate for "gpt-5.6-sol" in openai.json exactly as observed ($5.00/$30.00/$0.50 cached) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "gpt-5.6-sol" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
651
|
+
],
|
|
652
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
653
|
+
},
|
|
654
|
+
{
|
|
655
|
+
canonicalId: "gpt-5.6-terra",
|
|
656
|
+
provider: "azure-openai",
|
|
657
|
+
aliases: [],
|
|
658
|
+
family: "gpt-5.6",
|
|
659
|
+
pricing: [
|
|
660
|
+
{ "effectiveFrom": "2026-07-01", "currency": "USD", "unit": "per-million-tokens", "input": "2.50", "output": "15.00", "cachedInput": "0.25", "cacheWrite": "3.125", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["retailPrice confirmed identical across all 24 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "No Batch API meter was found for this model/SKU in the Retail Prices API response; batchMultiplier is intentionally omitted rather than assumed.", `DIFFERS from OpenAI's own first-party rate recorded in openai.json for the same canonicalId "gpt-5.6-terra": OpenAI first-party is $2.00/$12.00 input/output (cached $0.20), Azure Global is $2.50/$15.00 (cached $0.25). Both independently observed on 2026-08-05; this is a genuine, confirmed pricing divergence between the two channels for the same named model, not a transcription error \u2014 this is exactly the kind of difference this provider file exists to capture.`, `canonicalId "gpt-5.6-terra" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
661
|
+
],
|
|
662
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
canonicalId: "o1",
|
|
666
|
+
provider: "azure-openai",
|
|
667
|
+
aliases: [],
|
|
668
|
+
family: "o-series",
|
|
669
|
+
pricing: [
|
|
670
|
+
{ "effectiveFrom": "2024-12-01", "currency": "USD", "unit": "per-million-tokens", "input": "15.00", "output": "60.00", "cachedInput": "7.50", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["Azure's Retail Prices API quotes this meter per 1K tokens; converted to per-million-tokens by shifting the decimal point 3 places as exact string manipulation (never float multiplication).", "retailPrice confirmed identical across all 26 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "o1" in openai.json exactly as observed ($15.00/$60.00/$7.50 cached) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "o1" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
671
|
+
],
|
|
672
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
673
|
+
},
|
|
674
|
+
{
|
|
675
|
+
canonicalId: "o1-mini",
|
|
676
|
+
provider: "azure-openai",
|
|
677
|
+
aliases: [],
|
|
678
|
+
family: "o-series",
|
|
679
|
+
pricing: [
|
|
680
|
+
{ "effectiveFrom": "2025-04-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.10", "output": "4.40", "cachedInput": "0.55", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["Azure's Retail Prices API quotes this meter per 1K tokens; converted to per-million-tokens by shifting the decimal point 3 places as exact string manipulation (never float multiplication).", "retailPrice confirmed identical across all 25 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `No comparable first-party entry exists in openai.json's 2026-08-05 snapshot for "o1-mini" (it is either a legacy/superseded model no longer on OpenAI's current pricing page, or a variant OpenAI does not sell directly) \u2014 Azure's own resale rate is recorded as observed with no parity claim possible or intended.`] }
|
|
681
|
+
],
|
|
682
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
683
|
+
},
|
|
684
|
+
{
|
|
685
|
+
canonicalId: "o1-preview",
|
|
686
|
+
provider: "azure-openai",
|
|
687
|
+
aliases: [],
|
|
688
|
+
family: "o-series",
|
|
689
|
+
pricing: [
|
|
690
|
+
{ "effectiveFrom": "2024-10-01", "currency": "USD", "unit": "per-million-tokens", "input": "15.00", "output": "60.00", "cachedInput": "7.50", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["Azure's Retail Prices API quotes this meter per 1K tokens; converted to per-million-tokens by shifting the decimal point 3 places as exact string manipulation (never float multiplication).", "retailPrice confirmed identical across all 3 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "No Batch API meter was found for this model/SKU in the Retail Prices API response; batchMultiplier is intentionally omitted rather than assumed.", `No comparable first-party entry exists in openai.json's 2026-08-05 snapshot for "o1-preview" (it is either a legacy/superseded model no longer on OpenAI's current pricing page, or a variant OpenAI does not sell directly) \u2014 Azure's own resale rate is recorded as observed with no parity claim possible or intended.`] }
|
|
691
|
+
],
|
|
692
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
693
|
+
},
|
|
694
|
+
{
|
|
695
|
+
canonicalId: "o1-pro",
|
|
696
|
+
provider: "azure-openai",
|
|
697
|
+
aliases: [],
|
|
698
|
+
family: "o-series",
|
|
699
|
+
pricing: [
|
|
700
|
+
{ "effectiveFrom": "2025-03-01", "currency": "USD", "unit": "per-million-tokens", "input": "150.00", "output": "600.00", "cachedInput": "75.00", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["Azure's Retail Prices API quotes this meter per 1K tokens; converted to per-million-tokens by shifting the decimal point 3 places as exact string manipulation (never float multiplication).", "retailPrice confirmed identical across all 25 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "o1-pro" in openai.json exactly as observed ($150.00/$600.00) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "o1-pro" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
701
|
+
],
|
|
702
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
703
|
+
},
|
|
704
|
+
{
|
|
705
|
+
canonicalId: "o3",
|
|
706
|
+
provider: "azure-openai",
|
|
707
|
+
aliases: [],
|
|
708
|
+
family: "o-series",
|
|
709
|
+
pricing: [
|
|
710
|
+
{ "effectiveFrom": "2025-06-01", "currency": "USD", "unit": "per-million-tokens", "input": "2.00", "output": "8.00", "cachedInput": "0.50", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["Azure's Retail Prices API quotes this meter per 1K tokens; converted to per-million-tokens by shifting the decimal point 3 places as exact string manipulation (never float multiplication).", "retailPrice confirmed identical across all 24 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "o3" in openai.json exactly as observed ($2.00/$8.00/$0.50 cached) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "o3" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
711
|
+
],
|
|
712
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
713
|
+
},
|
|
714
|
+
{
|
|
715
|
+
canonicalId: "o3-mini",
|
|
716
|
+
provider: "azure-openai",
|
|
717
|
+
aliases: [],
|
|
718
|
+
family: "o-series",
|
|
719
|
+
pricing: [
|
|
720
|
+
{ "effectiveFrom": "2025-02-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.10", "output": "4.40", "cachedInput": "0.55", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["Azure's Retail Prices API quotes this meter per 1K tokens; converted to per-million-tokens by shifting the decimal point 3 places as exact string manipulation (never float multiplication).", "retailPrice confirmed identical across all 27 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "o3-mini" in openai.json exactly as observed ($1.10/$4.40/$0.55 cached) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "o3-mini" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
721
|
+
],
|
|
722
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
723
|
+
},
|
|
724
|
+
{
|
|
725
|
+
canonicalId: "o3-pro",
|
|
726
|
+
provider: "azure-openai",
|
|
727
|
+
aliases: [],
|
|
728
|
+
family: "o-series",
|
|
729
|
+
pricing: [
|
|
730
|
+
{ "effectiveFrom": "2025-06-01", "currency": "USD", "unit": "per-million-tokens", "input": "20.00", "output": "80.00", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["Azure's Retail Prices API quotes this meter per 1K tokens; converted to per-million-tokens by shifting the decimal point 3 places as exact string manipulation (never float multiplication).", "retailPrice confirmed identical across all 24 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "o3-pro" in openai.json exactly as observed ($20.00/$80.00) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "o3-pro" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
731
|
+
],
|
|
732
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
733
|
+
},
|
|
734
|
+
{
|
|
735
|
+
canonicalId: "o4-mini",
|
|
736
|
+
provider: "azure-openai",
|
|
737
|
+
aliases: [],
|
|
738
|
+
family: "o-series",
|
|
739
|
+
pricing: [
|
|
740
|
+
{ "effectiveFrom": "2025-04-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.10", "output": "4.40", "cachedInput": "0.275", "batchMultiplier": "0.5", "cheapestTier": true, "sourceUrl": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05", "notes": ["Azure's Retail Prices API quotes this meter per 1K tokens; converted to per-million-tokens by shifting the decimal point 3 places as exact string manipulation (never float multiplication).", "retailPrice confirmed identical across all 26 Azure regions returned for this Global-deployment SKU (spot-checked programmatically, not just a couple of regions) \u2014 no regional price variation observed for the Global tier.", "batchMultiplier 0.5 independently confirmed from this model's own Batch-API meter on Azure (batch input and output rows both computed to exactly 0.5x the standard Global rate), not assumed from a blanket policy statement.", `Matches OpenAI's own first-party rate for "o4-mini" in openai.json exactly as observed ($1.10/$4.40/$0.275 cached) \u2014 no markup detected for this model on Azure's Global deployment tier.`, `canonicalId "o4-mini" is deliberately identical to the same model's entry in openai.json \u2014 Azure genuinely resells the identical first-party OpenAI model, unlike AWS Bedrock's or OpenRouter's differently-branded catalogues. Following the aws-bedrock.json precedent (e.g. its "mistral-large-3" and "gemma-4-31b" entries) rather than OpenRouter's provider-prefixed-slug convention: this is an intentional cross-provider canonicalId collision, not an error. A bare lookup of this id without a provider qualifier is ambiguous by design and must fail, exactly as already documented for the aws-bedrock.json collisions, since a lookup with a duplicated canonicalId requires a provider qualifier to resolve unambiguously. Per this task's ownership boundary, openai.json itself was not modified to cross-reference this note; a follow-up pass should add a mirroring note there.`] }
|
|
741
|
+
],
|
|
742
|
+
source: { "url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=contains(productName,%20%27OpenAI%27)", "observedAt": "2026-08-05" }
|
|
743
|
+
},
|
|
744
|
+
{
|
|
745
|
+
canonicalId: "aya-expanse-32b",
|
|
746
|
+
provider: "cohere",
|
|
747
|
+
aliases: [],
|
|
748
|
+
family: "aya-expanse",
|
|
749
|
+
pricing: [
|
|
750
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.50", "output": "1.50", "sourceUrl": "https://cohere.com/pricing", "observedAt": "2026-08-05", "notes": ["Cohere's pricing page publishes an identical $0.50/$1.50 rate for both the 8B and 32B Aya Expanse sizes (confirmed by two independent re-fetches of the same page); this was double-checked rather than assumed to be an extraction error.", "effectiveFrom set conservatively to 2026-01-01; exact rate-effective date not published."] }
|
|
751
|
+
],
|
|
752
|
+
source: { "url": "https://cohere.com/pricing", "observedAt": "2026-08-05" }
|
|
753
|
+
},
|
|
754
|
+
{
|
|
755
|
+
canonicalId: "aya-expanse-8b",
|
|
756
|
+
provider: "cohere",
|
|
757
|
+
aliases: [],
|
|
758
|
+
family: "aya-expanse",
|
|
759
|
+
pricing: [
|
|
760
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.50", "output": "1.50", "sourceUrl": "https://cohere.com/pricing", "observedAt": "2026-08-05", "notes": ["Cohere's pricing page publishes an identical $0.50/$1.50 rate for both the 8B and 32B Aya Expanse sizes (confirmed by two independent re-fetches of the same page); this was double-checked rather than assumed to be an extraction error.", "effectiveFrom set conservatively to 2026-01-01; exact rate-effective date not published."] }
|
|
761
|
+
],
|
|
762
|
+
source: { "url": "https://cohere.com/pricing", "observedAt": "2026-08-05" }
|
|
763
|
+
},
|
|
764
|
+
{
|
|
765
|
+
canonicalId: "command",
|
|
766
|
+
provider: "cohere",
|
|
767
|
+
aliases: [],
|
|
768
|
+
family: "command",
|
|
769
|
+
pricing: [
|
|
770
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.00", "output": "2.00", "sourceUrl": "https://cohere.com/pricing", "observedAt": "2026-08-05", "notes": ["Cohere's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01.", "This rate appears in the pricing page's FAQ/legacy-rates section, not a headline pricing table; it is nonetheless the only per-token price Cohere currently publishes for this model."] }
|
|
771
|
+
],
|
|
772
|
+
source: { "url": "https://cohere.com/pricing", "observedAt": "2026-08-05" }
|
|
773
|
+
},
|
|
774
|
+
{
|
|
775
|
+
canonicalId: "command-light",
|
|
776
|
+
provider: "cohere",
|
|
777
|
+
aliases: [],
|
|
778
|
+
family: "command",
|
|
779
|
+
pricing: [
|
|
780
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.30", "output": "0.60", "sourceUrl": "https://cohere.com/pricing", "observedAt": "2026-08-05", "notes": ["Cohere's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01.", 'FAQ/legacy-rates section pricing, per the same caveat as "command".'] }
|
|
781
|
+
],
|
|
782
|
+
source: { "url": "https://cohere.com/pricing", "observedAt": "2026-08-05" }
|
|
783
|
+
},
|
|
784
|
+
{
|
|
785
|
+
canonicalId: "command-r-03-2024",
|
|
786
|
+
provider: "cohere",
|
|
787
|
+
aliases: [],
|
|
788
|
+
family: "command-r",
|
|
789
|
+
pricing: [
|
|
790
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.50", "output": "1.50", "sourceUrl": "https://cohere.com/pricing", "observedAt": "2026-08-05", "notes": [`"03-2024" is Cohere's own dated-snapshot naming for this model, not a confirmed price-effective date; effectiveFrom is set conservatively to 2026-01-01 per this repository's convention (a too-early effectiveFrom is safe; the price could have applied earlier than 2026 but was not independently confirmed).`, "FAQ/legacy-rates section pricing."] }
|
|
791
|
+
],
|
|
792
|
+
source: { "url": "https://cohere.com/pricing", "observedAt": "2026-08-05" }
|
|
793
|
+
},
|
|
794
|
+
{
|
|
795
|
+
canonicalId: "command-r-plus-04-2024",
|
|
796
|
+
provider: "cohere",
|
|
797
|
+
aliases: [],
|
|
798
|
+
family: "command-r-plus",
|
|
799
|
+
pricing: [
|
|
800
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "3.00", "output": "15.00", "sourceUrl": "https://cohere.com/pricing", "observedAt": "2026-08-05", "notes": [`"04-2024" is Cohere's own dated-snapshot naming for this model, not a confirmed price-effective date; effectiveFrom is set conservatively to 2026-01-01.`, `FAQ/legacy-rates section pricing. Superseded in Cohere's catalogue by "Command R+ 08-2024" (below), a distinct dated snapshot with its own price \u2014 the two are not the same PricingPeriod for one model, they are two different canonicalIds, matching how Cohere itself lists them.`] }
|
|
801
|
+
],
|
|
802
|
+
source: { "url": "https://cohere.com/pricing", "observedAt": "2026-08-05" }
|
|
803
|
+
},
|
|
804
|
+
{
|
|
805
|
+
canonicalId: "command-r-plus-08-2024",
|
|
806
|
+
provider: "cohere",
|
|
807
|
+
aliases: [],
|
|
808
|
+
family: "command-r-plus",
|
|
809
|
+
pricing: [
|
|
810
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "2.50", "output": "10.00", "sourceUrl": "https://cohere.com/pricing", "observedAt": "2026-08-05", "notes": [`"08-2024" is Cohere's own dated-snapshot naming for this model, not a confirmed price-effective date; effectiveFrom is set conservatively to 2026-01-01.`, "FAQ/legacy-rates section pricing."] }
|
|
811
|
+
],
|
|
812
|
+
source: { "url": "https://cohere.com/pricing", "observedAt": "2026-08-05" }
|
|
813
|
+
},
|
|
814
|
+
{
|
|
815
|
+
canonicalId: "gemini-2.5-flash",
|
|
816
|
+
provider: "google",
|
|
817
|
+
aliases: [],
|
|
818
|
+
family: "gemini-2.5",
|
|
819
|
+
pricing: [
|
|
820
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.30", "output": "2.50", "batchMultiplier": "0.5", "sourceUrl": "https://ai.google.dev/gemini-api/docs/pricing", "observedAt": "2026-08-05", "notes": ["Standard (paid) tier rate. Priority tier is $0.54/$4.50 (1.8x standard); not modeled as a separate field.", "effectiveFrom set conservatively to 2026-01-01; exact rate-effective date not published.", "cachedInput omitted: not confirmed per-model.", "batchMultiplier of 0.5 verified directly from this model's own Batch row ($0.15/$1.25 vs standard $0.30/$2.50)."] }
|
|
821
|
+
],
|
|
822
|
+
source: { "url": "https://ai.google.dev/gemini-api/docs/pricing", "observedAt": "2026-08-05" }
|
|
823
|
+
},
|
|
824
|
+
{
|
|
825
|
+
canonicalId: "gemini-2.5-flash-lite",
|
|
826
|
+
provider: "google",
|
|
827
|
+
aliases: [],
|
|
828
|
+
family: "gemini-2.5",
|
|
829
|
+
pricing: [
|
|
830
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.10", "output": "0.40", "batchMultiplier": "0.5", "sourceUrl": "https://ai.google.dev/gemini-api/docs/pricing", "observedAt": "2026-08-05", "notes": ["Standard (paid) tier rate.", "effectiveFrom set conservatively to 2026-01-01; exact rate-effective date not published.", "cachedInput omitted: not confirmed per-model.", "batchMultiplier of 0.5 verified directly from this model's own Batch row ($0.05/$0.20 vs standard $0.10/$0.40)."] }
|
|
831
|
+
],
|
|
832
|
+
source: { "url": "https://ai.google.dev/gemini-api/docs/pricing", "observedAt": "2026-08-05" }
|
|
833
|
+
},
|
|
834
|
+
{
|
|
835
|
+
canonicalId: "gemini-2.5-pro",
|
|
836
|
+
provider: "google",
|
|
837
|
+
aliases: [],
|
|
838
|
+
family: "gemini-2.5",
|
|
839
|
+
pricing: [
|
|
840
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.25", "output": "10.00", "cheapestTier": true, "sourceUrl": "https://ai.google.dev/gemini-api/docs/pricing", "observedAt": "2026-08-05", "notes": ["This is the standard-tier rate for prompts <= 200k tokens. For prompts > 200k tokens the page publishes a higher rate ($2.50 input / $15.00 output per 1M tokens) \u2014 this schema has no context-length-tiered pricing field, so only the <=200k (lower) tier is recorded here. Do not use this entry for long-context (>200k) requests.", "cachedInput and batchMultiplier are omitted: not confirmed for this Pro-tier model (the page states Batch/Flex give a general 50% reduction on input/output pricing, but no explicit per-model Batch row for this model was independently verified).", "effectiveFrom set conservatively to 2026-01-01; exact rate-effective date not published."] }
|
|
841
|
+
],
|
|
842
|
+
source: { "url": "https://ai.google.dev/gemini-api/docs/pricing", "observedAt": "2026-08-05" }
|
|
843
|
+
},
|
|
844
|
+
{
|
|
845
|
+
canonicalId: "gemini-3.1-pro-preview",
|
|
846
|
+
provider: "google",
|
|
847
|
+
aliases: [],
|
|
848
|
+
family: "gemini-3.1",
|
|
849
|
+
pricing: [
|
|
850
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "2.00", "output": "12.00", "cheapestTier": true, "sourceUrl": "https://ai.google.dev/gemini-api/docs/pricing", "observedAt": "2026-08-05", "notes": ["This is the standard-tier rate for prompts <= 200k tokens. For prompts > 200k tokens the page publishes a higher rate ($4.00 input / $18.00 output per 1M tokens) \u2014 this schema has no context-length-tiered pricing field, so only the <=200k (lower) tier is recorded here. Do not use this entry for long-context (>200k) requests.", "cachedInput and batchMultiplier are omitted: not confirmed for this Pro-tier model (unlike the Flash-tier models above, no explicit per-model Batch row was found for this model).", 'effectiveFrom set conservatively to 2026-01-01; exact rate-effective date not published. "-preview" in the model name suggests this may be short-lived/subject to change.', 'canonicalId uses the exact model name Google publishes on the pricing page ("Gemini 3.1 Pro Preview").'] }
|
|
851
|
+
],
|
|
852
|
+
source: { "url": "https://ai.google.dev/gemini-api/docs/pricing", "observedAt": "2026-08-05" }
|
|
853
|
+
},
|
|
854
|
+
{
|
|
855
|
+
canonicalId: "gemini-3.5-flash",
|
|
856
|
+
provider: "google",
|
|
857
|
+
aliases: [],
|
|
858
|
+
family: "gemini-3.5",
|
|
859
|
+
pricing: [
|
|
860
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.50", "output": "9.00", "batchMultiplier": "0.5", "sourceUrl": "https://ai.google.dev/gemini-api/docs/pricing", "observedAt": "2026-08-05", "notes": ["Standard (paid) tier rate. Priority tier is $2.70/$16.20 (1.8x standard); not modeled as a separate field.", 'effectiveFrom set conservatively to 2026-01-01; page shows a "Last Updated: July 30, 2026" stamp but not a rate-specific effective date.', "cachedInput omitted: not confirmed per-model (see gemini-3.6-flash notes for the same caveat).", "batchMultiplier of 0.5 verified directly from this model's own Batch row ($0.75/$4.50 vs standard $1.50/$9.00)."] }
|
|
861
|
+
],
|
|
862
|
+
source: { "url": "https://ai.google.dev/gemini-api/docs/pricing", "observedAt": "2026-08-05" }
|
|
863
|
+
},
|
|
864
|
+
{
|
|
865
|
+
canonicalId: "gemini-3.5-flash-lite",
|
|
866
|
+
provider: "google",
|
|
867
|
+
aliases: [],
|
|
868
|
+
family: "gemini-3.5",
|
|
869
|
+
pricing: [
|
|
870
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.30", "output": "2.50", "batchMultiplier": "0.5", "sourceUrl": "https://ai.google.dev/gemini-api/docs/pricing", "observedAt": "2026-08-05", "notes": ["Standard (paid) tier rate. Priority tier is $0.54/$4.50 (1.8x standard); not modeled as a separate field.", "effectiveFrom set conservatively to 2026-01-01; exact rate-effective date not published.", "cachedInput omitted: not confirmed per-model.", "batchMultiplier of 0.5 verified directly from this model's own Batch row ($0.15/$1.25 vs standard $0.30/$2.50)."] }
|
|
871
|
+
],
|
|
872
|
+
source: { "url": "https://ai.google.dev/gemini-api/docs/pricing", "observedAt": "2026-08-05" }
|
|
873
|
+
},
|
|
874
|
+
{
|
|
875
|
+
canonicalId: "gemini-3.6-flash",
|
|
876
|
+
provider: "google",
|
|
877
|
+
aliases: [],
|
|
878
|
+
family: "gemini-3.6",
|
|
879
|
+
pricing: [
|
|
880
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.50", "output": "7.50", "batchMultiplier": "0.5", "sourceUrl": "https://ai.google.dev/gemini-api/docs/pricing", "observedAt": "2026-08-05", "notes": ["Standard (paid) tier rate. The page also lists Flex and Priority tiers, which this schema does not model as separate fields: Flex is priced the same as Batch ($0.75/$3.75); Priority is $2.70/$13.50 (1.8x standard).", `Google's page shows "Last Updated: July 30, 2026 UTC" but does not state when this specific rate took effect; effectiveFrom is set conservatively to 2026-01-01.`, `cachedInput (context caching) is omitted: the page states a general "$0.15 per 1M cached input tokens" figure covering multiple models but does not confirm it is this specific model's rate, plus a separate per-hour storage fee this schema does not model. Recording an unconfirmed number would be worse than omitting it.`, "batchMultiplier of 0.5 was verified directly from this model's own Batch row ($0.75/$3.75 vs standard $1.50/$7.50)."] }
|
|
881
|
+
],
|
|
882
|
+
source: { "url": "https://ai.google.dev/gemini-api/docs/pricing", "observedAt": "2026-08-05" }
|
|
883
|
+
},
|
|
884
|
+
{
|
|
885
|
+
canonicalId: "gpt-oss-120b",
|
|
886
|
+
provider: "groq",
|
|
887
|
+
aliases: [],
|
|
888
|
+
family: "gpt-oss",
|
|
889
|
+
pricing: [
|
|
890
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.15", "output": "0.60", "sourceUrl": "https://console.groq.com/docs/models", "observedAt": "2026-08-05", "notes": ["Groq's docs page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01.", "No prompt-caching or Batch API discount is documented for Groq in the fetched page.", "OpenAI's open-weight gpt-oss-120b model, hosted independently by Groq under Groq's own rate card (also hosted by Together AI, at the same $0.15/$0.60 rate as observed \u2014 coincidental agreement, not assumed parity)."] }
|
|
891
|
+
],
|
|
892
|
+
source: { "url": "https://console.groq.com/docs/models", "observedAt": "2026-08-05" }
|
|
893
|
+
},
|
|
894
|
+
{
|
|
895
|
+
canonicalId: "gpt-oss-20b",
|
|
896
|
+
provider: "groq",
|
|
897
|
+
aliases: [],
|
|
898
|
+
family: "gpt-oss",
|
|
899
|
+
pricing: [
|
|
900
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.075", "output": "0.30", "sourceUrl": "https://console.groq.com/docs/models", "observedAt": "2026-08-05", "notes": ["Groq's docs page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01.", "No prompt-caching or Batch API discount is documented for Groq in the fetched page.", "Also hosted by Together AI at a different rate ($0.05/$0.20 as observed) \u2014 each host prices it independently; do not assume parity."] }
|
|
901
|
+
],
|
|
902
|
+
source: { "url": "https://console.groq.com/docs/models", "observedAt": "2026-08-05" }
|
|
903
|
+
},
|
|
904
|
+
{
|
|
905
|
+
canonicalId: "llama-3.1-8b-instant",
|
|
906
|
+
provider: "groq",
|
|
907
|
+
aliases: ["llama-3.1-8b"],
|
|
908
|
+
family: "llama-3.1",
|
|
909
|
+
pricing: [
|
|
910
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.05", "output": "0.08", "sourceUrl": "https://console.groq.com/docs/models", "observedAt": "2026-08-05", "notes": ["Groq's docs page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01.", "No prompt-caching or Batch API discount is documented for Groq in the fetched page, so cachedInput and batchMultiplier are omitted rather than assumed."] }
|
|
911
|
+
],
|
|
912
|
+
source: { "url": "https://console.groq.com/docs/models", "observedAt": "2026-08-05" }
|
|
913
|
+
},
|
|
914
|
+
{
|
|
915
|
+
canonicalId: "llama-3.3-70b-versatile",
|
|
916
|
+
provider: "groq",
|
|
917
|
+
aliases: ["llama-3.3-70b"],
|
|
918
|
+
family: "llama-3.3",
|
|
919
|
+
pricing: [
|
|
920
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.59", "output": "0.79", "sourceUrl": "https://console.groq.com/docs/models", "observedAt": "2026-08-05", "notes": ["Groq's docs page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01.", "No prompt-caching or Batch API discount is documented for Groq in the fetched page, so cachedInput and batchMultiplier are omitted rather than assumed.", "This is Groq's own hosted rate for the same open-weight model Together AI also hosts (see together.json's llama-3.3-70b at a different, higher price) and AWS Bedrock resells \u2014 each host prices it independently; do not assume parity."] }
|
|
921
|
+
],
|
|
922
|
+
source: { "url": "https://console.groq.com/docs/models", "observedAt": "2026-08-05" }
|
|
923
|
+
},
|
|
924
|
+
{
|
|
925
|
+
canonicalId: "qwen3.6-27b",
|
|
926
|
+
provider: "groq",
|
|
927
|
+
aliases: [],
|
|
928
|
+
family: "qwen",
|
|
929
|
+
pricing: [
|
|
930
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.60", "output": "3.00", "sourceUrl": "https://console.groq.com/docs/models", "observedAt": "2026-08-05", "notes": [`Listed under Groq's "Preview" models section, not "Production" \u2014 preview models on Groq are explicitly subject to change or removal without notice. Included because a real price was published, but treat this one as less stable than the production-tier entries in this file.`, "Groq's docs page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01."] }
|
|
931
|
+
],
|
|
932
|
+
source: { "url": "https://console.groq.com/docs/models", "observedAt": "2026-08-05" }
|
|
933
|
+
},
|
|
934
|
+
{
|
|
935
|
+
canonicalId: "codestral",
|
|
936
|
+
provider: "mistral",
|
|
937
|
+
aliases: [],
|
|
938
|
+
family: "codestral",
|
|
939
|
+
pricing: [
|
|
940
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.30", "output": "0.90", "sourceUrl": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05", "notes": ["Mistral's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01."] }
|
|
941
|
+
],
|
|
942
|
+
source: { "url": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05" }
|
|
943
|
+
},
|
|
944
|
+
{
|
|
945
|
+
canonicalId: "devstral-2",
|
|
946
|
+
provider: "mistral",
|
|
947
|
+
aliases: [],
|
|
948
|
+
family: "devstral",
|
|
949
|
+
pricing: [
|
|
950
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.40", "output": "2.00", "sourceUrl": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05", "notes": ["Mistral's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01."] }
|
|
951
|
+
],
|
|
952
|
+
source: { "url": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05" }
|
|
953
|
+
},
|
|
954
|
+
{
|
|
955
|
+
canonicalId: "devstral-small-2",
|
|
956
|
+
provider: "mistral",
|
|
957
|
+
aliases: [],
|
|
958
|
+
family: "devstral",
|
|
959
|
+
pricing: [
|
|
960
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.10", "output": "0.30", "sourceUrl": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05", "notes": ["Mistral's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01."] }
|
|
961
|
+
],
|
|
962
|
+
source: { "url": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05" }
|
|
963
|
+
},
|
|
964
|
+
{
|
|
965
|
+
canonicalId: "magistral-medium",
|
|
966
|
+
provider: "mistral",
|
|
967
|
+
aliases: [],
|
|
968
|
+
family: "magistral",
|
|
969
|
+
pricing: [
|
|
970
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "2.00", "output": "5.00", "sourceUrl": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05", "notes": ["Mistral's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01.", 'Listed as a reasoning model on the pricing page; no separate "reasoning" surcharge is published, so the reasoning field is omitted.'] }
|
|
971
|
+
],
|
|
972
|
+
source: { "url": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05" }
|
|
973
|
+
},
|
|
974
|
+
{
|
|
975
|
+
canonicalId: "magistral-small",
|
|
976
|
+
provider: "mistral",
|
|
977
|
+
aliases: [],
|
|
978
|
+
family: "magistral",
|
|
979
|
+
pricing: [
|
|
980
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.50", "output": "1.50", "sourceUrl": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05", "notes": ["Mistral's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01."] }
|
|
981
|
+
],
|
|
982
|
+
source: { "url": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05" }
|
|
983
|
+
},
|
|
984
|
+
{
|
|
985
|
+
canonicalId: "ministral-3-14b",
|
|
986
|
+
provider: "mistral",
|
|
987
|
+
aliases: [],
|
|
988
|
+
family: "ministral-3",
|
|
989
|
+
pricing: [
|
|
990
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.20", "output": "0.20", "sourceUrl": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05", "notes": ["Mistral's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01.", `AWS Bedrock resells a "Ministral 14B 3.0" at the same $0.20/$0.20 figure as independently observed on Bedrock's pricing page \u2014 likely the same model, coincidental agreement not assumed; Bedrock's variant was not added to aws-bedrock.json in this pass since the version suffix ("3.0") was not cross-checked against this "ministral-3-14b" naming.`] }
|
|
991
|
+
],
|
|
992
|
+
source: { "url": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05" }
|
|
993
|
+
},
|
|
994
|
+
{
|
|
995
|
+
canonicalId: "ministral-3-3b",
|
|
996
|
+
provider: "mistral",
|
|
997
|
+
aliases: [],
|
|
998
|
+
family: "ministral-3",
|
|
999
|
+
pricing: [
|
|
1000
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.10", "output": "0.10", "sourceUrl": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05", "notes": ["Mistral's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01."] }
|
|
1001
|
+
],
|
|
1002
|
+
source: { "url": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05" }
|
|
1003
|
+
},
|
|
1004
|
+
{
|
|
1005
|
+
canonicalId: "ministral-3-8b",
|
|
1006
|
+
provider: "mistral",
|
|
1007
|
+
aliases: [],
|
|
1008
|
+
family: "ministral-3",
|
|
1009
|
+
pricing: [
|
|
1010
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.15", "output": "0.15", "sourceUrl": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05", "notes": ["Mistral's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01."] }
|
|
1011
|
+
],
|
|
1012
|
+
source: { "url": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05" }
|
|
1013
|
+
},
|
|
1014
|
+
{
|
|
1015
|
+
canonicalId: "mistral-large-3",
|
|
1016
|
+
provider: "mistral",
|
|
1017
|
+
aliases: [],
|
|
1018
|
+
family: "mistral-large",
|
|
1019
|
+
pricing: [
|
|
1020
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.50", "output": "1.50", "sourceUrl": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05", "notes": ["Mistral's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01.", `This is Mistral's own first-party rate. AWS Bedrock also resells "Mistral Large 3" under its own rate card at the same $0.50/$1.50 figure as independently observed on Bedrock's pricing page \u2014 coincidental agreement between the two sources, not assumed; see aws-bedrock.json.`] }
|
|
1021
|
+
],
|
|
1022
|
+
source: { "url": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05" }
|
|
1023
|
+
},
|
|
1024
|
+
{
|
|
1025
|
+
canonicalId: "mistral-medium-3.5",
|
|
1026
|
+
provider: "mistral",
|
|
1027
|
+
aliases: [],
|
|
1028
|
+
family: "mistral-medium",
|
|
1029
|
+
pricing: [
|
|
1030
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.50", "output": "7.50", "sourceUrl": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05", "notes": ["Mistral's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01.", "No cachedInput or batchMultiplier is documented on the fetched page for this model; omitted rather than assumed."] }
|
|
1031
|
+
],
|
|
1032
|
+
source: { "url": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05" }
|
|
1033
|
+
},
|
|
1034
|
+
{
|
|
1035
|
+
canonicalId: "mistral-nemo",
|
|
1036
|
+
provider: "mistral",
|
|
1037
|
+
aliases: [],
|
|
1038
|
+
family: "mistral-nemo",
|
|
1039
|
+
pricing: [
|
|
1040
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.15", "output": "0.15", "sourceUrl": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05", "notes": ["Mistral's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01.", "An older model generation still listed with a live price on the current pricing page as fetched; included because it is confidently sourced, not because it is a current flagship."] }
|
|
1041
|
+
],
|
|
1042
|
+
source: { "url": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05" }
|
|
1043
|
+
},
|
|
1044
|
+
{
|
|
1045
|
+
canonicalId: "mistral-small-4",
|
|
1046
|
+
provider: "mistral",
|
|
1047
|
+
aliases: [],
|
|
1048
|
+
family: "mistral-small",
|
|
1049
|
+
pricing: [
|
|
1050
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.15", "output": "0.60", "sourceUrl": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05", "notes": ["Mistral's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01."] }
|
|
1051
|
+
],
|
|
1052
|
+
source: { "url": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05" }
|
|
1053
|
+
},
|
|
1054
|
+
{
|
|
1055
|
+
canonicalId: "mixtral-8x22b",
|
|
1056
|
+
provider: "mistral",
|
|
1057
|
+
aliases: [],
|
|
1058
|
+
family: "mixtral",
|
|
1059
|
+
pricing: [
|
|
1060
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "2.00", "output": "6.00", "sourceUrl": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05", "notes": ["Mistral's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01.", "An older model generation still listed with a live price on the current pricing page as fetched."] }
|
|
1061
|
+
],
|
|
1062
|
+
source: { "url": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05" }
|
|
1063
|
+
},
|
|
1064
|
+
{
|
|
1065
|
+
canonicalId: "mixtral-8x7b",
|
|
1066
|
+
provider: "mistral",
|
|
1067
|
+
aliases: [],
|
|
1068
|
+
family: "mixtral",
|
|
1069
|
+
pricing: [
|
|
1070
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.70", "output": "0.70", "sourceUrl": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05", "notes": ["Mistral's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01.", "An older model generation still listed with a live price on the current pricing page as fetched."] }
|
|
1071
|
+
],
|
|
1072
|
+
source: { "url": "https://mistral.ai/pricing/api", "observedAt": "2026-08-05" }
|
|
1073
|
+
},
|
|
1074
|
+
{
|
|
1075
|
+
canonicalId: "gpt-3.5-turbo",
|
|
1076
|
+
provider: "openai",
|
|
1077
|
+
aliases: [],
|
|
1078
|
+
family: "gpt-3.5",
|
|
1079
|
+
pricing: [
|
|
1080
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.50", "output": "1.50", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ["Found on https://developers.openai.com/api/docs/pricing during a second confirmation pass.", "No cached-input rate is published for gpt-3.5-turbo on the current pricing page; cachedInput is intentionally omitted rather than guessed.", "OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date."] }
|
|
1081
|
+
],
|
|
1082
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1083
|
+
},
|
|
1084
|
+
{
|
|
1085
|
+
canonicalId: "gpt-4.1",
|
|
1086
|
+
provider: "openai",
|
|
1087
|
+
aliases: [],
|
|
1088
|
+
family: "gpt-4.1",
|
|
1089
|
+
pricing: [
|
|
1090
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "2.00", "output": "8.00", "cachedInput": "0.50", "batchMultiplier": "0.5", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ["OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier reflects OpenAI's general Batch API policy as stated on the pricing page; not independently confirmed per-model."] }
|
|
1091
|
+
],
|
|
1092
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1093
|
+
},
|
|
1094
|
+
{
|
|
1095
|
+
canonicalId: "gpt-4.1-mini",
|
|
1096
|
+
provider: "openai",
|
|
1097
|
+
aliases: [],
|
|
1098
|
+
family: "gpt-4.1",
|
|
1099
|
+
pricing: [
|
|
1100
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.40", "output": "1.60", "cachedInput": "0.10", "batchMultiplier": "0.5", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ["OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier reflects OpenAI's general Batch API policy as stated on the pricing page; not independently confirmed per-model."] }
|
|
1101
|
+
],
|
|
1102
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1103
|
+
},
|
|
1104
|
+
{
|
|
1105
|
+
canonicalId: "gpt-4.1-nano",
|
|
1106
|
+
provider: "openai",
|
|
1107
|
+
aliases: [],
|
|
1108
|
+
family: "gpt-4.1",
|
|
1109
|
+
pricing: [
|
|
1110
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.10", "output": "0.40", "cachedInput": "0.025", "batchMultiplier": "0.5", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ["OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier reflects OpenAI's general Batch API policy as stated on the pricing page; not independently confirmed per-model."] }
|
|
1111
|
+
],
|
|
1112
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1113
|
+
},
|
|
1114
|
+
{
|
|
1115
|
+
canonicalId: "gpt-4o",
|
|
1116
|
+
provider: "openai",
|
|
1117
|
+
aliases: [],
|
|
1118
|
+
family: "gpt-4o",
|
|
1119
|
+
pricing: [
|
|
1120
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "2.50", "output": "10.00", "cachedInput": "1.25", "batchMultiplier": "0.5", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ["OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier reflects OpenAI's general Batch API policy as stated on the pricing page; not independently confirmed per-model."] }
|
|
1121
|
+
],
|
|
1122
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1123
|
+
},
|
|
1124
|
+
{
|
|
1125
|
+
canonicalId: "gpt-4o-mini",
|
|
1126
|
+
provider: "openai",
|
|
1127
|
+
aliases: [],
|
|
1128
|
+
family: "gpt-4o",
|
|
1129
|
+
pricing: [
|
|
1130
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.15", "output": "0.60", "cachedInput": "0.075", "batchMultiplier": "0.5", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ["OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier reflects OpenAI's general Batch API policy as stated on the pricing page; not independently confirmed per-model."] }
|
|
1131
|
+
],
|
|
1132
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1133
|
+
},
|
|
1134
|
+
{
|
|
1135
|
+
canonicalId: "gpt-5",
|
|
1136
|
+
provider: "openai",
|
|
1137
|
+
aliases: [],
|
|
1138
|
+
family: "gpt-5",
|
|
1139
|
+
pricing: [
|
|
1140
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.25", "output": "10.00", "cachedInput": "0.125", "batchMultiplier": "0.5", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ["OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier reflects OpenAI's general Batch API policy as stated on the pricing page; not independently confirmed per-model.", "Lead-supplied verified table (observed 2026-08-05) matches this rate exactly; independently re-confirmed against https://developers.openai.com/api/docs/pricing on the same date."] }
|
|
1141
|
+
],
|
|
1142
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1143
|
+
},
|
|
1144
|
+
{
|
|
1145
|
+
canonicalId: "gpt-5-mini",
|
|
1146
|
+
provider: "openai",
|
|
1147
|
+
aliases: [],
|
|
1148
|
+
family: "gpt-5",
|
|
1149
|
+
pricing: [
|
|
1150
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.25", "output": "2.00", "cachedInput": "0.025", "batchMultiplier": "0.5", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ["OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier reflects OpenAI's general Batch API policy as stated on the pricing page; not independently confirmed per-model."] }
|
|
1151
|
+
],
|
|
1152
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1153
|
+
},
|
|
1154
|
+
{
|
|
1155
|
+
canonicalId: "gpt-5-nano",
|
|
1156
|
+
provider: "openai",
|
|
1157
|
+
aliases: [],
|
|
1158
|
+
family: "gpt-5",
|
|
1159
|
+
pricing: [
|
|
1160
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.05", "output": "0.40", "cachedInput": "0.005", "batchMultiplier": "0.5", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ["OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier reflects OpenAI's general Batch API policy as stated on the pricing page; not independently confirmed per-model."] }
|
|
1161
|
+
],
|
|
1162
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1163
|
+
},
|
|
1164
|
+
{
|
|
1165
|
+
canonicalId: "gpt-5-pro",
|
|
1166
|
+
provider: "openai",
|
|
1167
|
+
aliases: [],
|
|
1168
|
+
family: "gpt-5",
|
|
1169
|
+
pricing: [
|
|
1170
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "15.00", "output": "120.00", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ['No cached-input rate is published for gpt-5-pro (shown as "\u2014"); cachedInput is intentionally omitted rather than guessed.', "OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier is intentionally omitted for this pro-tier model; not independently confirmed to apply."] }
|
|
1171
|
+
],
|
|
1172
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1173
|
+
},
|
|
1174
|
+
{
|
|
1175
|
+
canonicalId: "gpt-5.1",
|
|
1176
|
+
provider: "openai",
|
|
1177
|
+
aliases: [],
|
|
1178
|
+
family: "gpt-5.1",
|
|
1179
|
+
pricing: [
|
|
1180
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.25", "output": "10.00", "cachedInput": "0.125", "batchMultiplier": "0.5", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ["OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier reflects OpenAI's general Batch API policy as stated on the pricing page; not independently confirmed per-model."] }
|
|
1181
|
+
],
|
|
1182
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1183
|
+
},
|
|
1184
|
+
{
|
|
1185
|
+
canonicalId: "gpt-5.2",
|
|
1186
|
+
provider: "openai",
|
|
1187
|
+
aliases: [],
|
|
1188
|
+
family: "gpt-5.2",
|
|
1189
|
+
pricing: [
|
|
1190
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.75", "output": "14.00", "cachedInput": "0.175", "batchMultiplier": "0.5", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ["OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier reflects OpenAI's general Batch API policy as stated on the pricing page; not independently confirmed per-model."] }
|
|
1191
|
+
],
|
|
1192
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1193
|
+
},
|
|
1194
|
+
{
|
|
1195
|
+
canonicalId: "gpt-5.2-pro",
|
|
1196
|
+
provider: "openai",
|
|
1197
|
+
aliases: [],
|
|
1198
|
+
family: "gpt-5.2",
|
|
1199
|
+
pricing: [
|
|
1200
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "21.00", "output": "168.00", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ['No cached-input rate is published for gpt-5.2-pro (shown as "\u2014"); cachedInput is intentionally omitted rather than guessed.', "OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier is intentionally omitted for this pro-tier model; not independently confirmed to apply."] }
|
|
1201
|
+
],
|
|
1202
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1203
|
+
},
|
|
1204
|
+
{
|
|
1205
|
+
canonicalId: "gpt-5.4",
|
|
1206
|
+
provider: "openai",
|
|
1207
|
+
aliases: [],
|
|
1208
|
+
family: "gpt-5.4",
|
|
1209
|
+
pricing: [
|
|
1210
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "2.50", "output": "15.00", "cachedInput": "0.25", "batchMultiplier": "0.5", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ["OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier reflects OpenAI's general Batch API policy as stated on the pricing page; not independently confirmed per-model."] }
|
|
1211
|
+
],
|
|
1212
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1213
|
+
},
|
|
1214
|
+
{
|
|
1215
|
+
canonicalId: "gpt-5.4-mini",
|
|
1216
|
+
provider: "openai",
|
|
1217
|
+
aliases: [],
|
|
1218
|
+
family: "gpt-5.4",
|
|
1219
|
+
pricing: [
|
|
1220
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.75", "output": "4.50", "cachedInput": "0.075", "batchMultiplier": "0.5", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ["OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier reflects OpenAI's general Batch API policy as stated on the pricing page; not independently confirmed per-model."] }
|
|
1221
|
+
],
|
|
1222
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1223
|
+
},
|
|
1224
|
+
{
|
|
1225
|
+
canonicalId: "gpt-5.4-nano",
|
|
1226
|
+
provider: "openai",
|
|
1227
|
+
aliases: [],
|
|
1228
|
+
family: "gpt-5.4",
|
|
1229
|
+
pricing: [
|
|
1230
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.20", "output": "1.25", "cachedInput": "0.02", "batchMultiplier": "0.5", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ["OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier reflects OpenAI's general Batch API policy as stated on the pricing page; not independently confirmed per-model."] }
|
|
1231
|
+
],
|
|
1232
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1233
|
+
},
|
|
1234
|
+
{
|
|
1235
|
+
canonicalId: "gpt-5.4-pro",
|
|
1236
|
+
provider: "openai",
|
|
1237
|
+
aliases: [],
|
|
1238
|
+
family: "gpt-5.4",
|
|
1239
|
+
pricing: [
|
|
1240
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "30.00", "output": "180.00", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ['No cached-input rate is published for gpt-5.4-pro (shown as "\u2014"); cachedInput is intentionally omitted rather than guessed.', "OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier is intentionally omitted for this pro-tier model; not independently confirmed to apply."] }
|
|
1241
|
+
],
|
|
1242
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1243
|
+
},
|
|
1244
|
+
{
|
|
1245
|
+
canonicalId: "gpt-5.5",
|
|
1246
|
+
provider: "openai",
|
|
1247
|
+
aliases: [],
|
|
1248
|
+
family: "gpt-5.5",
|
|
1249
|
+
pricing: [
|
|
1250
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "5.00", "output": "30.00", "cachedInput": "0.50", "batchMultiplier": "0.5", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ["OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier reflects OpenAI's general Batch API policy as stated on the pricing page; not independently confirmed per-model."] }
|
|
1251
|
+
],
|
|
1252
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1253
|
+
},
|
|
1254
|
+
{
|
|
1255
|
+
canonicalId: "gpt-5.5-pro",
|
|
1256
|
+
provider: "openai",
|
|
1257
|
+
aliases: [],
|
|
1258
|
+
family: "gpt-5.5",
|
|
1259
|
+
pricing: [
|
|
1260
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "30.00", "output": "180.00", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ['No cached-input rate is published for gpt-5.5-pro (shown as "\u2014" on the pricing page); cachedInput is intentionally omitted rather than guessed.', "OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", `batchMultiplier is intentionally omitted for this pro-tier model: the pricing page's blanket "50% off Batch" statement was not independently confirmed to apply to the -pro tier, unlike the base tiers.`] }
|
|
1261
|
+
],
|
|
1262
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1263
|
+
},
|
|
1264
|
+
{
|
|
1265
|
+
canonicalId: "gpt-5.6-luna",
|
|
1266
|
+
provider: "openai",
|
|
1267
|
+
aliases: [],
|
|
1268
|
+
family: "gpt-5.6",
|
|
1269
|
+
pricing: [
|
|
1270
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.20", "output": "1.20", "cachedInput": "0.02", "batchMultiplier": "0.5", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ["OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier reflects OpenAI's general Batch API policy as stated on the pricing page; not independently confirmed per-model."] }
|
|
1271
|
+
],
|
|
1272
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1273
|
+
},
|
|
1274
|
+
{
|
|
1275
|
+
canonicalId: "gpt-5.6-sol",
|
|
1276
|
+
provider: "openai",
|
|
1277
|
+
aliases: [],
|
|
1278
|
+
family: "gpt-5.6",
|
|
1279
|
+
pricing: [
|
|
1280
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "5.00", "output": "30.00", "cachedInput": "0.50", "batchMultiplier": "0.5", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": [`OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date (this model's naming implies a later release, but a conservative too-early effectiveFrom only ever makes a historical lookup succeed when it should return "no period found", never the reverse).`, `batchMultiplier reflects OpenAI's general Batch API policy ("a 50% discount to Standard pricing rates across all models") as stated on the pricing page; not independently confirmed per-model.`] }
|
|
1281
|
+
],
|
|
1282
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1283
|
+
},
|
|
1284
|
+
{
|
|
1285
|
+
canonicalId: "gpt-5.6-terra",
|
|
1286
|
+
provider: "openai",
|
|
1287
|
+
aliases: [],
|
|
1288
|
+
family: "gpt-5.6",
|
|
1289
|
+
pricing: [
|
|
1290
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "2.00", "output": "12.00", "cachedInput": "0.20", "batchMultiplier": "0.5", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ["OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier reflects OpenAI's general Batch API policy as stated on the pricing page; not independently confirmed per-model."] }
|
|
1291
|
+
],
|
|
1292
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1293
|
+
},
|
|
1294
|
+
{
|
|
1295
|
+
canonicalId: "o1",
|
|
1296
|
+
provider: "openai",
|
|
1297
|
+
aliases: [],
|
|
1298
|
+
family: "o-series",
|
|
1299
|
+
pricing: [
|
|
1300
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "15.00", "output": "60.00", "cachedInput": "7.50", "batchMultiplier": "0.5", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ["OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier reflects OpenAI's general Batch API policy as stated on the pricing page; not independently confirmed per-model."] }
|
|
1301
|
+
],
|
|
1302
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1303
|
+
},
|
|
1304
|
+
{
|
|
1305
|
+
canonicalId: "o1-pro",
|
|
1306
|
+
provider: "openai",
|
|
1307
|
+
aliases: [],
|
|
1308
|
+
family: "o-series",
|
|
1309
|
+
pricing: [
|
|
1310
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "150.00", "output": "600.00", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ["Found on https://developers.openai.com/api/docs/pricing during a second confirmation pass.", 'No cached-input rate is published for o1-pro (shown as "\u2014"); cachedInput is intentionally omitted rather than guessed.', "OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier is intentionally omitted for this pro-tier model; not independently confirmed to apply."] }
|
|
1311
|
+
],
|
|
1312
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1313
|
+
},
|
|
1314
|
+
{
|
|
1315
|
+
canonicalId: "o3",
|
|
1316
|
+
provider: "openai",
|
|
1317
|
+
aliases: [],
|
|
1318
|
+
family: "o-series",
|
|
1319
|
+
pricing: [
|
|
1320
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "2.00", "output": "8.00", "cachedInput": "0.50", "batchMultiplier": "0.5", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ["OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier reflects OpenAI's general Batch API policy as stated on the pricing page; not independently confirmed per-model."] }
|
|
1321
|
+
],
|
|
1322
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1323
|
+
},
|
|
1324
|
+
{
|
|
1325
|
+
canonicalId: "o3-mini",
|
|
1326
|
+
provider: "openai",
|
|
1327
|
+
aliases: [],
|
|
1328
|
+
family: "o-series",
|
|
1329
|
+
pricing: [
|
|
1330
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.10", "output": "4.40", "cachedInput": "0.55", "batchMultiplier": "0.5", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ["OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier reflects OpenAI's general Batch API policy as stated on the pricing page; not independently confirmed per-model."] }
|
|
1331
|
+
],
|
|
1332
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1333
|
+
},
|
|
1334
|
+
{
|
|
1335
|
+
canonicalId: "o3-pro",
|
|
1336
|
+
provider: "openai",
|
|
1337
|
+
aliases: [],
|
|
1338
|
+
family: "o-series",
|
|
1339
|
+
pricing: [
|
|
1340
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "20.00", "output": "80.00", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ['No cached-input rate is published for o3-pro (shown as "\u2014"); cachedInput is intentionally omitted rather than guessed.', "OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier is intentionally omitted for this pro-tier model; not independently confirmed to apply."] }
|
|
1341
|
+
],
|
|
1342
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1343
|
+
},
|
|
1344
|
+
{
|
|
1345
|
+
canonicalId: "o4-mini",
|
|
1346
|
+
provider: "openai",
|
|
1347
|
+
aliases: [],
|
|
1348
|
+
family: "o-series",
|
|
1349
|
+
pricing: [
|
|
1350
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.10", "output": "4.40", "cachedInput": "0.275", "batchMultiplier": "0.5", "sourceUrl": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05", "notes": ["OpenAI's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01 pending confirmation of the true rollout date.", "batchMultiplier reflects OpenAI's general Batch API policy as stated on the pricing page; not independently confirmed per-model."] }
|
|
1351
|
+
],
|
|
1352
|
+
source: { "url": "https://developers.openai.com/api/docs/pricing", "observedAt": "2026-08-05" }
|
|
1353
|
+
},
|
|
1354
|
+
{
|
|
1355
|
+
canonicalId: "anthropic/claude-sonnet-5",
|
|
1356
|
+
provider: "openrouter",
|
|
1357
|
+
aliases: [],
|
|
1358
|
+
family: "anthropic-proxy",
|
|
1359
|
+
pricing: [
|
|
1360
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "2.00", "output": "10.00", "sourceUrl": "https://openrouter.ai/anthropic/claude-sonnet-5", "observedAt": "2026-08-05", "notes": ["UNCERTAIN \u2014 flagged explicitly: this rate ($2.00/$10.00) matches Anthropic's own INTRODUCTORY rate for claude-sonnet-5, which anthropic.json records as expiring 2026-08-31 and being replaced by a $3.00/$15.00 standard rate from 2026-09-01 (see anthropic.json). It is not clear from the OpenRouter page alone whether OpenRouter (a) has simply not yet updated its listing to the post-introductory rate, (b) is genuinely offering a different long-term rate than Anthropic's own API, or (c) this reflects a caching/rounding artifact in the page. Recorded as fetched and observed on 2026-08-05, but a follow-up reviewer should re-check this specific model close to and after 2026-09-01.", "OpenRouter's per-model page does not publish an effective date; effectiveFrom is set conservatively to 2026-01-01.", `canonicalId uses OpenRouter's own slug format, deliberately distinct from Anthropic's first-party canonicalId "claude-sonnet-5" (anthropic.json) to avoid a canonicalId collision; this is a legitimate cross-provider situation, not an error.`] }
|
|
1361
|
+
],
|
|
1362
|
+
source: { "url": "https://openrouter.ai/anthropic/claude-sonnet-5", "observedAt": "2026-08-05" }
|
|
1363
|
+
},
|
|
1364
|
+
{
|
|
1365
|
+
canonicalId: "google/gemini-3.1-pro-preview",
|
|
1366
|
+
provider: "openrouter",
|
|
1367
|
+
aliases: [],
|
|
1368
|
+
family: "google-proxy",
|
|
1369
|
+
pricing: [
|
|
1370
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "2.00", "output": "12.00", "cheapestTier": true, "sourceUrl": "https://openrouter.ai/google/gemini-3.1-pro-preview", "observedAt": "2026-08-05", "notes": ["OpenRouter's per-model page does not publish an effective date; effectiveFrom is set conservatively to 2026-01-01.", "Matches Google's own first-party <=200k-token-tier rate for gemini-3.1-pro-preview ($2.00/$12.00, see google.json) exactly as observed. Google's >200k-token tier ($4.00/$18.00) is not represented here (or, evidently, distinguished by OpenRouter's listing either) \u2014 same context-length-tiering limitation as google.json.", `canonicalId uses OpenRouter's own slug format, deliberately distinct from Google's first-party canonicalId "gemini-3.1-pro-preview" (google.json).`] }
|
|
1371
|
+
],
|
|
1372
|
+
source: { "url": "https://openrouter.ai/google/gemini-3.1-pro-preview", "observedAt": "2026-08-05" }
|
|
1373
|
+
},
|
|
1374
|
+
{
|
|
1375
|
+
canonicalId: "meta-llama/llama-3.3-70b-instruct",
|
|
1376
|
+
provider: "openrouter",
|
|
1377
|
+
aliases: [],
|
|
1378
|
+
family: "meta-proxy",
|
|
1379
|
+
pricing: [
|
|
1380
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.10", "output": "0.32", "sourceUrl": "https://openrouter.ai/meta-llama/llama-3.3-70b-instruct", "observedAt": "2026-08-05", "notes": ["OpenRouter's per-model page does not publish an effective date; effectiveFrom is set conservatively to 2026-01-01.", `Meta does not sell first-party API access to Llama, so there is no first-party "llama-3.3-70b" entry in this registry to compare against; Groq (groq.json: llama-3.3-70b-versatile, $0.59/$0.79) and Together AI (together.json: llama-3.3-70b, $1.04/$1.04) each host the same open-weight model at their own, different rates. OpenRouter's rate here is the lowest of the three observed, plausibly because OpenRouter itself proxies to one of several underlying hosts and shows a blended/lowest-cost route; not independently confirmed which underlying host this routes to.`] }
|
|
1381
|
+
],
|
|
1382
|
+
source: { "url": "https://openrouter.ai/meta-llama/llama-3.3-70b-instruct", "observedAt": "2026-08-05" }
|
|
1383
|
+
},
|
|
1384
|
+
{
|
|
1385
|
+
canonicalId: "openai/gpt-5",
|
|
1386
|
+
provider: "openrouter",
|
|
1387
|
+
aliases: [],
|
|
1388
|
+
family: "openai-proxy",
|
|
1389
|
+
pricing: [
|
|
1390
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.25", "output": "10.00", "sourceUrl": "https://openrouter.ai/openai/gpt-5", "observedAt": "2026-08-05", "notes": ["OpenRouter's per-model page does not publish an effective date; effectiveFrom is set conservatively to 2026-01-01.", "Matches OpenAI's own first-party rate for gpt-5 ($1.25/$10.00, see openai.json) exactly as observed \u2014 no markup detected for this model.", `canonicalId uses OpenRouter's own slug format ("openai/gpt-5"), deliberately distinct from OpenAI's first-party canonicalId "gpt-5" (openai.json) \u2014 this avoids a canonicalId collision while still allowing a cross-provider alias collision if a caller looks up the bare id "gpt-5" without a provider qualifier; no bare "gpt-5" alias was added to this entry to keep that surface area minimal.`] }
|
|
1391
|
+
],
|
|
1392
|
+
source: { "url": "https://openrouter.ai/openai/gpt-5", "observedAt": "2026-08-05" }
|
|
1393
|
+
},
|
|
1394
|
+
{
|
|
1395
|
+
canonicalId: "deepseek-v4-pro",
|
|
1396
|
+
provider: "together",
|
|
1397
|
+
aliases: [],
|
|
1398
|
+
family: "deepseek",
|
|
1399
|
+
pricing: [
|
|
1400
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.74", "output": "3.48", "cachedInput": "0.20", "sourceUrl": "https://www.together.ai/pricing", "observedAt": "2026-08-05", "notes": ["Together's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01."] }
|
|
1401
|
+
],
|
|
1402
|
+
source: { "url": "https://www.together.ai/pricing", "observedAt": "2026-08-05" }
|
|
1403
|
+
},
|
|
1404
|
+
{
|
|
1405
|
+
canonicalId: "gemma-4-31b",
|
|
1406
|
+
provider: "together",
|
|
1407
|
+
aliases: [],
|
|
1408
|
+
family: "gemma",
|
|
1409
|
+
pricing: [
|
|
1410
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.39", "output": "0.97", "sourceUrl": "https://www.together.ai/pricing", "observedAt": "2026-08-05", "notes": ["Together's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01.", 'Cross-provider alias/canonicalId collision (allowed, not an error): AWS Bedrock also lists "Gemma 4 31B" (aws-bedrock.json: gemma-4-31b) at a different, lower rate ($0.14/$0.40 as observed on Bedrock) \u2014 same underlying Google open-weight model, independently priced by each reseller; do not assume parity.'] }
|
|
1411
|
+
],
|
|
1412
|
+
source: { "url": "https://www.together.ai/pricing", "observedAt": "2026-08-05" }
|
|
1413
|
+
},
|
|
1414
|
+
{
|
|
1415
|
+
canonicalId: "glm-5.2",
|
|
1416
|
+
provider: "together",
|
|
1417
|
+
aliases: [],
|
|
1418
|
+
family: "glm",
|
|
1419
|
+
pricing: [
|
|
1420
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.40", "output": "4.40", "cachedInput": "0.26", "sourceUrl": "https://www.together.ai/pricing", "observedAt": "2026-08-05", "notes": ["Together's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01."] }
|
|
1421
|
+
],
|
|
1422
|
+
source: { "url": "https://www.together.ai/pricing", "observedAt": "2026-08-05" }
|
|
1423
|
+
},
|
|
1424
|
+
{
|
|
1425
|
+
canonicalId: "gpt-oss-120b",
|
|
1426
|
+
provider: "together",
|
|
1427
|
+
aliases: [],
|
|
1428
|
+
family: "gpt-oss",
|
|
1429
|
+
pricing: [
|
|
1430
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.15", "output": "0.60", "sourceUrl": "https://www.together.ai/pricing", "observedAt": "2026-08-05", "notes": ["Together's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01.", 'Cross-provider alias/canonicalId collision (allowed, not an error): Groq also publishes a model with canonicalId "gpt-oss-120b" (groq.json), independently priced at the same $0.15/$0.60 figure as observed. The identical string "gpt-oss-120b" is used as the canonicalId on both providers because that is the actual model name each provider publishes; resolving "gpt-oss-120b" without a provider qualifier is ambiguous across providers by design and the resolver requires a provider qualifier to disambiguate it.'] }
|
|
1431
|
+
],
|
|
1432
|
+
source: { "url": "https://www.together.ai/pricing", "observedAt": "2026-08-05" }
|
|
1433
|
+
},
|
|
1434
|
+
{
|
|
1435
|
+
canonicalId: "gpt-oss-20b",
|
|
1436
|
+
provider: "together",
|
|
1437
|
+
aliases: [],
|
|
1438
|
+
family: "gpt-oss",
|
|
1439
|
+
pricing: [
|
|
1440
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.05", "output": "0.20", "sourceUrl": "https://www.together.ai/pricing", "observedAt": "2026-08-05", "notes": ["Together's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01.", 'Cross-provider alias/canonicalId collision (allowed, not an error): Groq also publishes "gpt-oss-20b" (groq.json) at a different rate ($0.075/$0.30 as observed) \u2014 same model name, independently priced by each host; do not assume parity.'] }
|
|
1441
|
+
],
|
|
1442
|
+
source: { "url": "https://www.together.ai/pricing", "observedAt": "2026-08-05" }
|
|
1443
|
+
},
|
|
1444
|
+
{
|
|
1445
|
+
canonicalId: "kimi-k3",
|
|
1446
|
+
provider: "together",
|
|
1447
|
+
aliases: [],
|
|
1448
|
+
family: "kimi",
|
|
1449
|
+
pricing: [
|
|
1450
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "3.00", "output": "15.00", "cachedInput": "0.30", "sourceUrl": "https://www.together.ai/pricing", "observedAt": "2026-08-05", "notes": ["Together's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01."] }
|
|
1451
|
+
],
|
|
1452
|
+
source: { "url": "https://www.together.ai/pricing", "observedAt": "2026-08-05" }
|
|
1453
|
+
},
|
|
1454
|
+
{
|
|
1455
|
+
canonicalId: "llama-3.3-70b",
|
|
1456
|
+
provider: "together",
|
|
1457
|
+
aliases: [],
|
|
1458
|
+
family: "llama-3.3",
|
|
1459
|
+
pricing: [
|
|
1460
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.04", "output": "1.04", "sourceUrl": "https://www.together.ai/pricing", "observedAt": "2026-08-05", "notes": ["Together's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01.", "Also hosted by Groq (groq.json: llama-3.3-70b-versatile, $0.59/$0.79) and resold by AWS Bedrock \u2014 each host prices this same open-weight model independently; do not assume parity across providers."] }
|
|
1461
|
+
],
|
|
1462
|
+
source: { "url": "https://www.together.ai/pricing", "observedAt": "2026-08-05" }
|
|
1463
|
+
},
|
|
1464
|
+
{
|
|
1465
|
+
canonicalId: "minimax-m3",
|
|
1466
|
+
provider: "together",
|
|
1467
|
+
aliases: [],
|
|
1468
|
+
family: "minimax",
|
|
1469
|
+
pricing: [
|
|
1470
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.30", "output": "1.20", "cachedInput": "0.06", "sourceUrl": "https://www.together.ai/pricing", "observedAt": "2026-08-05", "notes": ["Together's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01."] }
|
|
1471
|
+
],
|
|
1472
|
+
source: { "url": "https://www.together.ai/pricing", "observedAt": "2026-08-05" }
|
|
1473
|
+
},
|
|
1474
|
+
{
|
|
1475
|
+
canonicalId: "qwen3.5-397b-a17b",
|
|
1476
|
+
provider: "together",
|
|
1477
|
+
aliases: [],
|
|
1478
|
+
family: "qwen",
|
|
1479
|
+
pricing: [
|
|
1480
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "0.60", "output": "3.60", "cachedInput": "0.35", "sourceUrl": "https://www.together.ai/pricing", "observedAt": "2026-08-05", "notes": ["Together's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01."] }
|
|
1481
|
+
],
|
|
1482
|
+
source: { "url": "https://www.together.ai/pricing", "observedAt": "2026-08-05" }
|
|
1483
|
+
},
|
|
1484
|
+
{
|
|
1485
|
+
canonicalId: "qwen3.7-max",
|
|
1486
|
+
provider: "together",
|
|
1487
|
+
aliases: [],
|
|
1488
|
+
family: "qwen",
|
|
1489
|
+
pricing: [
|
|
1490
|
+
{ "effectiveFrom": "2026-01-01", "currency": "USD", "unit": "per-million-tokens", "input": "1.25", "output": "3.75", "cachedInput": "0.13", "sourceUrl": "https://www.together.ai/pricing", "observedAt": "2026-08-05", "notes": ["Together's pricing page does not publish an effective date for this rate; effectiveFrom is set conservatively to 2026-01-01."] }
|
|
1491
|
+
],
|
|
1492
|
+
source: { "url": "https://www.together.ai/pricing", "observedAt": "2026-08-05" }
|
|
1493
|
+
}
|
|
1494
|
+
];
|
|
1495
|
+
|
|
1496
|
+
// src/errors.ts
|
|
1497
|
+
var NoPricingPeriodError = class extends Error {
|
|
1498
|
+
code = "NO_PRICING_PERIOD";
|
|
1499
|
+
canonicalModel;
|
|
1500
|
+
provider;
|
|
1501
|
+
at;
|
|
1502
|
+
constructor(canonicalModel, provider, at) {
|
|
1503
|
+
super(
|
|
1504
|
+
`No pricing period for "${provider}:${canonicalModel}" covers ${at}. Either the requested date precedes every known period for this model, or the model has no pricing data at all.`
|
|
1505
|
+
);
|
|
1506
|
+
this.name = "NoPricingPeriodError";
|
|
1507
|
+
this.canonicalModel = canonicalModel;
|
|
1508
|
+
this.provider = provider;
|
|
1509
|
+
this.at = at;
|
|
1510
|
+
}
|
|
1511
|
+
};
|
|
1512
|
+
var InvalidUsageError = class extends Error {
|
|
1513
|
+
code = "INVALID_USAGE";
|
|
1514
|
+
constructor(reason) {
|
|
1515
|
+
super(
|
|
1516
|
+
`Invalid usage: ${reason} Pass an LlmUsage object ({ inputTokens, outputTokens, ... }), or normalize a raw provider response first with normalizeOpenAIUsage/normalizeAnthropicUsage/normalizeGoogleUsage/normalizeOpenAICompatibleUsage.`
|
|
1517
|
+
);
|
|
1518
|
+
this.name = "InvalidUsageError";
|
|
1519
|
+
}
|
|
1520
|
+
};
|
|
1521
|
+
var InvalidTokenCountError = class extends Error {
|
|
1522
|
+
code = "INVALID_TOKEN_COUNT";
|
|
1523
|
+
field;
|
|
1524
|
+
value;
|
|
1525
|
+
constructor(field, value) {
|
|
1526
|
+
super(
|
|
1527
|
+
`usage.${field} must be a non-negative safe integer, received ${String(value)}. Negative, fractional, or unsafely large token counts are rejected rather than silently coerced.`
|
|
1528
|
+
);
|
|
1529
|
+
this.name = "InvalidTokenCountError";
|
|
1530
|
+
this.field = field;
|
|
1531
|
+
this.value = value;
|
|
1532
|
+
}
|
|
1533
|
+
};
|
|
1534
|
+
var InvalidRateError = class extends Error {
|
|
1535
|
+
code = "INVALID_RATE";
|
|
1536
|
+
field;
|
|
1537
|
+
value;
|
|
1538
|
+
constructor(field, value) {
|
|
1539
|
+
super(
|
|
1540
|
+
`Pricing field "${field}" must be a non-negative decimal string (e.g. "3.00"), received ${JSON.stringify(value)}.`
|
|
1541
|
+
);
|
|
1542
|
+
this.name = "InvalidRateError";
|
|
1543
|
+
this.field = field;
|
|
1544
|
+
this.value = value;
|
|
1545
|
+
}
|
|
1546
|
+
};
|
|
1547
|
+
|
|
1548
|
+
// src/fixed-point.ts
|
|
1549
|
+
var ZERO = { numerator: 0n, scale: 0 };
|
|
1550
|
+
var DECIMAL_PATTERN = /^\d+(\.\d+)?$/;
|
|
1551
|
+
function parseDecimalRate(value, field) {
|
|
1552
|
+
if (!DECIMAL_PATTERN.test(value)) {
|
|
1553
|
+
throw new InvalidRateError(field, value);
|
|
1554
|
+
}
|
|
1555
|
+
const dot = value.indexOf(".");
|
|
1556
|
+
if (dot === -1) {
|
|
1557
|
+
return { numerator: BigInt(value), scale: 0 };
|
|
1558
|
+
}
|
|
1559
|
+
const wholePart = value.slice(0, dot);
|
|
1560
|
+
const fractionPart = value.slice(dot + 1);
|
|
1561
|
+
return { numerator: BigInt(wholePart + fractionPart), scale: fractionPart.length };
|
|
1562
|
+
}
|
|
1563
|
+
var PER_MILLION_SCALE = 6;
|
|
1564
|
+
function costOfTokens(tokens, rate) {
|
|
1565
|
+
return {
|
|
1566
|
+
numerator: BigInt(tokens) * rate.numerator,
|
|
1567
|
+
scale: rate.scale + PER_MILLION_SCALE
|
|
1568
|
+
};
|
|
1569
|
+
}
|
|
1570
|
+
function multiplyExact(a, b) {
|
|
1571
|
+
return { numerator: a.numerator * b.numerator, scale: a.scale + b.scale };
|
|
1572
|
+
}
|
|
1573
|
+
function addExact(amounts) {
|
|
1574
|
+
if (amounts.length === 0) return ZERO;
|
|
1575
|
+
let maxScale = 0;
|
|
1576
|
+
for (const amount of amounts) if (amount.scale > maxScale) maxScale = amount.scale;
|
|
1577
|
+
let sum = 0n;
|
|
1578
|
+
for (const amount of amounts) {
|
|
1579
|
+
sum += amount.numerator * 10n ** BigInt(maxScale - amount.scale);
|
|
1580
|
+
}
|
|
1581
|
+
return { numerator: sum, scale: maxScale };
|
|
1582
|
+
}
|
|
1583
|
+
function formatExact(amount) {
|
|
1584
|
+
const negative = amount.numerator < 0n;
|
|
1585
|
+
const magnitude = negative ? -amount.numerator : amount.numerator;
|
|
1586
|
+
const divisor = 10n ** BigInt(amount.scale);
|
|
1587
|
+
const integerPart = amount.scale === 0 ? magnitude : magnitude / divisor;
|
|
1588
|
+
const fractionDigits = amount.scale === 0 ? "" : (magnitude % divisor).toString().padStart(amount.scale, "0");
|
|
1589
|
+
let trimmed = fractionDigits.replace(/0+$/, "");
|
|
1590
|
+
if (trimmed.length < 2) trimmed = trimmed.padEnd(2, "0");
|
|
1591
|
+
return `${negative ? "-" : ""}${integerPart.toString()}.${trimmed}`;
|
|
1592
|
+
}
|
|
1593
|
+
function toDisplayNumber(amount) {
|
|
1594
|
+
return Number(formatExact(amount));
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
// src/warnings.ts
|
|
1598
|
+
function unsupportedUsageFieldWarning(field) {
|
|
1599
|
+
return {
|
|
1600
|
+
code: "UNSUPPORTED_USAGE_FIELD",
|
|
1601
|
+
field,
|
|
1602
|
+
message: `usage field "${field}" is not recognized and was not priced. It is preserved here rather than silently discarded \u2014 if this represents billable tokens, report it under a known LlmUsage field.`
|
|
1603
|
+
};
|
|
1604
|
+
}
|
|
1605
|
+
function cachedExceedsInputWarning(inputTokens, subsetTotal) {
|
|
1606
|
+
return {
|
|
1607
|
+
code: "CACHED_EXCEEDS_INPUT",
|
|
1608
|
+
field: "cachedInputTokens",
|
|
1609
|
+
message: `cachedInputTokens + cacheWriteTokens (${String(subsetTotal)}) exceeds inputTokens (${String(inputTokens)}). Ordinary billable input was clamped to 0 rather than going negative; the reported cached/cache-write token counts were still billed in full.`
|
|
1610
|
+
};
|
|
1611
|
+
}
|
|
1612
|
+
function reasoningExceedsOutputWarning(outputTokens, reasoningTokens) {
|
|
1613
|
+
return {
|
|
1614
|
+
code: "REASONING_EXCEEDS_OUTPUT",
|
|
1615
|
+
field: "reasoningTokens",
|
|
1616
|
+
message: `reasoningTokens (${String(reasoningTokens)}) exceeds outputTokens (${String(outputTokens)}). Ordinary billable output was clamped to 0 rather than going negative; the reported reasoning token count was still billed in full.`
|
|
1617
|
+
};
|
|
1618
|
+
}
|
|
1619
|
+
function batchPricingUnavailableWarning(canonicalModel, provider) {
|
|
1620
|
+
return {
|
|
1621
|
+
code: "BATCH_PRICING_UNAVAILABLE",
|
|
1622
|
+
message: `mode: 'batch' was requested but "${provider}:${canonicalModel}"'s resolved pricing period publishes no batchMultiplier. Standard (non-batch) rates were used instead \u2014 this is the higher of the two prices, so the calculation never under-reports.`
|
|
1623
|
+
};
|
|
1624
|
+
}
|
|
1625
|
+
function partialTierPricingWarning(canonicalModel, provider) {
|
|
1626
|
+
return {
|
|
1627
|
+
code: "PARTIAL_TIER_PRICING",
|
|
1628
|
+
message: `"${provider}:${canonicalModel}"'s recorded rate is the cheapest of several published pricing tiers for this model (e.g. prompt size, deployment region, context length, or service tier \u2014 see the registry entry's notes for which). Real usage billed under a different tier will cost more than this calculation reports.`
|
|
1629
|
+
};
|
|
1630
|
+
}
|
|
1631
|
+
function reasoningPricedAsOutputWarning(canonicalModel, provider) {
|
|
1632
|
+
return {
|
|
1633
|
+
code: "REASONING_PRICED_AS_OUTPUT",
|
|
1634
|
+
field: "reasoningTokens",
|
|
1635
|
+
message: `"${provider}:${canonicalModel}" reported reasoning tokens but its pricing period publishes no dedicated reasoning rate. Billed at the output rate instead of being dropped, so the calculation never under-reports \u2014 but the real reasoning-token rate, if the provider publishes one, may differ.`
|
|
1636
|
+
};
|
|
1637
|
+
}
|
|
1638
|
+
function cachedInputPricedAsInputWarning(canonicalModel, provider) {
|
|
1639
|
+
return {
|
|
1640
|
+
code: "CACHED_INPUT_PRICED_AS_INPUT",
|
|
1641
|
+
field: "cachedInputTokens",
|
|
1642
|
+
message: `"${provider}:${canonicalModel}" reported cached input tokens but its pricing period publishes no dedicated cachedInput rate. Billed at the ordinary input rate instead of being dropped \u2014 the real cached rate, almost always cheaper, is not reflected, so this calculation may over-report for this line, never under-report.`
|
|
1643
|
+
};
|
|
1644
|
+
}
|
|
1645
|
+
function cacheWritePricedAsInputWarning(canonicalModel, provider) {
|
|
1646
|
+
return {
|
|
1647
|
+
code: "CACHE_WRITE_PRICED_AS_INPUT",
|
|
1648
|
+
field: "cacheWriteTokens",
|
|
1649
|
+
message: `"${provider}:${canonicalModel}" reported cache-write tokens but its pricing period publishes no dedicated cacheWrite rate. Billed at the ordinary input rate instead of being dropped \u2014 the real cache-write rate, usually a premium over input, is not reflected, so this calculation may under-report for this line.`
|
|
1650
|
+
};
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1653
|
+
// src/normalize/support.ts
|
|
1654
|
+
function isPlainObject(value) {
|
|
1655
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1656
|
+
}
|
|
1657
|
+
function assertUsageObject(value, adapterName) {
|
|
1658
|
+
if (!isPlainObject(value)) {
|
|
1659
|
+
throw new InvalidUsageError(`${adapterName} expected an object, received ${typeof value}.`);
|
|
1660
|
+
}
|
|
1661
|
+
return value;
|
|
1662
|
+
}
|
|
1663
|
+
function isValidTokenCount(value) {
|
|
1664
|
+
return typeof value === "number" && Number.isFinite(value) && Number.isInteger(value) && value >= 0;
|
|
1665
|
+
}
|
|
1666
|
+
function describeValue(value) {
|
|
1667
|
+
if (typeof value === "bigint") return `${value.toString()}n`;
|
|
1668
|
+
if (typeof value === "symbol") return value.toString();
|
|
1669
|
+
if (typeof value === "function") {
|
|
1670
|
+
return value.name.length > 0 ? `[Function: ${value.name}]` : "[Function (anonymous)]";
|
|
1671
|
+
}
|
|
1672
|
+
if (typeof value === "undefined") return "undefined";
|
|
1673
|
+
if (typeof value === "number") {
|
|
1674
|
+
if (Number.isNaN(value)) return "NaN";
|
|
1675
|
+
if (!Number.isFinite(value)) return String(value);
|
|
1676
|
+
if (Object.is(value, -0)) return "-0";
|
|
1677
|
+
return String(value);
|
|
1678
|
+
}
|
|
1679
|
+
try {
|
|
1680
|
+
const json = JSON.stringify(value);
|
|
1681
|
+
return json === void 0 ? String(value) : json;
|
|
1682
|
+
} catch {
|
|
1683
|
+
return Object.prototype.toString.call(value);
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
function describeInvalidNumber(value) {
|
|
1687
|
+
if (typeof value !== "number") return `${typeof value} ${describeValue(value)}`;
|
|
1688
|
+
if (Number.isNaN(value)) return "NaN";
|
|
1689
|
+
if (!Number.isFinite(value)) return String(value);
|
|
1690
|
+
if (!Number.isInteger(value)) return `a fractional value (${value})`;
|
|
1691
|
+
return `a negative value (${value})`;
|
|
1692
|
+
}
|
|
1693
|
+
function readNumber(obj, key, adapterName) {
|
|
1694
|
+
const value = obj[key];
|
|
1695
|
+
if (value === void 0 || value === null) return void 0;
|
|
1696
|
+
if (!isValidTokenCount(value)) {
|
|
1697
|
+
throw new InvalidUsageError(
|
|
1698
|
+
`${adapterName} expected "${key}" to be a non-negative integer, received ${describeInvalidNumber(value)}.`
|
|
1699
|
+
);
|
|
1700
|
+
}
|
|
1701
|
+
return value;
|
|
1702
|
+
}
|
|
1703
|
+
function readNestedNumber(obj, parentKey, key, adapterName) {
|
|
1704
|
+
const parent = obj[parentKey];
|
|
1705
|
+
if (parent === void 0 || parent === null) return void 0;
|
|
1706
|
+
if (!isPlainObject(parent)) {
|
|
1707
|
+
throw new InvalidUsageError(
|
|
1708
|
+
`${adapterName} expected "${parentKey}" to be an object, received ${typeof parent}.`
|
|
1709
|
+
);
|
|
1710
|
+
}
|
|
1711
|
+
return readNumber(parent, key, adapterName);
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
// src/normalize/generic.ts
|
|
1715
|
+
var KNOWN_FIELDS = /* @__PURE__ */ new Set([
|
|
1716
|
+
"inputTokens",
|
|
1717
|
+
"outputTokens",
|
|
1718
|
+
"cachedInputTokens",
|
|
1719
|
+
"cacheWriteTokens",
|
|
1720
|
+
"reasoningTokens"
|
|
1721
|
+
]);
|
|
1722
|
+
function readNumericField(obj, key) {
|
|
1723
|
+
const raw = obj[key];
|
|
1724
|
+
if (raw === void 0 || raw === null) return void 0;
|
|
1725
|
+
if (typeof raw !== "number") {
|
|
1726
|
+
throw new InvalidUsageError(
|
|
1727
|
+
`expected "${key}" to be a number, received ${typeof raw} ${describeValue(raw)}.`
|
|
1728
|
+
);
|
|
1729
|
+
}
|
|
1730
|
+
return raw;
|
|
1731
|
+
}
|
|
1732
|
+
function normalizeRequestUsage(value) {
|
|
1733
|
+
if (!isPlainObject(value)) {
|
|
1734
|
+
throw new InvalidUsageError(`expected an object, received ${typeof value}.`);
|
|
1735
|
+
}
|
|
1736
|
+
const inputTokens = readNumericField(value, "inputTokens");
|
|
1737
|
+
const outputTokens = readNumericField(value, "outputTokens");
|
|
1738
|
+
if (inputTokens === void 0 || outputTokens === void 0) {
|
|
1739
|
+
throw new InvalidUsageError(
|
|
1740
|
+
'expected numeric "inputTokens" and "outputTokens" fields, found none.'
|
|
1741
|
+
);
|
|
1742
|
+
}
|
|
1743
|
+
const cachedInputTokens = readNumericField(value, "cachedInputTokens");
|
|
1744
|
+
const cacheWriteTokens = readNumericField(value, "cacheWriteTokens");
|
|
1745
|
+
const reasoningTokens = readNumericField(value, "reasoningTokens");
|
|
1746
|
+
const usage = {
|
|
1747
|
+
inputTokens,
|
|
1748
|
+
outputTokens,
|
|
1749
|
+
...cachedInputTokens !== void 0 ? { cachedInputTokens } : {},
|
|
1750
|
+
...cacheWriteTokens !== void 0 ? { cacheWriteTokens } : {},
|
|
1751
|
+
...reasoningTokens !== void 0 ? { reasoningTokens } : {}
|
|
1752
|
+
};
|
|
1753
|
+
const warnings = [];
|
|
1754
|
+
for (const key of Object.keys(value)) {
|
|
1755
|
+
if (!KNOWN_FIELDS.has(key)) warnings.push(unsupportedUsageFieldWarning(key));
|
|
1756
|
+
}
|
|
1757
|
+
return { usage, warnings };
|
|
1758
|
+
}
|
|
1759
|
+
|
|
1760
|
+
// src/pricing-period.ts
|
|
1761
|
+
function selectPeriodOrThrow(descriptor, at) {
|
|
1762
|
+
const period = selectPricingPeriod(descriptor.pricing ?? [], at, {
|
|
1763
|
+
canonicalId: descriptor.canonicalId,
|
|
1764
|
+
provider: descriptor.provider
|
|
1765
|
+
});
|
|
1766
|
+
if (period === void 0) {
|
|
1767
|
+
const atLabel = at instanceof Date ? at.toISOString() : at;
|
|
1768
|
+
throw new NoPricingPeriodError(descriptor.canonicalId, descriptor.provider, atLabel);
|
|
1769
|
+
}
|
|
1770
|
+
return period;
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1773
|
+
// src/resolve-model.ts
|
|
1774
|
+
function resolveModel2(model, options = {}) {
|
|
1775
|
+
const registry = options.registry ?? MODEL_REGISTRY;
|
|
1776
|
+
return resolveModel(model, registry, {
|
|
1777
|
+
provider: options.provider,
|
|
1778
|
+
overrides: options.overrides,
|
|
1779
|
+
fallback: options.fallback
|
|
1780
|
+
});
|
|
1781
|
+
}
|
|
1782
|
+
|
|
1783
|
+
// src/calculate-cost.ts
|
|
1784
|
+
function assertSafeNonNegativeInteger(field, value) {
|
|
1785
|
+
if (!Number.isInteger(value) || !Number.isSafeInteger(value) || value < 0) {
|
|
1786
|
+
throw new InvalidTokenCountError(field, value);
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1789
|
+
function validateUsage(usage) {
|
|
1790
|
+
assertSafeNonNegativeInteger("inputTokens", usage.inputTokens);
|
|
1791
|
+
assertSafeNonNegativeInteger("outputTokens", usage.outputTokens);
|
|
1792
|
+
if (usage.cachedInputTokens !== void 0) {
|
|
1793
|
+
assertSafeNonNegativeInteger("cachedInputTokens", usage.cachedInputTokens);
|
|
1794
|
+
}
|
|
1795
|
+
if (usage.cacheWriteTokens !== void 0) {
|
|
1796
|
+
assertSafeNonNegativeInteger("cacheWriteTokens", usage.cacheWriteTokens);
|
|
1797
|
+
}
|
|
1798
|
+
if (usage.reasoningTokens !== void 0) {
|
|
1799
|
+
assertSafeNonNegativeInteger("reasoningTokens", usage.reasoningTokens);
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
function buildCostLine(tokens, rate) {
|
|
1803
|
+
const exact = costOfTokens(tokens, rate);
|
|
1804
|
+
return {
|
|
1805
|
+
line: {
|
|
1806
|
+
tokens,
|
|
1807
|
+
rate: formatExact(rate),
|
|
1808
|
+
costUsd: toDisplayNumber(exact),
|
|
1809
|
+
costUsdExact: formatExact(exact)
|
|
1810
|
+
},
|
|
1811
|
+
exact
|
|
1812
|
+
};
|
|
1813
|
+
}
|
|
1814
|
+
function calculateCost(request, options = {}) {
|
|
1815
|
+
const registry = options.registry ?? MODEL_REGISTRY;
|
|
1816
|
+
const provider = request.provider ?? options.provider;
|
|
1817
|
+
const resolved = resolveModel2(request.model, {
|
|
1818
|
+
provider,
|
|
1819
|
+
overrides: options.overrides,
|
|
1820
|
+
fallback: options.fallback,
|
|
1821
|
+
registry
|
|
1822
|
+
});
|
|
1823
|
+
const descriptor = resolved.descriptor;
|
|
1824
|
+
const at = request.at ?? /* @__PURE__ */ new Date();
|
|
1825
|
+
const period = selectPeriodOrThrow(descriptor, at);
|
|
1826
|
+
const { usage, warnings: usageWarnings } = normalizeRequestUsage(request.usage);
|
|
1827
|
+
validateUsage(usage);
|
|
1828
|
+
const warnings = [...usageWarnings];
|
|
1829
|
+
let batchAmount;
|
|
1830
|
+
if (request.mode === "batch") {
|
|
1831
|
+
if (period.batchMultiplier !== void 0) {
|
|
1832
|
+
batchAmount = parseDecimalRate(period.batchMultiplier, "batchMultiplier");
|
|
1833
|
+
} else {
|
|
1834
|
+
warnings.push(batchPricingUnavailableWarning(descriptor.canonicalId, descriptor.provider));
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
function effectiveRate(rateStr, field) {
|
|
1838
|
+
const rate = parseDecimalRate(rateStr, field);
|
|
1839
|
+
return batchAmount === void 0 ? rate : multiplyExact(rate, batchAmount);
|
|
1840
|
+
}
|
|
1841
|
+
const cachedInputTokens = usage.cachedInputTokens ?? 0;
|
|
1842
|
+
const cacheWriteTokens = usage.cacheWriteTokens ?? 0;
|
|
1843
|
+
const inputSubsetTotal = cachedInputTokens + cacheWriteTokens;
|
|
1844
|
+
let ordinaryInputTokens = usage.inputTokens - inputSubsetTotal;
|
|
1845
|
+
if (ordinaryInputTokens < 0) {
|
|
1846
|
+
warnings.push(cachedExceedsInputWarning(usage.inputTokens, inputSubsetTotal));
|
|
1847
|
+
ordinaryInputTokens = 0;
|
|
1848
|
+
}
|
|
1849
|
+
const reasoningTokens = usage.reasoningTokens ?? 0;
|
|
1850
|
+
let ordinaryOutputTokens = usage.outputTokens - reasoningTokens;
|
|
1851
|
+
if (ordinaryOutputTokens < 0) {
|
|
1852
|
+
warnings.push(reasoningExceedsOutputWarning(usage.outputTokens, reasoningTokens));
|
|
1853
|
+
ordinaryOutputTokens = 0;
|
|
1854
|
+
}
|
|
1855
|
+
const inputRate = effectiveRate(period.input, "input");
|
|
1856
|
+
const outputRate = effectiveRate(period.output, "output");
|
|
1857
|
+
const inputLine = buildCostLine(ordinaryInputTokens, inputRate);
|
|
1858
|
+
const outputLine = buildCostLine(ordinaryOutputTokens, outputRate);
|
|
1859
|
+
const lineAmounts = [inputLine.exact, outputLine.exact];
|
|
1860
|
+
let cachedInputLine;
|
|
1861
|
+
if (usage.cachedInputTokens !== void 0) {
|
|
1862
|
+
let rate;
|
|
1863
|
+
if (period.cachedInput !== void 0) {
|
|
1864
|
+
rate = effectiveRate(period.cachedInput, "cachedInput");
|
|
1865
|
+
} else {
|
|
1866
|
+
rate = inputRate;
|
|
1867
|
+
if (cachedInputTokens > 0) {
|
|
1868
|
+
warnings.push(cachedInputPricedAsInputWarning(descriptor.canonicalId, descriptor.provider));
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
const built = buildCostLine(cachedInputTokens, rate);
|
|
1872
|
+
cachedInputLine = built.line;
|
|
1873
|
+
lineAmounts.push(built.exact);
|
|
1874
|
+
}
|
|
1875
|
+
let cacheWriteLine;
|
|
1876
|
+
if (usage.cacheWriteTokens !== void 0) {
|
|
1877
|
+
let rate;
|
|
1878
|
+
if (period.cacheWrite !== void 0) {
|
|
1879
|
+
rate = effectiveRate(period.cacheWrite, "cacheWrite");
|
|
1880
|
+
} else {
|
|
1881
|
+
rate = inputRate;
|
|
1882
|
+
if (cacheWriteTokens > 0) {
|
|
1883
|
+
warnings.push(cacheWritePricedAsInputWarning(descriptor.canonicalId, descriptor.provider));
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
const built = buildCostLine(cacheWriteTokens, rate);
|
|
1887
|
+
cacheWriteLine = built.line;
|
|
1888
|
+
lineAmounts.push(built.exact);
|
|
1889
|
+
}
|
|
1890
|
+
let reasoningLine;
|
|
1891
|
+
if (usage.reasoningTokens !== void 0) {
|
|
1892
|
+
let rate;
|
|
1893
|
+
if (period.reasoning !== void 0) {
|
|
1894
|
+
rate = effectiveRate(period.reasoning, "reasoning");
|
|
1895
|
+
} else {
|
|
1896
|
+
rate = outputRate;
|
|
1897
|
+
if (reasoningTokens > 0) {
|
|
1898
|
+
warnings.push(reasoningPricedAsOutputWarning(descriptor.canonicalId, descriptor.provider));
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
const built = buildCostLine(reasoningTokens, rate);
|
|
1902
|
+
reasoningLine = built.line;
|
|
1903
|
+
lineAmounts.push(built.exact);
|
|
1904
|
+
}
|
|
1905
|
+
if (period.cheapestTier === true) {
|
|
1906
|
+
warnings.push(partialTierPricingWarning(descriptor.canonicalId, descriptor.provider));
|
|
1907
|
+
}
|
|
1908
|
+
const total = addExact(lineAmounts);
|
|
1909
|
+
const totalUsdExact = formatExact(total);
|
|
1910
|
+
const totalUsd = toDisplayNumber(total);
|
|
1911
|
+
return {
|
|
1912
|
+
model: request.model,
|
|
1913
|
+
canonicalModel: descriptor.canonicalId,
|
|
1914
|
+
provider: descriptor.provider,
|
|
1915
|
+
matchedBy: resolved.matchedBy,
|
|
1916
|
+
...resolved.requestedProvider !== void 0 ? { requestedProvider: resolved.requestedProvider } : {},
|
|
1917
|
+
currency: "USD",
|
|
1918
|
+
input: inputLine.line,
|
|
1919
|
+
output: outputLine.line,
|
|
1920
|
+
...cachedInputLine !== void 0 ? { cachedInput: cachedInputLine } : {},
|
|
1921
|
+
...cacheWriteLine !== void 0 ? { cacheWrite: cacheWriteLine } : {},
|
|
1922
|
+
...reasoningLine !== void 0 ? { reasoning: reasoningLine } : {},
|
|
1923
|
+
totalUsd,
|
|
1924
|
+
totalUsdExact,
|
|
1925
|
+
registryVersion: REGISTRY_VERSION,
|
|
1926
|
+
pricingEffectiveFrom: period.effectiveFrom,
|
|
1927
|
+
warnings
|
|
1928
|
+
};
|
|
1929
|
+
}
|
|
1930
|
+
|
|
1931
|
+
// src/calculator.ts
|
|
1932
|
+
function createPriceCalculator(defaults = {}) {
|
|
1933
|
+
return {
|
|
1934
|
+
calculateCost(request, options = {}) {
|
|
1935
|
+
return calculateCost(request, {
|
|
1936
|
+
overrides: options.overrides ?? defaults.overrides,
|
|
1937
|
+
fallback: options.fallback ?? defaults.fallback,
|
|
1938
|
+
registry: options.registry ?? defaults.registry,
|
|
1939
|
+
provider: options.provider
|
|
1940
|
+
});
|
|
1941
|
+
},
|
|
1942
|
+
resolveModel(model, options = {}) {
|
|
1943
|
+
return resolveModel2(model, {
|
|
1944
|
+
overrides: options.overrides ?? defaults.overrides,
|
|
1945
|
+
fallback: options.fallback ?? defaults.fallback,
|
|
1946
|
+
registry: options.registry ?? defaults.registry,
|
|
1947
|
+
provider: options.provider
|
|
1948
|
+
});
|
|
1949
|
+
}
|
|
1950
|
+
};
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
// src/overrides.ts
|
|
1954
|
+
function createPriceOverride(input) {
|
|
1955
|
+
const effectiveFrom = input.effectiveFrom ?? "1970-01-01";
|
|
1956
|
+
const period = {
|
|
1957
|
+
effectiveFrom,
|
|
1958
|
+
...input.effectiveTo !== void 0 ? { effectiveTo: input.effectiveTo } : {},
|
|
1959
|
+
currency: "USD",
|
|
1960
|
+
unit: "per-million-tokens",
|
|
1961
|
+
input: input.input,
|
|
1962
|
+
output: input.output,
|
|
1963
|
+
...input.cachedInput !== void 0 ? { cachedInput: input.cachedInput } : {},
|
|
1964
|
+
...input.cacheWrite !== void 0 ? { cacheWrite: input.cacheWrite } : {},
|
|
1965
|
+
...input.reasoning !== void 0 ? { reasoning: input.reasoning } : {},
|
|
1966
|
+
...input.batchMultiplier !== void 0 ? { batchMultiplier: input.batchMultiplier } : {},
|
|
1967
|
+
sourceUrl: input.sourceUrl ?? "urn:usage-tab:custom-override",
|
|
1968
|
+
observedAt: input.observedAt ?? effectiveFrom,
|
|
1969
|
+
...input.notes !== void 0 ? { notes: input.notes } : {}
|
|
1970
|
+
};
|
|
1971
|
+
return {
|
|
1972
|
+
canonicalId: input.canonicalId,
|
|
1973
|
+
// `ModelDescriptor.provider` is typed `ProviderId` for registry source
|
|
1974
|
+
// data (schema-validated against the baseline provider list); an
|
|
1975
|
+
// override is not registry source data, and `resolveModel` never checks
|
|
1976
|
+
// this field against `PROVIDER_IDS` at runtime, so a negotiated deal
|
|
1977
|
+
// with an unlisted vendor is free to use any label here.
|
|
1978
|
+
provider: input.provider ?? "custom",
|
|
1979
|
+
aliases: input.aliases ?? [],
|
|
1980
|
+
...input.family !== void 0 ? { family: input.family } : {},
|
|
1981
|
+
...input.contextWindow !== void 0 ? { contextWindow: input.contextWindow } : {},
|
|
1982
|
+
pricing: [period]
|
|
1983
|
+
};
|
|
1984
|
+
}
|
|
1985
|
+
|
|
1986
|
+
// src/normalize/openai.ts
|
|
1987
|
+
var KNOWN_TOP_LEVEL = /* @__PURE__ */ new Set([
|
|
1988
|
+
"prompt_tokens",
|
|
1989
|
+
"completion_tokens",
|
|
1990
|
+
"input_tokens",
|
|
1991
|
+
"output_tokens",
|
|
1992
|
+
"total_tokens",
|
|
1993
|
+
"prompt_tokens_details",
|
|
1994
|
+
"completion_tokens_details",
|
|
1995
|
+
"input_tokens_details",
|
|
1996
|
+
"output_tokens_details"
|
|
1997
|
+
]);
|
|
1998
|
+
var KNOWN_DETAIL_FIELDS = /* @__PURE__ */ new Set([
|
|
1999
|
+
"cached_tokens",
|
|
2000
|
+
"reasoning_tokens",
|
|
2001
|
+
"audio_tokens",
|
|
2002
|
+
"accepted_prediction_tokens",
|
|
2003
|
+
"rejected_prediction_tokens"
|
|
2004
|
+
]);
|
|
2005
|
+
function normalizeOpenAIUsage(value) {
|
|
2006
|
+
const obj = assertUsageObject(value, "normalizeOpenAIUsage");
|
|
2007
|
+
const adapterName = "normalizeOpenAIUsage";
|
|
2008
|
+
const inputTokens = readNumber(obj, "prompt_tokens", adapterName) ?? readNumber(obj, "input_tokens", adapterName);
|
|
2009
|
+
const outputTokens = readNumber(obj, "completion_tokens", adapterName) ?? readNumber(obj, "output_tokens", adapterName);
|
|
2010
|
+
if (inputTokens === void 0 || outputTokens === void 0) {
|
|
2011
|
+
throw new InvalidUsageError(
|
|
2012
|
+
'normalizeOpenAIUsage expected numeric "prompt_tokens"/"completion_tokens" (Chat Completions) or "input_tokens"/"output_tokens" (Responses API).'
|
|
2013
|
+
);
|
|
2014
|
+
}
|
|
2015
|
+
const cachedInputTokens = readNestedNumber(obj, "prompt_tokens_details", "cached_tokens", adapterName) ?? readNestedNumber(obj, "input_tokens_details", "cached_tokens", adapterName);
|
|
2016
|
+
const reasoningTokens = readNestedNumber(obj, "completion_tokens_details", "reasoning_tokens", adapterName) ?? readNestedNumber(obj, "output_tokens_details", "reasoning_tokens", adapterName);
|
|
2017
|
+
const usage = {
|
|
2018
|
+
inputTokens,
|
|
2019
|
+
outputTokens,
|
|
2020
|
+
...cachedInputTokens !== void 0 ? { cachedInputTokens } : {},
|
|
2021
|
+
...reasoningTokens !== void 0 ? { reasoningTokens } : {}
|
|
2022
|
+
};
|
|
2023
|
+
const warnings = [];
|
|
2024
|
+
for (const key of Object.keys(obj)) {
|
|
2025
|
+
if (!KNOWN_TOP_LEVEL.has(key)) warnings.push(unsupportedUsageFieldWarning(key));
|
|
2026
|
+
}
|
|
2027
|
+
for (const detailKey of [
|
|
2028
|
+
"prompt_tokens_details",
|
|
2029
|
+
"completion_tokens_details",
|
|
2030
|
+
"input_tokens_details",
|
|
2031
|
+
"output_tokens_details"
|
|
2032
|
+
]) {
|
|
2033
|
+
const details = obj[detailKey];
|
|
2034
|
+
if (!isPlainObject(details)) continue;
|
|
2035
|
+
for (const key of Object.keys(details)) {
|
|
2036
|
+
if (!KNOWN_DETAIL_FIELDS.has(key))
|
|
2037
|
+
warnings.push(unsupportedUsageFieldWarning(`${detailKey}.${key}`));
|
|
2038
|
+
}
|
|
2039
|
+
}
|
|
2040
|
+
return { usage, warnings };
|
|
2041
|
+
}
|
|
2042
|
+
|
|
2043
|
+
// src/normalize/anthropic.ts
|
|
2044
|
+
var KNOWN_TOP_LEVEL2 = /* @__PURE__ */ new Set([
|
|
2045
|
+
"input_tokens",
|
|
2046
|
+
"output_tokens",
|
|
2047
|
+
"cache_creation_input_tokens",
|
|
2048
|
+
"cache_read_input_tokens",
|
|
2049
|
+
"cache_creation"
|
|
2050
|
+
]);
|
|
2051
|
+
var KNOWN_CACHE_CREATION_FIELDS = /* @__PURE__ */ new Set([
|
|
2052
|
+
"ephemeral_5m_input_tokens",
|
|
2053
|
+
"ephemeral_1h_input_tokens"
|
|
2054
|
+
]);
|
|
2055
|
+
function normalizeAnthropicUsage(value) {
|
|
2056
|
+
const obj = assertUsageObject(value, "normalizeAnthropicUsage");
|
|
2057
|
+
const adapterName = "normalizeAnthropicUsage";
|
|
2058
|
+
const baseInputTokens = readNumber(obj, "input_tokens", adapterName);
|
|
2059
|
+
const outputTokens = readNumber(obj, "output_tokens", adapterName);
|
|
2060
|
+
if (baseInputTokens === void 0 || outputTokens === void 0) {
|
|
2061
|
+
throw new InvalidUsageError(
|
|
2062
|
+
'normalizeAnthropicUsage expected numeric "input_tokens" and "output_tokens".'
|
|
2063
|
+
);
|
|
2064
|
+
}
|
|
2065
|
+
const cachedInputTokens = readNumber(obj, "cache_read_input_tokens", adapterName);
|
|
2066
|
+
let cacheWriteTokens = readNumber(obj, "cache_creation_input_tokens", adapterName);
|
|
2067
|
+
const warnings = [];
|
|
2068
|
+
if (obj.cache_creation !== void 0 && obj.cache_creation !== null) {
|
|
2069
|
+
if (!isPlainObject(obj.cache_creation)) {
|
|
2070
|
+
throw new InvalidUsageError(
|
|
2071
|
+
`${adapterName} expected "cache_creation" to be an object, received ${typeof obj.cache_creation}.`
|
|
2072
|
+
);
|
|
2073
|
+
}
|
|
2074
|
+
const creation = obj.cache_creation;
|
|
2075
|
+
if (cacheWriteTokens === void 0) {
|
|
2076
|
+
const fiveMinute = readNumber(creation, "ephemeral_5m_input_tokens", adapterName) ?? 0;
|
|
2077
|
+
const oneHour = readNumber(creation, "ephemeral_1h_input_tokens", adapterName) ?? 0;
|
|
2078
|
+
if (fiveMinute > 0 || oneHour > 0) cacheWriteTokens = fiveMinute + oneHour;
|
|
2079
|
+
}
|
|
2080
|
+
for (const key of Object.keys(creation)) {
|
|
2081
|
+
if (!KNOWN_CACHE_CREATION_FIELDS.has(key)) {
|
|
2082
|
+
warnings.push(unsupportedUsageFieldWarning(`cache_creation.${key}`));
|
|
2083
|
+
}
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
const inputTokens = baseInputTokens + (cachedInputTokens ?? 0) + (cacheWriteTokens ?? 0);
|
|
2087
|
+
const usage = {
|
|
2088
|
+
inputTokens,
|
|
2089
|
+
outputTokens,
|
|
2090
|
+
...cachedInputTokens !== void 0 ? { cachedInputTokens } : {},
|
|
2091
|
+
...cacheWriteTokens !== void 0 ? { cacheWriteTokens } : {}
|
|
2092
|
+
};
|
|
2093
|
+
for (const key of Object.keys(obj)) {
|
|
2094
|
+
if (!KNOWN_TOP_LEVEL2.has(key)) warnings.push(unsupportedUsageFieldWarning(key));
|
|
2095
|
+
}
|
|
2096
|
+
return { usage, warnings };
|
|
2097
|
+
}
|
|
2098
|
+
|
|
2099
|
+
// src/normalize/google.ts
|
|
2100
|
+
var KNOWN_TOP_LEVEL3 = /* @__PURE__ */ new Set([
|
|
2101
|
+
"promptTokenCount",
|
|
2102
|
+
"candidatesTokenCount",
|
|
2103
|
+
"totalTokenCount",
|
|
2104
|
+
"cachedContentTokenCount",
|
|
2105
|
+
"thoughtsTokenCount"
|
|
2106
|
+
]);
|
|
2107
|
+
function normalizeGoogleUsage(value) {
|
|
2108
|
+
const obj = assertUsageObject(value, "normalizeGoogleUsage");
|
|
2109
|
+
const adapterName = "normalizeGoogleUsage";
|
|
2110
|
+
const inputTokens = readNumber(obj, "promptTokenCount", adapterName);
|
|
2111
|
+
const candidatesTokenCount = readNumber(obj, "candidatesTokenCount", adapterName);
|
|
2112
|
+
if (inputTokens === void 0 || candidatesTokenCount === void 0) {
|
|
2113
|
+
throw new InvalidUsageError(
|
|
2114
|
+
'normalizeGoogleUsage expected numeric "promptTokenCount" and "candidatesTokenCount" (Gemini usageMetadata).'
|
|
2115
|
+
);
|
|
2116
|
+
}
|
|
2117
|
+
const cachedInputTokens = readNumber(obj, "cachedContentTokenCount", adapterName);
|
|
2118
|
+
const reasoningTokens = readNumber(obj, "thoughtsTokenCount", adapterName);
|
|
2119
|
+
const outputTokens = candidatesTokenCount + (reasoningTokens ?? 0);
|
|
2120
|
+
const usage = {
|
|
2121
|
+
inputTokens,
|
|
2122
|
+
outputTokens,
|
|
2123
|
+
...cachedInputTokens !== void 0 ? { cachedInputTokens } : {},
|
|
2124
|
+
...reasoningTokens !== void 0 ? { reasoningTokens } : {}
|
|
2125
|
+
};
|
|
2126
|
+
const warnings = [];
|
|
2127
|
+
for (const key of Object.keys(obj)) {
|
|
2128
|
+
if (!KNOWN_TOP_LEVEL3.has(key)) warnings.push(unsupportedUsageFieldWarning(key));
|
|
2129
|
+
}
|
|
2130
|
+
return { usage, warnings };
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
// src/normalize/openai-compatible.ts
|
|
2134
|
+
var KNOWN_TOP_LEVEL4 = /* @__PURE__ */ new Set([
|
|
2135
|
+
"prompt_tokens",
|
|
2136
|
+
"completion_tokens",
|
|
2137
|
+
"total_tokens",
|
|
2138
|
+
"prompt_tokens_details",
|
|
2139
|
+
"completion_tokens_details",
|
|
2140
|
+
"cached_tokens",
|
|
2141
|
+
"prompt_cache_hit_tokens",
|
|
2142
|
+
"prompt_cache_miss_tokens"
|
|
2143
|
+
]);
|
|
2144
|
+
function normalizeOpenAICompatibleUsage(value) {
|
|
2145
|
+
const obj = assertUsageObject(value, "normalizeOpenAICompatibleUsage");
|
|
2146
|
+
const adapterName = "normalizeOpenAICompatibleUsage";
|
|
2147
|
+
const inputTokens = readNumber(obj, "prompt_tokens", adapterName);
|
|
2148
|
+
const outputTokens = readNumber(obj, "completion_tokens", adapterName);
|
|
2149
|
+
if (inputTokens === void 0 || outputTokens === void 0) {
|
|
2150
|
+
throw new InvalidUsageError(
|
|
2151
|
+
'normalizeOpenAICompatibleUsage expected numeric "prompt_tokens" and "completion_tokens".'
|
|
2152
|
+
);
|
|
2153
|
+
}
|
|
2154
|
+
const cachedInputTokens = readNestedNumber(obj, "prompt_tokens_details", "cached_tokens", adapterName) ?? readNumber(obj, "cached_tokens", adapterName) ?? readNumber(obj, "prompt_cache_hit_tokens", adapterName);
|
|
2155
|
+
const reasoningTokens = readNestedNumber(
|
|
2156
|
+
obj,
|
|
2157
|
+
"completion_tokens_details",
|
|
2158
|
+
"reasoning_tokens",
|
|
2159
|
+
adapterName
|
|
2160
|
+
);
|
|
2161
|
+
const usage = {
|
|
2162
|
+
inputTokens,
|
|
2163
|
+
outputTokens,
|
|
2164
|
+
...cachedInputTokens !== void 0 ? { cachedInputTokens } : {},
|
|
2165
|
+
...reasoningTokens !== void 0 ? { reasoningTokens } : {}
|
|
2166
|
+
};
|
|
2167
|
+
const warnings = [];
|
|
2168
|
+
for (const key of Object.keys(obj)) {
|
|
2169
|
+
if (!KNOWN_TOP_LEVEL4.has(key)) warnings.push(unsupportedUsageFieldWarning(key));
|
|
2170
|
+
}
|
|
2171
|
+
return { usage, warnings };
|
|
2172
|
+
}
|
|
2173
|
+
//# sourceMappingURL=index.cjs.map
|