API Security Best Practices: OWASP API Top 10 in Practice
A developer builds an endpoint that returns a customer’s order. It checks the session token, loads the order by the id in the URL, and returns it. Every test passes, code review approves it, and the API ships.
Nothing in that flow asks whether the order belongs to the caller. Change one digit in the id and the endpoint hands over someone else’s record, because it was never told not to.
That single missing comparison is API1 in the OWASP API Security Top 10, and it remains the most common way real APIs leak data. It also shows why API security best practices read differently from web application ones.
The vulnerability is not a payload, an encoding bug, or a missing header. It is a business rule nobody wrote down.
What are API security best practices?
Section titled “What are API security best practices?”API security best practices are the design and implementation rules that keep an API safe once an attacker has a valid token. They cover authorization on every object and function, authentication that resists automation, responses that expose only the fields a client needs, server-side limits on what one request can consume, and an accurate inventory of every version you have exposed.
The definition deliberately starts after authentication. Most API breaches involve a caller who is genuinely signed in, using a credential they were given, calling an endpoint they were allowed to reach. The failure is that the server confirmed identity and then skipped the question of permission.
That is why the OWASP API Security Top 10 looks so different from the web list. Its top two categories are both broken access control, split by what the caller is reaching: an object they do not own, or a function their role should not invoke.
Why do APIs fail differently from web applications?
Section titled “Why do APIs fail differently from web applications?”A web application has a user interface that quietly enforces half of its security model. Buttons are hidden from roles that should not use them, fields are dropped before render, and page sizes are fixed by the template.
An API has none of that. The client is whatever the caller decides to run, so every constraint the interface used to apply has to exist on the server or it does not exist at all.
That changes what you can assume. The response is the API, not the screen, and the request body is fully attacker-controlled, including fields your form never showed.
The id in the path is a parameter rather than a fact. Anything the client sends can be edited by whoever is holding the token.
How does the OWASP API Security Top 10 group real failures?
Section titled “How does the OWASP API Security Top 10 group real failures?”The 2023 edition of the list is easier to train against when you group it by the question the server forgot to ask.
Authorization: does this caller own this thing?
Section titled “Authorization: does this caller own this thing?”Broken object level authorization, API1, is the one from the opening example. The server loads the object named in the request and returns it without comparing ownership, which lets any authenticated caller walk through ids and harvest records. Our broken object level authorization exercise puts you on both sides: swap the id and read another rider’s trip, then add the ownership check that stops it.
Broken function level authorization, API5, is the role version of the same gap. Admin routes share the API with ordinary users, the controls are hidden in the interface, and the endpoints carry no role guard, so any valid token reaches them. The broken function level authorization exercise has you call staff-only endpoints from a read-only analyst account, then fix it at the router rather than the handler.
Authentication: can the check be brute-forced?
Section titled “Authentication: can the check be brute-forced?”Broken authentication, API2, is rarely a broken credential check. It is usually a correct check with no defense against automation, which matters most when the credential is short.
A six-digit email code has one million possibilities. Without rate limiting or lockout, an attacker who knows only an email address can walk the entire space. The broken user authentication exercise runs that attack against an unlimited verify endpoint, then rate-limits per account and returns 429.
Data: what is actually in the response?
Section titled “Data: what is actually in the response?”Excessive data exposure happens when an endpoint serializes the whole stored object and trusts the client to display only the safe parts. The screen looks fine. The raw JSON in the network tab carries the phone number, the date of birth, and the coordinates.
The fix is a serialization allow-list, not a smarter client. Work through it in the excessive data exposure exercise, which has you compare a rendered profile page against the response behind it.
Mass assignment is the same problem pointed the other way. When an update endpoint binds every field in the request body onto the model, a client can add role or balance to a PATCH and write attributes the form never exposed. The mass assignment exercise mints a loyalty balance with two extra keys, then binds only the editable fields.
Limits and inventory: what did you forget?
Section titled “Limits and inventory: what did you forget?”Unrestricted resource consumption, API4, covers endpoints with no server-side bound on how much one request can pull. A page size taken straight from the query string turns normal pagination into a full table export. See it happen in the unrestricted resource consumption exercise.
Improper inventory management, API9, is the version you cannot fix in code you are looking at. A deprecated v1 that was documented as retired but never decommissioned still answers, without any of the controls v2 added. The improper inventory management exercise reads records through the old version, then retires it properly with 410 Gone.
Security misconfiguration, API8, rounds out the set. A CORS policy that reflects any Origin and allows credentials lets any website read a signed-in account, with no application bug involved at all.
Which API security best practices actually reduce risk?
Section titled “Which API security best practices actually reduce risk?”These are ordered by how much breach probability they remove per hour of engineering work, not by how they appear in the standard.
- Check ownership in the data layer, not the handler. A scoped query that filters by the caller’s id cannot be forgotten the way an if-statement can. Handlers get copied; repository methods get reused.
- Put role checks at the router. A guard applied per-route is auditable in one file. A guard applied inside each handler is auditable only by reading all of them.
- Serialize with an allow-list. Define the fields a response may contain. Anything added to the model later stays private until someone deliberately publishes it.
- Bind with an allow-list too. Accept a named set of writable fields from the request body and drop the rest, so a new column is never accidentally client-writable.
- Cap page size and rate on the server. Set a hard maximum that no request parameter can raise, and rate-limit per account rather than per IP.
- Log the reads, not just the writes. Authorized access is the only category of abuse that breaks no control, so an audit trail is the sole detection mechanism. The insufficient logging and monitoring exercise shows a support agent pulling a customer profile with no ticket and leaving no trace.
- Keep an inventory and enforce decommissioning dates. A deprecated version that still answers is production, whatever the docs say.
- Parameterize every query. Injection is older than REST and still ships. The API injection exercise turns a catalog search into a full database read, then parameterizes so input stays data.
How do you train developers on API security?
Section titled “How do you train developers on API security?”Reading the OWASP API Security Top 10 teaches the vocabulary. It does not teach the reflex, because recognizing BOLA in a slide deck is a different skill from noticing that the repository method you just wrote takes an id and no user.
The pattern that transfers is attack then fix, on code that behaves like the code your team writes. A developer who has personally walked ids through an endpoint and watched other people’s records come back stops writing unscoped queries. One who has only seen the diagram usually does not.
That is how our API security exercises are built. Each one runs a working attack against a realistic service, then has you ship the fix and prove the attack no longer works. The same approach covers the web layer in our application security catalogue, so a team can move across the OWASP web and API lists without changing how they learn.
For a broader look at how hands-on platforms compare on language coverage, OWASP mapping, and pricing, see our roundup of secure coding training platforms. If your stack has moved past REST into model-backed services, the OWASP Top 10 for LLM applications covers the risks that list does not.
How do you measure whether API security training worked?
Section titled “How do you measure whether API security training worked?”Completion rates measure attendance. Three signals measure behavior.
Track the share of new endpoints that ship with an ownership check present at first review, before anyone asks for it. Track how long a deprecated version stays reachable after its announced retirement date. Track whether authorization findings from penetration tests cluster in new code or in code written before the training.
All three are countable from systems you already run. None of them require a survey.
Frequently asked questions
Section titled “Frequently asked questions”What is the most common API vulnerability?
Broken object level authorization, listed as API1 in the OWASP API Security Top 10. An API confirms the caller has a valid session, then returns whatever object the request names without checking that the object belongs to that caller. It is common because the check has to be written deliberately for every by-id route, and nothing about a passing test suite reveals that it is missing.
Is the OWASP API Security Top 10 different from the OWASP Top 10?
Yes. The web Top 10 covers application-layer classes like injection, cryptographic failures, and misconfiguration across the whole application. The API list is scoped to interfaces consumed by code rather than browsers, so it gives authorization two separate entries, one for objects and one for functions, and adds inventory management for forgotten versions and hosts.
How often should we run API security training?
Tie it to the work rather than the calendar. Every developer who will touch an API endpoint should complete the authorization and data-exposure exercises before their first such change, with a short refresh when the OWASP list is revised or after any authorization finding reaches production.
Can API security be handled by a gateway or WAF?
Only partly. A gateway enforces authentication, rate limits, and schema validation well, and those are real controls worth having. It cannot decide whether order 4192 belongs to the caller, because that answer lives in your data model, which means object-level authorization has to be implemented in the application.
What should a developer fix first in an existing API?
Enumerate every route that takes an identifier and confirm each one filters by the caller. That single sweep addresses the highest-frequency category on the list, and it can be done from a route table without waiting for a penetration test.
Start with one endpoint
Section titled “Start with one endpoint”Pick the busiest by-id route in your API and read the query behind it. If the filter names only the object id and not the caller, you have found the same bug that opens this article.
Then hand your developers something to practice on. Our API security exercises are free to try, and you can talk to us about rolling them out across an engineering team.