Blog / AI agents

AI Agent API Cost Control: Cap Web Data Spend

AI agent API cost control comes down to two numbers: the credits one call costs and the maximum number of calls one run may make. On Perceptlayer a successful call costs the credits shown on its endpoint, which is 1 credit for nearly all of them, and a failed call costs nothing. Multiply calls per run by runs per month, add a hard cap in your own code, and the worst case is known before the agent starts.

Why do agent data costs drift?

Agents decide at run time how many calls a task needs, so the bill depends on model behaviour as much as on traffic. A model that keeps refining a query or loops on an empty result makes more calls than you planned. Per-call pricing is fine. The unbounded loop is the problem, and the fix is a ceiling the loop can't pass.

Prepaid credits help because the account itself has a ceiling. The service is prepaid: purchased credits last 12 months, with no subscription and no seats. When the balance runs out, calls return insufficient_credits (402) and nothing more is debited, so a runaway agent stops at the balance you loaded. A per-run cap keeps one run from eating that whole balance.

How do you calculate credits per agent task?

Count the calls one task needs, multiply by the credits per call, and keep two figures: the typical case and the capped worst case. For endpoints that cost 1 credit, calls and credits are the same number. Check the cost shown on each endpoint you give the agent, because the cap should be in credits if any endpoint costs more than 1.

Take an example agent that answers a research question. Assume it typically makes 8 calls per task and you cap it at 20. These are example figures for the arithmetic, not measurements. Per run, that's 8 credits typical and 20 credits worst case.

Pack Price Credits Cost per 1,000 calls Typical run (8 calls) Capped run (20 calls)
Free tier $0 1,000 per month $0 $0 $0
Starter $10 12,500 $0.80 $0.0064 $0.016
Growth $50 83,000 $0.60 $0.0048 $0.012
Scale $200 400,000 $0.50 $0.004 $0.01

Run counts follow from the credits. The free tier's 1,000 credits cover 125 typical runs (1,000 ÷ 8) or 50 capped runs (1,000 ÷ 20). The Starter pack's 12,500 credits cover 1,562 typical runs or 625 capped runs. At 500 tasks a month, typical spend is 4,000 credits, and the cap bounds the worst case at 10,000 credits, which fits inside the Starter pack's 12,500.

Why don't failed calls count against the budget?

A failed call returns an HTTP status, a JSON error body and the header X-Credits-Used: 0. Only a successful response debits credits. So the retries an agent makes after a rate_limited (429, the status RFC 6585 defines for too many requests) or source_error (502) response don't change the credit total.

Take a run that makes 8 successful calls and hits 3 errors along the way: 8 credits, not 11. The three failed attempts cost nothing in credits. They still cost time and model tokens, so they should count toward a separate attempt cap.

That second cap matters. An agent that retries an invalid_parameters (422) response forever will never be billed for it, and it will never finish either. See the error reference and the rate limit docs.

How do you build AI agent API cost control in code?

Put the cap in the function that executes the agent's tool calls. The wrapper below counts credits and attempts, refuses to send a request that would pass either limit, and raises BudgetExceeded so the agent loop stops and returns what it has. It counts each successful call at the endpoint's listed cost, which you pass in as credits_per_call.

import os
import requests


class BudgetExceeded(Exception):
    pass


class CallBudget:
    def __init__(self, max_credits, max_attempts, credits_per_call=1):
        self.max_credits = max_credits
        self.max_attempts = max_attempts
        self.credits_per_call = credits_per_call
        self.spent = 0
        self.attempts = 0

    def call(self, url, params=None, method="GET"):
        if self.spent + self.credits_per_call > self.max_credits:
            raise BudgetExceeded(f"credit cap reached: {self.spent}/{self.max_credits}")
        if self.attempts >= self.max_attempts:
            raise BudgetExceeded(f"attempt cap reached: {self.attempts}/{self.max_attempts}")

        self.attempts += 1
        try:
            response = requests.request(
                method,
                url,
                params=params,
                headers={"X-API-Key": os.environ["API_KEY"]},
                timeout=30,
            )
        except requests.RequestException as error:
            raise BudgetExceeded(f"request failed, stopping the run: {error}") from error
        if response.status_code == 402:
            raise BudgetExceeded("account is out of credits")
        if response.ok:
            self.spent += self.credits_per_call
        return response

Use one CallBudget per run and hand its call method to the agent as the only way to reach the API.

budget = CallBudget(max_credits=20, max_attempts=30)
url = os.environ["ENDPOINT_URL"]  # copied from the endpoint's page

try:
    response = budget.call(url, params={"q": "example"})
    print(response.status_code, f"{budget.spent} credits spent")
except BudgetExceeded as stop:
    print("stopping the run:", stop)

A timeout or connection error counts as an attempt and ends the run cleanly instead of crashing the loop. The credit count is a local estimate: it adds the endpoint's listed cost for each successful response and doesn't read anything from the response. Treat it as a ceiling check, and compare it with the X-Credits-Remaining header, which every successful response carries with your balance after the call.

Set max_attempts above max_credits so a few free failures can retry, and keep the gap small. Here 20 credits allow 20 successful calls, and the 10 extra attempts allow up to 10 failures before the run stops. See also the requests docs.

What changes when the agent calls through MCP?

The MCP server at https://api.perceptlayer.com/mcp exposes three tools, search_endpoints, get_endpoint and call_endpoint. search_endpoints and get_endpoint only look things up in the catalogue and cost nothing, so call_endpoint is the one tool that needs a budget check. A successful call_endpoint costs the credits shown on its endpoint, failed calls cost nothing, and its result reports the credits used and the balance remaining. The MCP docs cover the tools.

The cap needs your own agent loop, because the loop is where tool calls get executed. Route every call_endpoint the model requests through a budget check, and let the loop stop when it raises. The sketch below assumes your MCP client gives you a function send_call_endpoint(arguments) that runs the tool and returns its result; credits_per_call is the cost listed on the endpoint.

class McpBudget:
    def __init__(self, max_credits, credits_per_call=1):
        self.max_credits = max_credits
        self.credits_per_call = credits_per_call
        self.spent = 0

    def call_endpoint(self, send_call_endpoint, arguments):
        if self.spent + self.credits_per_call > self.max_credits:
            raise BudgetExceeded(f"credit cap reached: {self.spent}/{self.max_credits}")
        try:
            result = send_call_endpoint(arguments)
        except Exception as error:
            raise BudgetExceeded(f"tool call failed, stopping the run: {error}") from error
        if not getattr(result, "isError", False):
            self.spent += self.credits_per_call
        return result

MCP marks a failed tool call with isError in its result (see the MCP tools specification), which is what the wrapper checks before counting credits. In the loop, when the model asks for call_endpoint, call budget.call_endpoint(...) instead of the client directly. Catch BudgetExceeded outside the loop and return what the agent has so far. As with the HTTP wrapper, the credit count is a local estimate, not a figure read from the response.

The related walkthrough, Claude MCP Web Search: Live Results for an Agent, shows the tools in use.

How should you size a balance for an agent?

Size the balance for the capped worst case, then watch the typical case. Take runs per month × cap × credits per call. For 500 runs capped at 20 calls, that's 10,000 credits, which the Starter pack's 12,500 credits cover for $10. For 5,000 runs, it's 100,000 credits at the cap and 40,000 at 8 calls per run. One Growth pack (83,000 credits, $50) covers the typical 40,000. Two Growth packs (166,000 credits, $100) cover the 100,000-credit worst case. A Scale pack ($200) holds 400,000 credits at a lower rate per call, so it only pays off if you'll use most of it within the 12 months credits last.

Start on the free tier. Every month after you verify an email address you get 1,000 free credits, with no credit card, which is enough to measure your real calls per task with a cap in place.

The credits docs and the pricing page have the details and the packs. Get a free API key, add the wrapper above, and run 20 tasks before you decide on a pack. More agent guides are in the AI agents category.

Frequently asked questions

Do failed calls use credits?

No. A failed call returns an HTTP status, a JSON error body with a code, message and request_id, and the header X-Credits-Used: 0. Only a successful response debits credits. Failed attempts still take time, so cap attempts as well as credits, and see the error docs for each code.

How much does an agent run cost at 20 calls?

At 1 credit per call, a run capped at 20 calls uses at most 20 credits. That's $0.016 at the Starter rate of $0.80 per 1,000 calls, $0.012 at the Growth rate of $0.60, and $0.01 at the Scale rate of $0.50. Calls to the rare endpoint that costs more than 1 credit change the maths.

Should the budget live in the prompt or in code?

In code. A prompt that says "make at most 20 calls" is a request the model can miss after a long context or a confusing result. A wrapper that counts credits and raises an exception at the cap is deterministic. Use the prompt to tell the agent what to do when the wrapper stops it.

What happens when my credits run out mid-run?

The API returns insufficient_credits with HTTP status 402, and nothing is debited for that call. In the example wrapper, a 402 raises BudgetExceeded, which ends the run cleanly. Purchased credits last 12 months, and there is no subscription.

Does the free tier cover testing an agent?

Yes. Every account gets 1,000 free credits each month after verifying an email address, with no credit card. At a cap of 20 calls per run, that's 50 capped runs a month, or 125 runs at 8 calls each, which is enough to measure real calls per task before buying a pack.

  1. Claude MCP Web Search: Live Results for an Agent

    Add the Perceptlayer MCP server to Claude, let the agent call the Google Search endpoint, and count its cost: 1 credit per search call.

  2. Zillow Listings API: Get Property Data as JSON

    One GET to /v1/zillow/search returns listings near a point as JSON with price, beds, baths and address. Parameters, a real response, 1 credit per call.

Start with 1,000 free credits

No password to set. We email you a sign-in link, and your key works on every API.

No credit card. 1,000 free credits a month.