# How do I stop an AI agent from overspending on a paid data API?

> Agents loop, retry and page further than you meant. Budget guardrails for Xiaohongshu, Douyin and other social data calls: free price checks, page caps, prepaid limits.

Canonical page: https://okdata.online/answers/cap-ai-agent-spend-data-api/

**Short answer: **Have the agent price the task before it runs (looking up endpoints and prices on okdata is free), enforce a page cap and a dollar budget in your own code using the charge returned with every call, and retry only failures that are safe to retry. Because the balance is prepaid, the worst case is the balance itself: 500 runaway Xiaohongshu searches would cost $10.00, then calls stop.

The classic overnight bill comes from an agent stuck in a loop: a tool call fails, the agent tries again, pages a little further, tries again, thousands of times. People on the OpenAI forum describe account limits and try/except wrappers that did not stop the charge before it happened. The guardrail has to sit in the code that makes the call, and it has to know what each call cost.

## Four guardrails, cheapest first

1. **Price the task before running it.** Over MCP, the `find` and `describe` tools cost nothing and need no key, and `describe` shows the price of an endpoint. Ask the agent to say "this is about 12 calls, roughly X" before the first paid `call`. Over HTTP, read prices from the endpoint pages, such as [Xiaohongshu note search](/apis/xiaohongshu/notes/search/) or [Douyin video search](/apis/douyin/videos/search/).
2. **Cap pages in code.** Every page is a separate charge. A `max_pages` argument that the model cannot change beats any instruction in the prompt.
3. **Track real spend.** Each response carries `meta.billing.amount`, the exact charge for that call as a decimal string. Add it up and stop when the budget is gone.
4. **Retry only what is worth retrying.** Errors say whether a retry can help (`retry: "yes"`, `"after_fix"`, `"no"`, `"same_key"`). Failed calls are never charged, but a loop of pointless retries still burns time and rate limit.

## What a budget buys

| Budget | Xiaohongshu searches | Douyin searches |
|---|---|---|
| $1.00 | 50 pages | — |
| $1.00 | — | 50 pages |
| Runaway loop, 500 calls | $10.00 | $10.00 |

## A budget wrapper

```python
import os, time, uuid
from decimal import Decimal
import requests

API = "https://api.okdata.online"
H = {"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"}

class Budget:
    def __init__(self, usd: str, max_calls: int):
        self.left = Decimal(usd)
        self.calls_left = max_calls

    def get(self, path: str, **params):
        if self.left <= 0 or self.calls_left <= 0:
            raise RuntimeError("budget used up, stopping")
        key = str(uuid.uuid4())  # one key per logical call, reused on retry
        for _ in range(3):
            body = requests.get(API + path, params=params, timeout=60,
                                headers={**H, "Idempotency-Key": key}).json()
            if body["code"] == "ok":
                self.calls_left -= 1
                self.left -= Decimal(body["meta"]["billing"]["amount"])
                return body
            if body.get("retry") not in ("yes", "same_key"):
                raise RuntimeError(f"{body['code']}: {body['message']}")
            time.sleep(body.get("retry_after_seconds") or 2)
        raise RuntimeError("gave up after 3 tries")

budget = Budget("0.50", max_calls=40)
page = budget.get("/v1/xiaohongshu/notes/search", query="防晒霜", sort="latest")
```

Give the agent `budget.get` as its only way to fetch data. It can overshoot by one call at most, because the check runs before the call.

## The hard stop you already have

okdata is prepaid. When the balance reaches zero, calls fail with `insufficient_balance` and nothing is charged, so no loop can spend more than you topped up. Keep the balance near what a week of normal use needs, and check it any time with `GET /v1/account`. A new key starts with $0.10.

## Other layers worth adding

Agent frameworks have their own brakes: `max_iterations` on a LangChain agent, `recursion_limit` in LangGraph, a step limit in most others. Use them too; they stop runaway reasoning, which also costs model tokens. API gateways with spending rules help when several teams share one key. Billing dashboards and email alerts are useful, but they report after the money is gone. Prices for every endpoint are on the [pricing page](/pricing/), and every error code with its retry advice is on the [errors page](/docs/errors/).

## Endpoints used

- [Xiaohongshu note search](https://okdata.online/apis/xiaohongshu/notes/search/) `xiaohongshu.notes.search`: $0.02 per call · about 20 notes per page
- [Douyin video search](https://okdata.online/apis/douyin/videos/search/) `douyin.videos.search`: $0.02 per call · about 20 videos per page

Updated 2026-11-12
