Using a JWT scoped to your current user, you make a GET request to /api/orders/1024. Then, as a quick test, you ask for an order your account has no business seeing and definitely shouldn’t have access to. If the API hands it over, you’ve demonstrated Broken Object Level Authorization, the number one risk in the 2023 OWASP API Security Top 10, and it took a single request. Nothing about that request was malformed, which is why it’s the kind of flaw a scanner with one login walks straight past, and why API penetration testing has become its own discipline rather than a footnote in a web app assessment.
Your endpoints serve mobile apps, partner integrations, and other services directly, and many of them are never touched by the website front end at all. Traditional application pentests were built for a world where the browser was the client.
What Is API Penetration Testing?
API penetration testing is a security assessment that simulates real-world attacks against an application programming interface to find vulnerabilities and demonstrate their impact. Instead of clicking through a UI, the tester works directly with the API endpoints, chaining small weaknesses into real consequences, such as reading another tenant’s data or calling an admin-only action from a standard account.
A web app pentest typically covers what the front end exposes. An API pentest deliberately targets the endpoints behind the API, including routes the UI never calls. APIs hand out object identifiers, accept structured payloads, and enforce their own authorization on every request, so they fail in ways specific to that model.
Why APIs Need a Dedicated Penetration Test
Authorization failures are the hard part. They’re difficult for any scanner that holds a single identity and has no model of the access policy it should be enforcing, because the requests are syntactically valid. You won’t find a broken access check by fuzzing for injection strings. Finding one means comparing behavior across identities, roles, objects, and methods.
Source review and AI-assisted review get you partway there, and flagging an endpoint that never checks access at all is genuinely useful. What they can’t settle is how the deployed API behaves with real identities against real data. A scanner configured with multiple profiles can automate part of that comparison, and a tester can push it further.
The flaw is only proven when a tester, or an automated tool acting like one, authenticates as one user and attempts to access another user’s resources. Detection and verification aren’t the same job.
API inventories drift. A single service tends to expose far more endpoints than a traditional web application, spread across multiple versions, and teams add more on every release. When documentation and retirement lag behind deployment, older versions remain accessible. OWASP is blunt about the consequence: threat agents “usually get unauthorized access through old API versions or endpoints left running unpatched and using weaker security requirements.”
You’ll hear those called zombie APIs. A pentest that only exercises what the current UI calls will miss them entirely.
Compliance pushes in the same direction. PCI DSS carries an explicit penetration testing requirement, numbered 11.4 in v4.x, covering the cardholder data environment perimeter and critical systems. An API that stores, processes, or transmits account data, or that could affect the security of that environment, may fall in scope. SOC 2 works differently. It’s an examination of controls against the applicable AICPA Trust Services Criteria, rather than a blanket testing mandate, and API authorization testing can provide evidence of logical access controls when those are in scope.
The API Vulnerabilities That Matter Most
Most of what a tester hunts for maps to the OWASP API Security Top 10. Three of the top five entries are authorization failures, where a caller accesses data or performs actions they shouldn’t, sometimes without authenticating at all. That concentration is why API security testing gets its own workstream. Our full breakdown of the OWASP API Security Top 10 risks goes deeper on all ten.
- Broken Object Level Authorization (API1): the API accepts an object reference and acts on it, whether that’s a read, an update, or a delete, without checking that the caller is authorized to do so. Ownership is one possible rule; access can equally turn on tenancy, sharing, delegation, or roles. The ID can sit in the path, the query string, a header, or the body. OWASP draws the line precisely: “the violation happens at the object level, by manipulating the ID.”
- Broken Authentication (API2): a separate identity failure, not an authorization one. Missing authentication on a route, failure to validate token authenticity or expiry, weak JWT signatures or key handling, credential-stuffing and brute-force exposure, and unsafe account recovery flows.
- Broken Object Property Level Authorization (API3): the caller can read or modify object properties they aren’t authorized to touch, whether that’s a sensitive field exposed in a response or a protected field accepted from a request. Mass assignment lives here. Returning only the properties an endpoint needs is still worth doing as a defense-in-depth measure.
- Broken Function-Level Authorization (API5): the caller reaches a function they shouldn’t be able to access at all. Usually that’s an action reserved for a higher role, but it also covers a user in one group calling a function meant only for another group at the same privilege level. OWASP frames the test as a question worth memorizing: can a user “perform sensitive actions … that they should not have access to by simply changing the HTTP method (e.g. from GET to DELETE)?”
Injection, SSRF, and missing rate limiting still show up in real engagements and you should test for them, but the authorization cluster is what makes API testing its own discipline.
Black Box, Grey Box, and White Box API Testing
The three models describe how much internal knowledge and access the assessor is given. They aren’t fixed attacker personas, and none of them is universally best.
| Model | Assessor knowledge and access | Approximates | Useful for |
| Black box | No internal knowledge; public docs may still exist | An outsider starting from zero | Externally observable behavior and public exposure |
| Grey box | API documentation plus dedicated test identities | A malicious or compromised user | Testing across identity, role, object and tenant boundaries |
| White box | Source, architecture, configuration and specs | An attacker with insider knowledge | Implementation paths and design assumptions you can’t infer externally |
When cross-user and cross-role authorization coverage is the priority, grey box is usually the efficient choice. Give a tester credentials for two roles, plus the API documentation, and they can systematically check whether one role can access another’s objects and functions, which is where the highest-severity findings sit.
Black box testing is closer to a real external attack but burns a lot of the engagement just discovering endpoints. White box testing reaches code paths the other two can only guess at, though it needs source access a tester often doesn’t have. Plenty of engagements combine techniques.
The API Penetration Testing Methodology, Step by Step
These phases track what experienced testers and the OWASP guidance converge on.
Scoping and Rules of Engagement
Everything below assumes you own the API or hold explicit written authorization to test it. The requests in this guide are illustrative, and running them against someone else’s system without permission is not a pentest.
Then agree on the target hosts, versions, and environments; the test identities, roles, and tenants you’ll be given; whether write, delete, and high-volume operations are permitted; the test window, source IPs, and rate ceilings; how test data and evidence are handled and cleaned up; an emergency stop procedure and contacts; and whether a retest is in scope.
Scope is where most disappointing pentests go wrong. A test scoped to production read-only traffic won’t tell you anything about your DELETE handlers.
Reconnaissance and Endpoint Discovery
Everything starts with mapping the attack surface. The tester collects API documentation, imports any OpenAPI or Swagger definition, and enumerates endpoints, methods, and parameters. A reachable swagger.json accelerates recon by exposing routes, methods, and parameters, but treat it as a finding only when that document wasn’t meant for this audience. Where docs are missing or stale, the tester infers routes from client traffic, guesses conventional paths, and brute-forces hidden paths and parameters.
The goal is a complete inventory. Undocumented endpoints deserve extra scrutiny simply because they’re harder to inventory, test, patch, and retire. A solid recon pass proxies every request the client apps make, imports the spec, and reconciles the two: endpoints in traffic but not the spec, and vice versa, are both worth a hard look.
GraphQL APIs get an extra step. When introspection is enabled and accessible, a tester can query the schema’s types, fields, and operations directly. OWASP recommends disabling or restricting it in production deployments whose consumers don’t need it, though that only reduces schema disclosure. It doesn’t stand in for authorization, query-cost limits, or input validation.
Authentication Testing
Next, the tester probes how the API establishes identity: token issuance, expiry, and validation; JWT handling; session management; and whether authentication can be bypassed or replayed outright. A single route that skips authentication undermines every access check behind it.
Authorization Testing (BOLA and BFLA)
BOLA is horizontal. It’s the test from the top of this post: as a standard user, you request GET /api/orders/1024, which is yours, then change it to 1025. If the API hands back an order belonging to another user, that’s the finding, and it doesn’t matter who that other user is.
BFLA is about reaching a function you shouldn’t reach at all. Most of the time, that means an action reserved for a higher role, like POST /api/admin/settings or GET /api/v1/users/export_all, called from an account that should never be allowed to do so. It also covers the sideways case, where a user in one group calls a function scoped to another group. Either way, you’re checking whether the endpoint enforces the role or just the login.
Build a coverage matrix across the in-scope object types, identities, roles, tenants, and operations, and include alternate methods where the rules of engagement allow. Authorization is often correct for reads but missing for updates or deletes on the same resource. Our guide to Broken Function Level Authorization covers how to test the function-level side in depth.
Input Validation and Injection
With authorization mapped, the tester goes after the data the API accepts: SQL and NoSQL injection, command injection, and SSRF. For SSRF, test every user-controlled value that could cause the server to access another resource, whether it appears in the path, query string, headers, or body. Mass assignment is tested here too by adding unexpected fields, such as “role”: “admin”, to the request body and observing whether the API binds them.
Automatic binding is the mechanism that exposes it, and APIs that map JSON straight onto internal models are especially open to it. Classify a successful unauthorized property change as API3, not a generic input-validation bug: OWASP puts the root cause at the missing property-level authorization check.
Business Logic and Rate Limiting
The last phase targets flaws that exist only in how the application is meant to work: multi-step flows driven out of order, or quantity and price fields that can be manipulated. Limits belong here too, tested by the risk each one controls: throttling and lockout on authentication, then frequency, concurrency, timeouts, payload and page size, and query cost for resource consumption, then whether a perfectly valid operation can be automated in a way that harms the business. These findings take the most work because they require understanding intent, not just syntax.
API Penetration Testing Checklist
A starter checklist, not exhaustive coverage, but it’s the shape of what a serious engagement covers:
- Inventory every endpoint: undocumented, deprecated, and non-production API routes included. Import the OpenAPI spec and diff it against what’s actually deployed.
- Test authentication on every route: token validation, expiry, replay, and whether anything is unintentionally public.
- Test object-level authorization: replay requests across user accounts with swapped identifiers.
- Test function-level authorization: attempt privileged actions from unprivileged roles, across every HTTP method.
- Test input handling: injection (SQL, NoSQL, command), SSRF, and mass assignment.
- Test business logic: out-of-order workflows, parameter manipulation, and missing rate limiting.
- Check data exposure: does any endpoint return more fields than the client actually needs?
- Verify error handling: no stack traces, internal hostnames, or implementation details in responses.
- Test property-level authorization: read and modify sensitive properties the caller shouldn’t control, including unexpected request fields.
- Test consumption limits and sensitive flows: frequency, concurrency, payload and page size, query cost, and whether a valid operation can be automated harmfully.
- Review inventory and configuration: environments, versions, deprecated routes, third-party data flows, TLS, CORS, allowed methods, and exposed management interfaces.
- Record evidence, clean up, and retest: keep the request, response, identity, and object for each finding, remove test artifacts, then confirm each fix under the same conditions.
Tools for API Penetration Testing
Tooling supports the methodology, it doesn’t replace it. A typical engagement pulls from four categories.
| Category | Examples | What it’s for |
| Intercepting proxies | Burp Suite, OWASP ZAP | Capturing, modifying, and replaying requests by hand. The backbone of manual authorization testing. |
| API-aware DAST | Tools that consume specifications, recorded traffic, or both | Automating authenticated tests across the API styles a given tool supports, without hand-writing each request. |
| API clients | Postman, Insomnia | Building, saving, and replaying requests against documented endpoints, and importing an OpenAPI collection. |
| Fuzzers | Boundary and malformed input generators | Surfacing crashes and injection points at scale. |
Pick based on the authorization work rather than feature lists. A proxy makes it easy to run the same operation across identities, objects, roles, and methods: capture one user’s request, swap the token, replay it. Token swapping is one technique among several, since other tests hold the identity fixed and change the object, or reach a privileged route anonymously, and scripts and configured scanners can automate the same comparisons.
Automated scanners give you breadth across an API surface that’s too large to hand-test, and much of the kit overlaps with functional testing: the Postman collections and OpenAPI specs your QA team already maintains make excellent recon material. Our roundup of API testing tools covers that side in more detail.
Pentest vs Continuous API Security Testing
Here’s the gap a pentest alone leaves open. The report is accurate the day it lands, but an assessment can’t cover endpoints or authorization decisions introduced after it finishes, and every deploy between engagements ships more of both.
That’s the argument for pairing pentests with continuous runtime testing, and it’s what we built StackHawk to do. We ship agent skills for Claude Code, Cursor, Codex, Antigravity, and GitHub Copilot that drive the hawk CLI, so when a feature is finished and before the PR opens, the agent runs HawkScan against your running application, works through what comes back, and rescans to confirm the fix landed. HawkScan still runs in CI/CD as well.
Three parts of it map onto phases of this guide:
- Discovery: a scan finds routes from your OpenAPI, GraphQL, gRPC, and SOAP definitions, an HTML crawl, proxied Postman or Playwright traffic, or a HAR file. That covers the recon step.
- Business Logic Testing: cross-user checks for BOLA and BFLA, with BOPLA covered by separate property-level plugins.
- Rescan: replays the requests behind previous findings instead of rediscovering the app, falling back to a full scan when that replay data isn’t available. That’s the retest step.
None of that is zero-configuration, and multi-profile testing is the part to plan for. It needs an OpenAPI spec, at least two dedicated test identities, and representative data: peer identities need separately owned resources for BOLA, and you need identities at different privilege levels for BFLA. Our own docs are blunt about the other constraint. Run active multi-profile scans against staging or test environments rather than production, which holds real customer data, and use the separate passive policy if you need to look at production at all.
The two approaches do different jobs. Continuous testing catches known classes and regressions on every change, while a human tester explores the novel, chained, and context-dependent abuse cases that nobody has written a check for yet. Our comparison of DAST and AI pen testing digs further into where each approach earns its place.
Conclusion
Two decisions carry most of the value here. Test authorization across identities, roles, objects, and methods rather than trusting that a valid-looking request was a permitted one, and retest the changes that ship between manual engagements, because those are the ones nobody has looked at.
If you want to see what that looks like against your own APIs, you can start a free trial and run it from Claude Code, Cursor, Codex, Antigravity, or GitHub Copilot. If you’re carrying the program rather than the codebase, here’s how we approach it with security teams.
Frequently Asked Questions
In an environment you’re authorized to test, authenticate as user A and record a request for invoice 1024, which belongs to A. Now replay that same request as user B, keeping the ID at 1024. If B receives A’s invoice with no authorized relationship to it, you’ve demonstrated Broken Object Level Authorization. Changing the identity while holding the object fixed is what makes the result mean something.
There’s no single best tool. Manual work usually runs on an intercepting proxy such as Burp Suite or OWASP ZAP. Breadth and repeatability come from API-aware DAST that can drive authenticated scans from an OpenAPI spec. Most real engagements combine both.
API testing broadly means validating an API’s behavior. Functional API testing verifies that endpoints return the correct results, while API security testing, including penetration testing, ensures that endpoints can’t be abused to access data or perform actions they shouldn’t. This guide is about the security side.
Almost every provider quotes against a defined scope because the price varies with endpoint count and complexity, API styles, the number of identities and tenants in play, the test model, business-logic depth, reporting requirements, and retest scope. Continuous automated testing is priced separately and covers routine findings between engagements, which is why many teams budget for both.
