
TLDR
- The biggest API breaches come from missing authorization checks (not authentication), not from sophisticated attacks. Fix authorization first.
- Validate every input on the server. Trust no client. Type validation, range validation, allow-lists for enums.
- Use rate limiting per user and per IP. The first defense against credential stuffing and scraping.
- Log everything sensitive: failed auth attempts, permission denials, admin actions. You cannot detect what you do not log.
- Run security scans on your dependencies. Most breaches involve a known CVE in a library that nobody updated.
API security is full of complicated frameworks, vendor pitches, and theoretical threats. The breaches that actually happen are usually mundane. Here is the prioritized checklist of things that actually matter, based on the patterns we see when we audit existing systems.
1. Authorization, Not Just Authentication
Authentication answers "who are you?" Authorization answers "are you allowed to do this?" Most teams get authentication right (passwords, JWTs, sessions) and ignore authorization until something breaks.
The most common API vulnerability we find is broken object-level authorization. The endpoint /api/orders/123 returns order 123 if the user is logged in. It does not check whether order 123 actually belongs to that user. So a logged-in user can change the URL to /api/orders/456 and see someone else's order.
The fix is simple but easy to forget: every query that fetches data should include the current user (or current tenant) as a filter. Not just "is the user logged in" but "is this resource theirs to see?" Use database-level enforcement (row-level security) where possible to make this impossible to forget.
2. Input Validation on the Server
Client-side validation is for user experience. Server-side validation is for security. They are not interchangeable.
For every endpoint, define a schema for what valid input looks like and reject anything that does not match. Use a validation library (Zod, Joi, Yup, Pydantic) instead of writing manual checks. Validate:
- Type (string, number, boolean, etc.)
- Format (email, UUID, ISO date)
- Range (min/max length, min/max value)
- Allowed values for enums (no surprises)
- Required vs optional fields
- Maximum size for arrays and objects
Reject anything that does not pass. Return a 400 with a clear error message. Never trust the client.
3. Rate Limiting
Without rate limiting, a single attacker can:
- Try millions of password combinations on your login endpoint
- Scrape your entire database through paginated endpoints
- Burn your LLM API budget by spamming your AI endpoint
- DDoS you with cheap, simple traffic
Implement rate limiting at multiple layers: per IP for unauthenticated traffic, per user for authenticated traffic, and per endpoint for expensive operations. The default for most apps should be something like 100 requests per minute per IP, with stricter limits on auth endpoints (10 per minute).
Tools like Upstash, Cloudflare, or your reverse proxy can handle this without writing custom code.
4. Use HTTPS Everywhere
This is so basic it should not need mentioning, and yet we still see HTTP in production. Force HTTPS at the load balancer or CDN level. Set HSTS headers so browsers refuse to downgrade. Redirect any HTTP request to HTTPS. There is no scenario in 2026 where serving an API over plain HTTP is acceptable.
5. Secrets in Environment Variables, Not Code
Your API keys, database credentials, and signing secrets do not belong in source code. They belong in environment variables managed by your deployment platform or a secret manager (Vault, AWS Secrets Manager, Azure Key Vault).
Audit your repository periodically for accidental secret commits. Use a tool like git-secrets or trufflehog. Once a secret is committed to git, even if you delete it, assume it is compromised. Rotate it.
6. Log Security Events
You cannot investigate what you did not log. At minimum, log:
- Failed authentication attempts (with IP and timestamp)
- Authorization denials (user X tried to access resource Y but was denied)
- Admin actions (especially permission changes, data exports, account deletions)
- Rate limit triggers
- Unusual patterns (lots of 404s from one IP, unusual user agents)
Send these to a centralized log system (Datadog, Sentry, even just CloudWatch) where you can search and alert on patterns. The logs you save today are what lets you investigate next year's incident.
7. Secure Your Dependencies
The easiest way to compromise an API in 2026 is through a vulnerable dependency. The Log4j incident was not a sophisticated attack on application code. It was a known vulnerability in a widely-used library.
Set up automated dependency scanning. GitHub's Dependabot is free and covers most cases. Snyk is more thorough. Run npm audit, pip-audit, or your language's equivalent regularly. Patch when alerts fire.
8. Don't Roll Your Own Auth
Authentication is a solved problem with subtle pitfalls. Use a battle-tested library or service: Auth.js (formerly NextAuth), Clerk, Supabase Auth, Auth0, Cognito, or your framework's built-in solution. Resist the temptation to build it yourself. Even experienced engineers regularly ship subtle auth bugs.
9. Set Sensible CORS Policies
If your API serves browsers, configure CORS explicitly. Allow the origins you actually need (your frontend domain). Do not use Access-Control-Allow-Origin: *. Do not use credentials: true unless you have actually thought about what that means.
If your API is server-to-server only, do not enable CORS at all.
10. Use Security Headers
Add basic security headers to your responses:
- Strict-Transport-Security (HSTS)
- X-Content-Type-Options: nosniff
- X-Frame-Options: DENY (or use Content-Security-Policy frame-ancestors)
- Content-Security-Policy (for HTML responses)
- Referrer-Policy
Helmet (for Node.js) and similar libraries set these defaults correctly out of the box.
The Practical Order of Operations
If you have an existing API and want to improve security, work in this order:
- Audit every endpoint for missing authorization checks. Fix them.
- Add input validation to every endpoint that does not have it.
- Add rate limiting if you do not have it.
- Set up dependency scanning and patch known CVEs.
- Add security event logging and review the logs.
- Then everything else.
This is not the sexy work. It is the work that prevents the breaches we read about in the news. At Stunzer Digital, security audits are part of how we close out major projects. If you have an API in production and have not had a fresh set of eyes on it, that is worth scoping.
Tags
Related service
Want this built? See how we work on Web Development.


