Overview
This page is the authoritative reference for what every external paid API call in the codebase costs. It has three layers:- The audit — every paid call site, its exact model id, and how it is invoked.
- The pricing — verified per-model rates, pulled from vendor pricing pages.
- The math — per-stage, per-pipeline, and corpus-scale cost projections.
Verified: August 14, 2026. Every model id below was read out of the code on that date; every price was read from the vendor’s own pricing page on that date. Where a number is an estimate rather than a measurement, it is labelled (est.).
The older Cost Tracking page covers the same ground as of July 3, 2026 and also documents fixed monthly subscriptions and Trigger.dev credit budgeting. Where the two disagree on a model or a price, this page is correct — see What changed.
Part 1 — The audit
Model registries
Four files decide which model runs. Change a model here and it changes everywhere.How calls reach a provider
Three distinct mechanisms are in use, and the distinction matters for cost:Vercel AI Gateway
gateway("openai/gpt-5.6-luna") or getModelForFeature(). Zero markup — you pay provider list price. All Luna, and all Claude routed through the API app.Direct provider SDK
anthropic.messages.create() and the GoogleGenAI client. Full list price, no gateway involved. Used by the strain pipeline’s Claude passes, all Gemini image generation, and Lyria.Anthropic Batch API
anthropic.messages.batches.create(). 50% off input and output. Only reachable in the strain pipeline’s batch mode.Paid call sites
Reasoning effort is cost-critical. GPT-5.6 Luna bills reasoning tokens as output ($1.20/1M), and they are invisible in the response. Luna’s provider default is
medium. Every call site below pins an explicit effort — the Effort column is the single biggest per-call cost lever in the codebase.Strain research pipeline
All paths under
packages/trigger/src/. Stage 05 runs direct by default: strain-research-pipeline.ts:62 sets useDirectMode to true, so the 50% Batch discount does not apply to a normal self-serve run.
Other pipelines
Hono API features
No embeddings anywhere. A repo-wide sweep for
embed(, .embeddings., and vector-model ids returns nothing in apps/api/src, packages/trigger/src, or apps/mobile/convex. Similarity and matching are done with SQL and string heuristics, not vectors — so there is $0 embedding spend to account for.getReasoningOptions() returns { openai: { reasoningEffort } }. Non-OpenAI providers ignore the openai key, so it is harmless to spread into a Mistral or Claude call — the medium on the receipt parser has no effect and no cost.Notebook section tiers
A full notebook is 23 sections: 2 computed (free) and 21 AI-billed, resolved throughMODEL_TIERS in apps/api/src/config/ai.ts. Section definitions and their estimatedOutputTokens live in packages/ai-prompts/src/config/section-config.ts.
Things that look paid but are not
gpt-4o-mini-tts — retired, not a live call site
gpt-4o-mini-tts — retired, not a live call site
NOTEBOOK_ARTIFACT_MODEL_IDS in packages/report-contracts/src/artifact-plan.ts:88 still contains 'gpt-4o-mini-tts', and its own comment explains why: notebook narration is retired and no executor references the model. The value survives only because the enum is persisted to notebookArtifacts.executor.modelId and a Zod enum cannot be empty. There is no TTS call anywhere in the codebase — no audio/speech, no ElevenLabs, no .speech. call. This line costs $0.Delisted OpenAI models still in the registry
Delisted OpenAI models still in the registry
MODELS in apps/api/src/config/ai.ts still lists gpt-5, gpt-5-mini, o3, and o4-mini. gpt-5 and gpt-5-mini are annotated in the file as delisted by OpenAI in June 2026. No FEATURE_MODELS entry points at any of them, so none can be reached.Mistral Large / Magistral Medium
Mistral Large / Magistral Medium
Present in
MODELS, referenced by no feature. Note also that magistral-medium-2506 no longer appears on Mistral’s pricing page at all — the medium tier is now Mistral Medium 3.5.SCRAPE_CONFIG.maxUrls is dead config
SCRAPE_CONFIG.maxUrls is dead config
config/pipeline.config.ts declares maxUrls: 15, but tasks/stages/03-scrape.ts never reads it. Every filtered URL is scraped — which is why a ranked strain measures ~36 scrapes, not 15. Budget against the measured number, not the config.Part 2 — Verified pricing
All rates in USD per 1M tokens unless stated otherwise. Read from vendor pricing pages on August 14, 2026.Text and vision models
Image, audio, video
Search, scraping, compute
Checkpointed waits are free. Trigger.dev does not bill compute for any
wait.for / wait.until longer than 5 seconds, which is why a 5-minute pipeline run bills for only ~5 minutes of active machine time.Part 3 — Per-run cost math
Assumptions
Measured from production (not estimates)
Measured from production (not estimates)
- Unranked strain: 25 results searched → 6–16 scraped → 6–16 extractions. 11 used as midpoint.
- Ranked strain: 40 searched → ~36 scraped → ~34 extractions.
- Extraction truncates article content at 50,000 chars ≈ 12,500 tokens per article (
lib/gemini/extraction.ts:30). - Stage timings, typical unranked run (ms): search 3,200 · filter 1,300 · scrape 78,000 · extract 35,000 · process 150,000 · imaging 40,000 · save 1,100.
- Ranked refresh with
skipImaging+skipMusic(ms): search 4,630 · filter 2,055 · scrape 304,735 · extract 76,414 · process 86,625 · imaging 142 · save 1,897. - One paper summary measured at **1,345 in / 649 out = 0.20/$1.20, independently confirming the rate.
- Machine presets read from code: orchestrator
medium-1x; stages 03/04medium-2x; stages 05/06large-1x; stages 01/02/07 defaultsmall-1x.
Estimated (token counts we do not measure)
Estimated (token counts we do not measure)
- Extraction: ~13,300 input tokens/article (12,500 content + ~800 prompt + schema); ~2,000 output tokens/article including
lowreasoning. (est.) - FactFinder: ~12,000 input/pass unranked, ~30,000 ranked; ~2,500 output/pass against a 4,096 cap. (est.)
- Copywriter: ~15,000 input unranked / ~30,000 ranked; ~6,000 output against an 8,192 cap. (est.)
- Image prompts: ~6,000 input; ~2,500 output against a 4,096 cap. (est.)
- Notebook: ~4,000 input tokens per section (order context + strain data + prior sections). (est.)
- A 30% token uplift is applied to all
claude-sonnet-5andclaude-opus-4.8figures for the new tokenizer. - Orchestrator billed at ~10s of active compute; the rest of its wall-clock is checkpointed and free. (est.)
(a) Typical unranked strain — direct mode
(b) Ranked strain — 40 results, direct mode
(c) Ranked refresh — skipImaging + skipMusic
Skipping imaging removes 0.0136 of
large-1x compute — a 26% cut on a ranked run. It is by far the cheapest optimization available, and the right default for any re-research pass where the existing hero and mascot images are still good.Where the money goes
Music pipeline
Auto-fires after research completes unlessskipMusic is set.
Combined per strain
Extrapolations
Cost to research N strains (research + music)
Cost to RE-research the full corpus
Re-research keeps existing images and audio, soskipImaging + skipMusic apply throughout.
Per-unit costs — other pipelines
Notebook breakdown
Could not be priced
What changed since the July page
The headline per-strain number moved less than the underlying changes suggest, because two large moves cancelled: extraction got much cheaper (Luna replaced Flash-Lite) while compute and Exa were both materially undercounted before.
How to update this page
1
Re-read the model registries
These four files are the only places a model id is decided. If a model id changed, every number downstream is wrong.
2
Re-check every reasoningEffort call site
Reasoning tokens bill as output. A call site that loses its explicit effort silently falls back to Luna’s Every hit should either be the definition in
medium default and can multiply that call’s output cost.config/ai.ts or a call site with an explicit effort. A bare generateText against Luna with no providerOptions is a cost bug.3
Re-pull vendor pricing
4
Watch these dated cliffs
- Jan 1, 2027 — Gemini Flash input/output doubles (3.75 → 7.50). Context caching doubles too.
- Sep 1, 2026 — no longer a real price change (Anthropic cancelled it), but
getAnthropicBatchPricing()still thinks it is. Fix that function or every batch-mode cost log overstates by 50%. - Any OpenAI repricing of
gpt-5.6-luna, which moved 80% within three weeks of launch and is the most volatile rate on this page.
5
Re-measure, don't re-estimate
The token counts in Part 3 are estimates. If a run’s real usage is available — Trigger.dev run metadata, an Anthropic
usage block, or an AI Gateway spend report — prefer it and mark the row as measured. The paper-summarizer row is the model: a real 1,345/649 measurement that reproduced the vendor rate exactly.