Howwise RSS
AI & Automation9 min read

AI Agent API Calls Increasing but No Revenue: Triage

Short answer

When AI agent API calls are increasing but there is no revenue, the cause is almost always ordinary: a payment provider hold, a failing webhook, a swapped or expired key, or a retry loop. Agents have no motive, so check Stripe, webhooks, then git.

Key takeaways
  • Agents do not sabotage: each run only sees its prompt, files and tools, so a sudden break comes from changed code, config, keys, model behaviour or a provider-side hold.
  • First confirm in the Stripe, PayPal or Paddle dashboard that money is really failing before you touch any code.
  • Check webhook event deliveries for 4xx/5xx errors, a wrong signing secret, a body altered before signature verification or a disabled endpoint, and use git diff against the last good commit to find agent edits.
  • Rising calls with flat revenue usually mean a retry loop or a job that stopped deduplicating, so cap iterations, tokens and monthly spend.
  • A scheduled synthetic test purchase plus alerts on revenue, webhook failures and cost per transaction would catch this within hours.

Why are my AI agent API calls going up while revenue is flat?

An LLM agent has no motive and no memory of your success. Each run sees only its prompt, context window, files and tool outputs. Telling it that your product is doing well cannot make it act against you.

What does change behaviour is concrete: edited files, a different context, a model or version update, or a tool that started failing. Rising API usage with flat revenue is the classic fingerprint of a retry loop, a polling job, an agent re-running a task, or a failing step that is retried endlessly.

So treat this as an incident with a technical cause. The runbook below takes about 30 minutes if you follow the order, because it checks the cheapest and most common causes first.

How do I confirm money is really failing?

Many cases of "payments stopped" are really unreported revenue or a provider-side hold. Do this before reading any code, since it decides whether you have a code problem at all.

  1. Open the Stripe, PayPal or Paddle dashboard and look at the payments list for the last 7 days. Compare failed, succeeded and refunded counts to the previous week.
  2. Look for account-level banners: a verification or identity request, a restricted account, paused payouts, or a reserve placed on your balance.
  3. Check Disputes for a spike. A wave of chargebacks can trigger holds.
  4. Check whether customers are paying but your app does not record it. If the provider shows successes and your database shows none, the fault is in your webhook handling, not in payments.
  5. Check for lapsed cards on your own account (provider fees, subscriptions to hosting) and for an expired or rolled API key.
Tip: Make one test purchase in live mode with a real low-priced item (and refund it) if it is safe to do so. It tells you in two minutes whether checkout, payment and fulfilment each work.

How do I check whether my Stripe webhook is broken?

In the Stripe dashboard go to Developers > Webhooks, open your endpoint and read the event deliveries list. Each delivery shows the HTTP status your server returned.

Match what you see to the cause. A 400 on every event usually means your handler is rejecting the request after signature verification fails, because construct_event raised an error. The common reasons are a wrong signing secret (whsec_...), a secret from the test-mode endpoint used in live mode, or a framework or middleware that parses and re-serialises the JSON so the raw bytes no longer match the signature. Verify against the raw request body, not a parsed object.

A 404 means the route or URL changed. A 500 means your handler crashes. Repeated failures over several days can lead Stripe to disable the endpoint, so check its status too.

Also check idempotency. Stripe retries events, and may deliver the same event more than once, so the handler must record processed event IDs. The order of operations matters: if you fulfil first and record afterwards, a crash between the two steps leaves the order fulfilled but not recorded, and the retry fulfils it a second time.

The fix is to make handling and recording atomic. Write the event ID and your database changes in a single transaction, so either both commit or neither does. For side effects that cannot be rolled back, such as emails or shipments, write an idempotency record with a status (processing, then done) before fulfilling, pass a stable idempotency key to downstream calls, and return a 500 on failure so Stripe retries.

event = stripe.Webhook.construct_event(
    request.get_data(),  # raw bytes, not parsed JSON
    sig_header,
    os.environ["STRIPE_WEBHOOK_SECRET"],
)

with db.transaction():  # one atomic unit: record + fulfil
    # INSERT ... ON CONFLICT DO NOTHING; False if the ID already exists
    if not claim_event(event["id"], status="processing"):
        return "", 200  # duplicate delivery, acknowledge it
    handle(event)  # writes the order in the same transaction
    set_status(event["id"], "done")
# any exception rolls everything back and returns 500, so Stripe retries
return "", 200
Warning: Do not disable signature verification to "get it working". An agent that suggests this is trading a bug for a security hole. Fix the secret or the raw-body handling instead.

How do I find what the agent changed?

Version control is the source of truth. If the project is not in git, run git init and commit the current state now, so the next change is at least visible. Then use the history of the files that matter: checkout, webhook, auth and env config.

Look specifically for edits to price or product IDs, the API version, environment variable names, redirect or success URLs, rate limits, and the webhook route. Also check dependency files for upgrades.

git log --since="10 days ago" --stat --oneline
git diff <last-good-commit> HEAD -- app/checkout app/webhooks config
git blame -L 1,80 app/webhooks/stripe.py
git log -p --since="10 days ago" -- .env.example package.json requirements.txt
# restore one file safely instead of resetting everything:
git restore --source=<last-good-commit> -- app/webhooks/stripe.py
Tip: Read the agent's session transcript or logs too, but treat its summary as a claim. Ask it for facts (files touched, commands run, the failing flow with logs) and verify each against git and dashboards.

Where are the extra AI agent API calls coming from?

Open your LLM or API provider's usage page and break usage down per key, per endpoint and per hour. A step change at a specific hour points to a deploy or a cron change. A steady climb points to a queue that is growing.

Then look at response codes. Many 429s (rate limit), 401s (bad key) or 5xx responses next to repeated identical requests mean a client retrying without backoff. Check your cron, queue or scheduler for a job that stopped deduplicating, so the same item is processed again every run.

Put a hard ceiling on every loop so a failure costs cents instead of hundreds of dollars.

MAX_STEPS, MAX_TOKENS = 8, 40_000
used = 0
for step in range(MAX_STEPS):
    resp = call_model(messages, max_tokens=2_000)
    used += resp.usage.total_tokens
    if resp.done or used > MAX_TOKENS:
        break
else:
    alert("agent hit step limit")
# retries: exponential backoff, max 3 attempts, then fail loudly
Warning: If costs are climbing right now, revoke or pause the key first and investigate after. Stopping the spend is more urgent than finding the cause.

Which silent breakages should I check, and what do they look like?

These are the usual suspects. Many produce no visible error, which is why the break goes unnoticed for days.

Data and labeling products have one more failure mode: schema or format drift. If a field or label is renamed, or a model changes its output format, validation fails and the product can look empty or invalid to buyers, so deliveries and purchases stop. Add schema validation and a sample check on every output batch.

SymptomLikely causeWhere to lookFix
Provider shows no failures, no new paymentsCheckout broken or traffic lostLive test purchase, redirect URLs, domain and SSL expiryRestore the URL or cert, renew the domain
Payments succeed, orders not fulfilledWebhook 400/404/500 or disabled endpointDevelopers > Webhooks > event deliveriesCorrect the signing secret, raw-body handling or route, resend failed events
401 errors, calls climbingExpired or rotated keyProvider usage logs, deploy envIssue a new key, update the environment
Test charges onlyTest and live keys swappedKey prefix sk_test vs sk_live, mode toggleUse live keys in production
Everything broke after a deploy.env overwritten or API version bumpedgit diff on config, dependency filesRestore config, pin the versions
Output rejected by buyers or parserSchema or model format driftValidation logs, sample outputsAdd schema validation, pin the model version
Calls up 10x, errors 429/5xxRetry loop or duplicate jobsUsage per key, endpoint and hour; cron or queueBackoff, idempotency keys, loop caps

How do I put guardrails on AI agents so this cannot repeat silently?

Assume an agent will eventually make a wrong edit, and limit the blast radius. Give it the least privilege that still lets it work, require review, and make failures loud.

Then monitor outcomes rather than activity. A synthetic purchase that runs on a schedule and alerts on failure would have caught this within hours, and a daily cost-per-successful-transaction number shows AI agent API calls decoupling from revenue straight away.

ControlHow to set it up
Least-privilege keysUse Stripe restricted keys with only the permissions needed, read-only where possible; never hand agents the full secret key
Branches and reviewAgents commit to branches or pull requests, you review the diff, and there are no direct production deploys
Protected filesUse CODEOWNERS or branch protection on checkout, webhook, auth and config paths
Spend capsSet a monthly budget and alert thresholds on the LLM provider, plus per-run step and token limits
Environment separationKeep staging in test mode with its own keys and webhook secret
Synthetic testA scheduled test purchase (test mode on staging, or a refunded live one) that pages you on failure
AlertsRevenue per day below a threshold, webhook failure rate, error rate, and cost per transaction above a limit

What mistakes make these incidents worse?

Blaming the AI before checking the payment provider is the most common one, and it wastes the first hour on the wrong layer. Pleading or accusing the agent in a prompt only adds noise to its context and fixes nothing.

The others are structural: letting agents edit production without version control, sharing full-access secret keys, having no spend limits, and changing several things at once while debugging. Change one thing, re-test the flow, and record the result, or you will not know which change worked.

Common questions

Can an AI agent break my payments on purpose?

No. A model has no goals between runs and cannot hold a grudge or retaliate. It can make wrong edits, misread instructions or loop on errors, and these have ordinary traces in git, logs and provider dashboards.

Why did my AI coding agent change my code without asking?

It acts on the task and context it was given, and a broad request such as "fix the checkout error" can lead it to edit related files. Tight scopes, branch-only access, protected paths and a required diff review keep edits visible and reversible.

How do I stop an AI agent running up API costs?

Revoke or pause the key, then set a monthly budget and alerts at the provider. In code, add a maximum step count, a max_tokens limit, and retries with backoff capped at about three attempts.

How do I debug an AI agent pipeline?

Log each step's input, output, status code, token count and run ID, then replay the failing run on a single item. Compare against the last good run, and change one variable at a time.

Can I resend Stripe events that my webhook missed?

Yes. Fix the endpoint first, then resend failed events from the event delivery view in the dashboard, or fetch recent events through the Events API and process them. Your handler must be idempotent, with the event ID recorded atomically alongside fulfilment, so replays do not double-fulfil orders.

Related topics:ai agentsstripe webhooksdebuggingapi costsguardrails