Quick Answer
AI agents write code that compiles and passes tests. What they don't know is the fine print buried in the provider docs. So the code sails through review and then fails quietly in production, because it's missing an idempotency key, or webhook verification, or some other requirement the AI never read.
The problem: your AI doesn't read the docs
Your Claude Code or Cursor builds integration code by pattern-matching against training data. Ask it to wire up Stripe, Resend, or Firebase and it hands you something that looks finished.
Here's what it quietly skips:
- It doesn't read the whole provider documentation
- It doesn't know about deprecation warnings
- It doesn't grasp "silent failures," where the code runs without erroring but does the wrong thing
- It doesn't know that some API calls do damage if they run twice
So it ships code that:
- Compiles and passes linting
- Has correct types
- Passes unit tests on the happy path
- Looks complete to a human reviewer
- Fails silently in production
And the failure doesn't show up right away. It surfaces weeks later, when a customer gets charged twice, or a webhook fires twice, or an email goes to the wrong domain. By then it's been live long enough that you're firefighting instead of fixing.
The deeper problem: you're testing AI code with AI
You already know AI code can be wrong, so you ask Claude to write tests. But look at what just happened: you asked Claude to write both the code and the tests.
If Claude hallucinated the API call, it very likely hallucinated what to test for too. Now you've got two AI systems nodding along at each other's mistakes, and zero real visibility into what's actually broken.
Real examples: bugs that slip right through
Example 1: idempotency keys
Your AI sends a Resend email with no idempotency key. The network hiccups. The send() call returns, but the request timed out, so your app retries. Resend receives two identical requests, and without a key to tie them together, it sends the email twice.
Your customer just got the same email twice. And if it's a transaction confirmation, they now think they've been charged twice, which is a support ticket you didn't need.
The docs are explicit: for any request that modifies data, send an idempotency-key header, and if a request times out you retry with the same key to get the cached response back. The AI simply never knew.
Example 2: webhook signature verification
Your AI writes a webhook endpoint that trusts req.body. But anyone can send a fake webhook, and your app will process it as if it were real.
The docs say verify the signature before you process anything. The AI saw plenty of webhook code in training, it just never learned that skipping verification is a security hole.
Example 3: Firebase auth timing
Your AI checks auth.currentUser immediately, before Firebase has initialized. So currentUser is null, the component renders the logged-out UI, and by the time Firebase finishes loading, the page is already showing the wrong thing.
The docs spell it out: auth.currentUser stays null until Firebase initializes, so wrap your auth checks in onAuthStateChanged(). The AI has seen Firebase code, it just doesn't know about the timing trap.
How api-doctor catches this
api-doctor runs deterministic AST rules against your code. Same input, same output, every time.
Take the idempotency key case. There's a rule for exactly that:
✗ Resend: 2 issues found
resend-missing-idempotency-key
src/newsletter.ts:5
Missing idempotency-key. Retried requests will send duplicate emails.
Severity: error
Fix: Add headers: { "idempotency-key": crypto.randomUUID() }
It catches these before code review. Before merge. Before production has a chance to bite you.
How to use api-doctor
# Scan your project
npx @api-doctor/cli .
# Install as an agent skill so Claude Code validates its own code
npx @api-doctor/cli install
Now when you ask your agent to integrate with Resend, it writes the code, runs api-doctor against it, sees the error, fixes it on its own, and commits something clean. No human review needed for the known stuff.
Frequently asked questions
Q: Why doesn't my linter catch this?
Linters check syntax (is this valid JavaScript?) and style (do we use semicolons?). api-doctor checks correctness (is this the right API call for the job?). Your linter has no idea that Resend's send() wants an idempotency key.
Q: Can I use api-doctor without an agent?
Yes. Run npx @api-doctor/cli . by hand or drop it into your CI/CD pipeline.
Q: Does api-doctor send my code anywhere? No. It runs locally, your code never leaves your machine, and all the rules are open source.
Q: Will api-doctor catch every bug? No. It catches deterministic bugs, the ones that violate a specific rule. Logic errors and semantic bugs are still yours to own.