API Security · 2026
API Security Best Practices: A 2026 Engineering Guide
Your application is mostly an API now, and that is where the high-impact breaches happen. This is the practitioner's guide to the controls that matter: authentication, authorization, rate limiting, input validation, and secrets — organized around the OWASP API Security Top 10, with code and MITRE ATT&CK mapping.

Quick answer
Secure an API by authenticating every request, authorizing every object access on the server, validating and constraining all input, rate-limiting and quota-ing every endpoint, and keeping secrets out of code and clients. The single highest-impact control is object-level authorization — never trust an identifier supplied by the client. Organize the work around the OWASP API Security Top 10 and verify it with authenticated, role-aware penetration testing.
The classic OWASP Top 10 was written for web pages. APIs have their own failure modes, which is why OWASP maintains a separate API Security Top 10 that leads with authorization rather than injection. We build APIs for a living — our API development practice bakes these defenses in, and our web app pentest tests them. The sections below follow the order that matters in practice, not the order people expect.
1. Authentication: prove who is calling
Authentication verifies identity. Use a standard rather than rolling your own: OAuth 2.0 / OpenID Connect for user-facing APIs, signed short-lived tokens (JWT or opaque) for service-to-service calls, and scoped API keys only where a full token flow is impractical. The failure mode here is OWASP API2: Broken Authentication — weak tokens, missing expiry, no rotation, or accepting tokens that were never validated.
- Validate token signature, issuer, audience, and expiry on every request — do not trust an unverified token because it "looks right."
- Keep access tokens short-lived; use refresh tokens deliberately.
- Require MFA on the human login that mints those tokens.
- Rate-limit the login and token endpoints (see section 4) to blunt credential stuffing.
ATT&CK link: weak authentication enables Valid Accounts (T1078) and Brute Force (T1110).
2. Authorization: the bug that actually breaches you
Authorization decides what an authenticated caller may do. This is where most real API breaches happen, and it splits into two OWASP entries: API1: Broken Object-Level Authorization (BOLA) and API3: Broken Object Property-Level Authorization. BOLA is the classic: the endpoint trusts an ID from the client instead of checking ownership against the session.
// VULNERABLE — trusts the URL parameter
app.get("/api/orders/:id", auth, async (req, res) => {
const order = await db.orders.findById(req.params.id);
return res.json(order); // any logged-in user reads any order
});
// FIXED — scope the lookup to the authenticated owner
app.get("/api/orders/:id", auth, async (req, res) => {
const order = await db.orders.findOne({
id: req.params.id,
ownerId: req.user.id, // ownership enforced server-side
});
if (!order) return res.status(404).end();
return res.json(order);
});Property-level authorization is the subtler cousin: a user is allowed to update a record but should not be allowed to set every field on it. Mass-assignment bugs let a caller flip role: "admin" or isVerified: true through an update endpoint that blindly spreads the request body.
- Enforce authorization on the server for every object access. Deny by default.
- Allow-list which fields a request may set; never spread the raw body into a database write.
- For multi-tenant systems, scope every query by tenant — consider database-level row isolation. Our SaaS platform development practice builds tenant isolation in at the data layer.
- Test with a low-privilege account, never an admin one.
3. Input validation and output handling
Validate every input against a strict schema at the boundary — types, ranges, lengths, and allowed values. Reject what does not conform rather than trying to sanitize it. A schema validator (Zod, JSON Schema, Pydantic) at the edge of each handler closes a wide class of injection and logic bugs before they reach your data layer.
- Use parameterized queries / prepared statements everywhere — never build SQL by concatenation.
- Constrain numeric and quantity fields. A negative or absurdly large amount is a business-logic exploit waiting to happen.
- Set and verify
Content-Type; reject unexpected payload formats. - Guard against server-side request forgery: if your API fetches a URL, allow-list the destination and block internal and cloud-metadata ranges.
ATT&CK link: input flaws feed Exploit Public-Facing Application (T1190).
4. Rate limiting and resource consumption
OWASP API4: Unrestricted Resource Consumption covers the cost-and-availability side. Without limits, one client can exhaust your capacity, run up your cloud bill, or brute-force credentials. Apply limits per authenticated identity and per IP, with tighter limits on expensive endpoints.
// Stricter limit on a sensitive endpoint
// 5 attempts / 15 min / IP on login; fail closed on limiter error
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5,
standardHeaders: true, // emit RateLimit + Retry-After
handler: (_req, res) =>
res.status(429).json({ error: "too_many_requests" }),
});
app.post("/api/login", loginLimiter, loginHandler);- Return
429with aRetry-Afterheader. - Stricter limits on login, password reset, search, and export.
- Pair limits with per-tenant quotas so one customer cannot starve the rest.
- Bound pagination and payload sizes; reject unbounded list requests.
ATT&CK link: missing limits enable Brute Force (T1110) and Endpoint Denial of Service (T1499).
5. Secrets, keys, and transport
Secrets belong in a secrets manager or platform environment variables, never in source control and never in a client bundle where they are trivially extracted. This is the raw material for account takeover, so treat a leaked key as an incident.
- Store secrets in AWS Secrets Manager, GCP Secret Manager, or Vault.
- Rotate on a schedule and on any suspicion of exposure.
- Scope keys to least privilege; prefer short-lived tokens.
- Enforce TLS on every endpoint, including internal service calls.
- Verify signatures on inbound webhooks — see our Stripe webhook security guide for the pattern.
Mid-post: test the API, don't just harden it
Hardening is half the work. An authenticated, role-aware API pentest proves the authorization checks actually hold. Book a free scoping call.
The OWASP API Security Top 10 at a glance
| Risk | What it means |
|---|---|
| API1 BOLA | Object access not scoped to the authenticated owner |
| API2 Auth | Broken or weak authentication of the caller |
| API3 Property auth | Caller can read/write fields they should not (mass assignment) |
| API4 Resources | No rate limits or quotas; consumption abuse |
| API5 Function auth | Regular users reach admin-only functions |
| API6–API10 | Business-flow abuse, SSRF, misconfiguration, inventory gaps, unsafe third-party API use |
For the web-application companion list, see the OWASP Top 10 explained, and the short definition lives in the glossary.
Operational practices that hold over time
Controls decay without process. Three habits keep an API secure past launch day:
- Inventory. Maintain an up-to-date list of every endpoint and version. OWASP API9 (improper inventory management) is how forgotten staging or v1 endpoints become the breach.
- Logging and monitoring. Log authentication, authorization-denied, and high-value actions with enough context to investigate, and alert on anomalies.
- Regular testing. Re-test after any release that changes auth or data access. For compliance-driven cadence, see how to prepare for a SOC 2 audit.
For founders building payment or money-movement APIs, the stakes are higher still — our fintech penetration testing guide covers the threat model specific to APIs that touch funds, and the SaaS platform development practice builds these controls in from day one.
Frequently asked questions
What are the most important API security best practices?
Authenticate every request, authorize every object access on the server, validate and constrain all input, rate-limit and quota every endpoint, keep secrets out of code and clients, and log security-relevant events. Above all, enforce object-level authorization — the single most common and most damaging API flaw is an endpoint that trusts an ID from the client instead of checking it against the authenticated session.
What is the difference between authentication and authorization in an API?
Authentication proves who is making the request — verifying a token, key, or session. Authorization decides what that identity is allowed to do. APIs frequently get authentication right and authorization wrong: a valid token is accepted, but the server never checks whether that user owns the specific record being requested. That gap is broken object-level authorization, the top entry on the OWASP API Security Top 10.
What is the OWASP API Security Top 10?
It is OWASP's API-specific risk list, separate from the web Top 10. It leads with authorization failures unique to APIs: broken object-level authorization (API1), broken authentication (API2), broken object property-level authorization (API3), and unrestricted resource consumption (API4). Because modern apps are mostly APIs behind a thin UI, this list is often the one that determines whether you get breached.
How should APIs handle rate limiting?
Apply limits per authenticated identity and per IP, with stricter limits on expensive or sensitive endpoints — login, password reset, search, export, and anything that triggers downstream cost. Return 429 with a Retry-After header, fail closed when the limiter is unavailable, and pair limits with quotas so a single tenant cannot exhaust shared capacity. Rate limiting is your primary defense against credential stuffing and resource-consumption abuse.
Where should API secrets and keys be stored?
In a dedicated secrets manager (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault) or platform environment variables that are never committed to source. Never embed secret keys in client-side bundles or mobile apps, where they are trivially extractable. Rotate keys on a schedule and on suspicion of compromise, scope them to the least privilege required, and prefer short-lived tokens over long-lived static keys.
How do you test API security?
With authenticated, role-aware penetration testing rather than scanning alone. A tester uses low-privilege accounts on each role tier and tries to access objects belonging to other users and tenants, manipulate object properties, abuse business logic, and exhaust resources. Findings are mapped to the OWASP API Top 10 and the relevant MITRE ATT&CK techniques so engineers and auditors can prioritize the fix.
Sources & references
- [1]OWASP API Security Top 10 (2023) · OWASP
- [2]OWASP Cheat Sheet Series — REST Security · OWASP
- [3]RFC 6749 — The OAuth 2.0 Authorization Framework · IETF
- [4]MITRE ATT&CK Enterprise Matrix · MITRE
Related reading and next steps
- API Development service
- Web Application Pentest service
- SaaS Platform Development service
- Penetration Testing service overview
- The OWASP Top 10 explained (2026)
- Penetration testing for fintech startups
- Stripe webhook security best practices
- Red team vs pen test vs audit
- What is the OWASP Top 10?
- Talk to Bill about your API security
Harden it, then prove it holds.
An authenticated API pentest maps every finding to the OWASP API Top 10 and the ATT&CK technique it enables. Book a free scoping call and we'll cover the right depth for your API.
More engineering security reading
All postsStripe Webhook Security Best Practices
Idempotency, signature verification, retries, and dead-letter handling.
Read postWhat Is Penetration Testing? A Founder's Buyer Guide
What a pentest actually is, the five types you can buy, and what a real report looks like.
Read postRed Team vs Pen Test vs Audit
Three engagement types, three buyer profiles, and when to use each.
Read post