When agents use your software, your API becomes the product

August 29th, 202610 mins read

When agents use your software, your API becomes the product

A few months ago, I was reviewing the logs for an API and noticed paying users repeatedly hitting the same endpoint (sometimes 500+ times), even after reaching their plan limit and getting a 429 Too Many Requests response.

My first thought was that we hadn't explained the limits well enough. So, we improved the docs, wrote about rate limits, and tried to clarify the behavior, but the requests kept coming.

Eventually, the pattern made sense.

Many developers today aren't sitting down to write integrations line by line. They'd rather give the API docs to Claude, Cursor, Copilot, or other coding agents and ask them to build the integration.

That means the AI agent wrote the loop, the developer shipped it, and the code kept calling our API based on whatever the model inferred from our docs and OpenAPI specification.

Our API already returned rate-limit information, but the specification didn't describe enough of it for generated code to know what to do after a 429. So the code kept going.

That incident changed how I think about API documentation.

I gave this talk at API Conference Lagos last month, titled Software Is Going Headless: What the API Becomes When Agents Run Everything. See my slides here.

Your docs have machine readers now

Postman's 2025 State of the API report surveyed more than 5,700 developers, architects, and executives. While 89% said they use generative AI in their daily work, only 24% said they actively design APIs with AI agents in mind, and 60% still design mainly for human consumers.

That gap says a lot.

We are already using AI to build integrations for APIs that were originally documented for human developers, and that AI agent usage is growing faster than I expected.

Mintlify analyzed roughly 790 million requests to documentation sites over 30 days in 2026 and found that AI coding agents accounted for 45.3% of them, almost the same as browsers at 45.8%. Claude Code alone generated 199.4 million requests, while Cursor generated another 142.3 million, and Mintlify says the real number may be even higher because some agents do not identify themselves clearly.

I wrote more about the documentation side of this in Your docs are now read by machines, where I looked at how AI tools consume technical docs and what we can do to make that content easier for them to understand.

So when we write API documentation today, there is a good chance the reader isn't a person opening the docs in Chrome.

It may be an agent fetching the page because somebody typed "Build me a dashboard using this API."

Agents only know what you expose

A developer who gets a confusing API response can usually investigate by inspecting the headers, searching the docs, trying another request, or asking someone for help.

An agent, on the other hand, may have much less context. If all it has is your OpenAPI specification and a task, then whatever the spec says becomes a large part of what it knows about your API.

That makes inaccuracies more expensive.

An outdated OpenAPI definition used to be mostly a documentation problem. Now the same mismatch can end up in generated code, because the model may use the spec to decide which parameters to send, what errors to expect, and how to handle them.

That was what I wanted to understand after seeing the repeated 429 requests, so I gave our OpenAPI specification to Claude and asked it to audit the API from an agent's point of view.

A talk slide listing the gaps Claude found between our OpenAPI spec and the running API
A slide from my APIConf talk: what Claude flagged when it audited our spec against the running API.

As you can see from a slide I shared at APIConf, it found several places where the specification and the running API had drifted apart. Some plan requirements were different from what the code actually enforced. Rate-limit headers existed in production but were not properly represented in the spec. Some server errors were missing, and middleware behavior existed that a consumer relying on the specification would never know about.

The relationship is fairly simple:

A diagram showing the agent depending on the specification, which is supposed to mirror the implementation
When the implementation and specification disagree, the agent starts from the wrong information.

When the implementation and specification disagree, the agent starts with the wrong information.

Error responses are instructions too

The 429 issue changed how I think about API errors. A good error response should explain what happened and give the caller enough information to decide what to do next.

For example, the HTTP standard for 429 Too Many Requests allows a Retry-After header to tell the client how long to wait before trying again:

HTTP/1.1 429 Too Many Requests
Retry-After: 60
Content-Type: application/json

{
  "error": "rate_limit_exceeded",
  "message": "Try again in 60 seconds."
}

OpenAPI already gives us a way to describe that behaviour. The response definition can include both the body and the Retry-After header, so generated code or an agent has something concrete to work with when the request fails.

responses:
  '429':
    description: Too many requests
    headers:
      Retry-After:
        description: Number of seconds to wait before retrying
        schema:
          type: integer
    content:
      application/json:
        schema:
          type: object
          properties:
            error:
              type: string
              example: rate_limit_exceeded
            message:
              type: string
              example: Try again in 60 seconds.

So the issue was not a lack of tooling. Our OpenAPI specification simply did not describe enough of how the API actually behaved.

MCP makes the same idea explicit. Its tool specification separates protocol errors from tool execution errors, and recommends returning actionable tool failures to the model with isError: true so the model can see what happened and try to correct itself.

That is a useful way to think about API errors in general. The response does not only describe what went wrong. It also gives the agent the information it needs to decide what to do next.

If the response says only:

{
  "error": "Request failed"
}

the model has very little to work with. Compare that with:

{
  "error": "rate_limit_exceeded",
  "retry_after_seconds": 60,
  "message": "Your current plan allows 100 requests per minute."
}

Now there is enough information for generated code or an agent to decide what to do next. The same applies to authentication, validation, permissions, missing resources, and server errors. A 403 should make it clear whether the user lacks permission, needs a different plan, or cannot perform the action at all.

Validation errors should point to the failing field and explain the expected format, while temporary failures should be easy to distinguish from permanent ones. Human developers benefit from that clarity too, but agents make the cost of vague error handling much easier to see.

You don't need to rebuild your API for agents

I don't think this means everyone needs to build an MCP server right away. I would start with the API itself. It still needs to behave correctly, the OpenAPI specification needs to reflect that behavior, and the errors need to tell the caller enough to recover when something goes wrong.

Salesforce is an interesting example of how far this can eventually go. In April 2026, it announced Headless 360, exposing Salesforce capabilities through APIs, MCP tools, and CLI commands. Parker Harris, Salesforce's co-founder, had asked a simple question shortly before the announcement:

Why should you ever log into Salesforce again?

Parker Harris, Salesforce co-founder

Salesforce's answer was to make more of the product callable without going through the browser.

I don't read that as the end of user interfaces. There are plenty of things I would still rather do visually.

What changes is that the interface is no longer the only product surface.

A workflow can now look like this:

A flow from a person to an agent to the API to the application, with the dashboard off to the side
The person may never open your dashboard, so the API carries more of the product experience.

The person may never see your dashboard, which means the API itself starts shaping more of the product experience. Endpoint names, authorization rules, schemas, and the OpenAPI specification all affect what an agent can understand and do.

What matters most is that the specification matches production. If the docs say one thing and the API behaves differently, the agent is working from the wrong version of your product.

I would test the agent path directly

After seeing that pattern in our logs, one of the simplest tests I now use is to give the agent only what a developer would have publicly available, such as the docs, the OpenAPI specification, and an API key, then ask it to build a small integration.

For example:

Using only this API documentation, build a script that
fetches the latest data for a symbol and handles errors
and rate limits correctly.

Then read the code it produces and ask questions like:

  • Did it invent a parameter?
  • Did it understand authentication?
  • Does it know which plan can access the endpoint?
  • What does it do with a 429?
  • Does it retry 500 responses forever?
  • Does it even know those errors can occur?

If the generated code gets something wrong because the published contract didn't explain it, I would treat that as an API issue too.

That was one of the practical exercises I shared at API Conference Lagos. Give an agent only your public API material and see where the integration breaks. It can quickly reveal gaps in the docs, the spec, or the API behavior.

You can also automate parts of that check. CI can compare routes with the OpenAPI file, validate known error responses, and test plan or permission rules against what the docs claim. You can even have an agent periodically build a small integration from the public spec and use the result to catch places where the documented behavior has drifted from production.

The API is becoming a product surface

The 429 loop taught me that improving agent experience can start with something very basic:

  1. Make sure the API specification reflects how the API actually behaves.
  2. Document the errors that really happen.
  3. Expose the headers callers need.
  4. Keep plan and permission rules in sync with production.
  5. Give the caller enough information to recover when something goes wrong.

And lots more…

Then give an agent the same public docs your users get and see what it builds. You may find that the next API bug is already sitting in the spec.


Joel Olawanle

Joel Olawanle

Software Engineer & Technical Writer. Building Spidra & NGN Market.

Follow on Twitter