The API Endpoints Nobody Is Watching
During a penetration test on a financial services firm, we found a customer account data endpoint at /api/v1/accounts. It returned full account details, including account numbers and balances, for any account ID we passed in the URL. No authentication header required. No session check. Wide open.
The v2 endpoint, the one the current mobile app used, required OAuth and had proper authorization checks. The v1 endpoint was "deprecated" two years ago. Nobody had turned it off. It had just quietly kept responding to requests, unmonitored, unlogged, unprotected, while the organization's security team ran assessments against the current application.
This is not an unusual finding. Variations of it show up in a meaningful percentage of API-focused assessments. The endpoint that should not have worked, worked.
The Inventory Problem
APIs are the connective tissue of modern applications. Every microservice, every third-party integration, every mobile backend, every internal tool that communicates with another internal tool does it over an API. The question is not whether your organization has a large number of APIs. It does. The question is whether anyone knows what they all are.
In most organizations the answer is: approximately not. There is no single source of truth for what APIs exist, what they expose, who can call them, and what authentication they require. There is documentation that covers the major services, which is somewhere between 40 and 70 percent accurate depending on when it was last updated. There are OpenAPI specs for the services that have them, which is fewer than half. And there is a shadow layer of internal services that were never formally documented because they were "just internal" and not worth the paperwork.
The inventory problem is where all the other API security problems start. You cannot review what you have not mapped. You cannot monitor what you do not know exists. And deprecated endpoints stay running forever when nobody has a complete picture of what is running.
Why "Internal" Stopped Being a Security Control
Internal APIs accumulated weak security over years because of an assumption that turned out to be wrong: that network position implied trust. If only the application can call this endpoint, why would it need authentication? The application is trusted.
Things change. Internal services get exposed externally when architecture evolves. Attackers who gain a foothold inside a network now have access to every internal endpoint built around the assumption of good faith. Cloud environments make "internal" harder to define than on-premises networks ever did. A service accessible from within a VPC is accessible to anyone who can get into that VPC, which is a much larger population than whoever built the service originally had in mind.
An API that relies on network position for security is relying on a perimeter that does not exist in most modern environments. Every API should require authentication as if it were publicly exposed, because the circumstances under which it becomes publicly exposed are increasingly common and increasingly hard to predict.
The Patterns That Keep Appearing
Undocumented version endpoints are a consistent finding. Services evolve. V1 gets replaced by v2 with proper authentication and authorization. V1, which was "deprecated," still responds to requests because deprecation means "we stopped using it," not "we turned it off." The documentation says deprecated. The endpoint says 200 OK.
Excessive data exposure is quieter and more common than most teams realize. An endpoint designed to return a user's display name for a profile widget returns the full user object from the database, including fields the frontend never renders. The developer retrieved the whole record because it was simpler and filtered in the client. The API never filtered. Callers who go directly to the API get everything.
Broken object-level authorization is how the expensive breaches happen. An endpoint returns order data at /api/orders/12345 and is supposed to verify that the requesting user owns order 12345. The check exists. It was tested. It works on the path where the user ID in the token matches the order owner. What was not tested is the path where someone passes a different order ID and a valid token for a different account. That path also works, and it is not a hypothetical.
Missing rate limiting on authentication endpoints explains how credential stuffing attacks succeed at the scale they do. An endpoint that does not enforce a request rate limit or lockout policy is an open invitation to test passwords at whatever speed the infrastructure permits. The answer is often very fast.
What Actually Helps
Start with discovery, not documentation. Traffic analysis from your API gateway is the most reliable source of what APIs actually exist. If you do not have an API gateway sitting in front of your services, that is the first gap to address.
A gateway gives you a single enforcement point for authentication, a centralized log of every API request, rate limiting that applies consistently across services, and visibility into anomalous traffic patterns. The individual services do not have to each get security right if the gateway always checks first. This is microsegmentation logic applied to the API layer: a compromised client does not give an attacker direct access to every backend service.
Mandate OpenAPI specifications for every API, including internal ones, and treat undocumented APIs as out of compliance. An API without a spec has no formal review process. An API without a review process has no security assessment. That chain runs directly to the deprecated v1 endpoint that nobody knew was still running.
Test your production APIs against the OWASP API Security Top 10 as part of every penetration testing engagement, not as a separate exercise that happens when someone remembers to ask for it. The categories in that list, broken object-level authorization, broken authentication, excessive data exposure, are not theoretical constructs. They are patterns extracted from real incidents at organizations with functional security programs.
The Leverage Point
API security is one of the areas where the gap between "we did the assessment" and "we actually fixed the posture" is widest. The assessment surfaces the deprecated endpoints, the missing authorization checks, the services without rate limiting. The work of actually closing those gaps requires coordination between security and every engineering team that owns a service, and that coordination is where findings go to become backlog items that never move.
The organizations that close that gap build it into the development process rather than the assessment process. Security review of API design before deployment, not just after. Automated scanning of deployed services against known patterns. A gateway that enforces the baseline before any individual service gets a chance to miss it.
The deprecated endpoint kept responding because nobody was watching. Build a program that watches.