API Security: The Complete Guide for Developers (2026)
Your API is the attack surface that matters most. This guide covers every major threat category, authentication pattern, and testing strategy — so you can ship fast without leaving the door open.
APIs power every modern application. They're also the #1 target for attackers. According to Cloudflare's 2024 API Security Report, API-targeted attacks grew 137% year-over-year — and the vast majority targeted small and mid-sized companies, not enterprises with large security teams.
If you're an indie developer or startup CTO, this guide is for you. We'll walk through every major threat, every authentication pattern, and the practical steps you can take today — even before you have a dedicated security team. You can scan your API for free right now to see where you stand.
What Is API Security?
API security is the set of practices, configurations, and controls that protect your application's programming interfaces from unauthorized access, data exposure, abuse, and attack. It covers everything from how you authenticate callers to how you handle malformed input to how you configure server response headers.
Unlike traditional web application security — which focuses on what users see in a browser — API security is about the machine-to-machine layer. Your API doesn't care what the UI looks like. Anyone with curl can hit it directly, bypass your frontend entirely, and see exactly what your backend returns.
That's why API security requires an external, attacker's-eye-view. Running an external API scanner against your live app reveals what code review alone cannot.
Common API Threats You Need to Know
The OWASP API Security Top 10 is the canonical reference for API threats. Here's what each threat looks like in practice for a startup-scale app.
1. Injection Attacks
SQL injection, NoSQL injection, command injection — these attacks happen when untrusted user input reaches an interpreter without proper sanitization. In API terms: if your endpoint accepts a filter or query parameter and passes it directly to a database query, an attacker can manipulate that query to extract, modify, or delete data.
The fix: Use parameterized queries (never string-concatenated SQL), an ORM with proper escaping, and input validation on every field before it reaches your data layer. Prisma, Drizzle, and TypeORM all handle this correctly by default — as long as you don't use raw query helpers with unescaped input.
2. Broken Authentication
Broken authentication is the #1 OWASP API risk. It covers everything from missing auth on endpoints to weak token validation to API keys shipped in client-side JavaScript.
Common patterns: a developer adds a route during debugging and forgets to protect it; a mobile app stores a secret API key in the app bundle; a JWT is accepted without verifying its signature. Each is exploitable by a moderately skilled attacker.
The fix: Every non-public API route must verify a valid token server-side. We cover JWT and OAuth patterns in depth below.
3. Excessive Data Exposure
Your API returns a full user object. The frontend only displays the name and email. But the response also contains the user's password hash, internal notes, billing status, and admin flags — because the developer returned the raw database row and trusted the frontend to filter it.
This is excessive data exposure. It's endemic in startups because it's fast to write and invisible until someone intercepts a response in DevTools.
The fix: Serialize API responses explicitly. Never return raw database objects. Define a response schema (DTOs in NestJS, Zod transform in Next.js) and strip everything that shouldn't leave the server.
4. Missing Rate Limiting
Without rate limiting, your API is an open invitation to brute-force attacks, credential stuffing, enumeration, and DDoS. An attacker can try 10,000 passwords against your login endpoint in minutes, or hammer your AI endpoint until your OpenAI bill is five figures.
The fix: Add rate limiting at the edge (Cloudflare, Vercel, AWS WAF) and at the application layer. For auth endpoints specifically, implement exponential backoff after failed attempts and account lockout after a threshold.
5. Misconfigured CORS
CORS (Cross-Origin Resource Sharing) controls which domains can make requests to your API from a browser. Access-Control-Allow-Origin: * tells every browser in the world that any site can read responses from your API — including responses authenticated with your users' cookies.
The wildcard is almost always a mistake. Most developers add it to fix a development error and forget to tighten it before launch.
The fix: Lock CORS to an explicit allowlist of origins. In Next.js, set this in your API route middleware or next.config.js headers. Never use * with credentials: include.
Check your API for all five threat categories — free
No signup. No SDK. 60-second external scan.
Scan Your API Free →Authentication Best Practices
Authentication is where most startup APIs fail. Let's look at the three main patterns — JWT, OAuth, and API keys — and what to get right with each.
JWT (JSON Web Tokens)
JWTs are the most common auth mechanism in modern APIs. A signed token is issued at login and sent with every subsequent request. The server verifies the signature without hitting a database.
What to get right:
- Always verify the signature. Never decode and trust a JWT without verifying the signature with your secret key. Libraries like
jsonwebtoken,jose, andnext-authdo this correctly — raw base64 decoding does not. - Set short expiry times. Access tokens should expire in 15–60 minutes. Use refresh tokens for session persistence.
- Never put secrets in the payload. JWT payloads are base64-encoded, not encrypted. Anyone can decode them. Only put non-sensitive identifiers (user ID, role) in the payload.
- Avoid the
nonealgorithm. Some JWT libraries accept tokens withalg: none— no signature required. Explicitly reject this in your validator configuration.
For a deeper dive, see our guide: JWT Security Best Practices: 8 Mistakes That Expose Your API.
OAuth 2.0
OAuth 2.0 is the standard for delegated authorization — letting users grant your app access to a third-party service (Google, GitHub, Stripe) without sharing their password. If you're building a "Sign in with Google" flow, you're using OAuth.
What to get right:
- Use the Authorization Code flow with PKCE for any public client (SPAs, mobile apps). Never use the implicit flow for new apps — it's deprecated.
- Validate the
stateparameter on every callback to prevent CSRF attacks. - Store tokens server-side or in secure, httpOnly cookies — never in localStorage or sessionStorage.
- Use libraries (
next-auth,passport,auth0) rather than rolling your own OAuth implementation. The edge cases are subtle and consequential.
API Keys
API keys are the simplest auth mechanism — a shared secret sent with every request, typically in the Authorization header or as a query parameter.
What to get right:
- Never put API keys in client-side code. This includes
NEXT_PUBLIC_variables, mobile app bundles, and any JavaScript that ships to a browser. Keys in client code are public keys. - Scope keys to minimum permissions. An API key for reading user data shouldn't be able to delete accounts. Stripe, GitHub, and most modern platforms support fine-grained key permissions — use them.
- Rotate keys regularly. Build rotation into your key management workflow. Any key that might have been exposed should be revoked immediately.
- Store keys in environment variables (
.env), a secrets manager (AWS Secrets Manager, HashiCorp Vault), or a platform like Doppler. Never commit keys to git.
Exposed API keys in your live app? Find out in 60 seconds.
Scan Your API Free →Testing Your API for Security Issues
Security testing for APIs falls into two categories: code-level analysis (static) and runtime testing against a live app (dynamic). You need both.
Static Analysis (Before Deploy)
Static analysis scans your source code for known vulnerability patterns — hardcoded secrets, insecure dependencies, dangerous function calls. Run it in CI so issues are caught before they reach production.
- Semgrep — open-source static analysis with security-focused rulesets for Node.js, Python, Go, and more.
- Snyk — dependency vulnerability scanning. Good for catching CVEs in your
node_modules. - Gitleaks / TruffleHog — scan git history for committed secrets. Run this immediately if you've ever accidentally committed credentials.
- ESLint security plugins —
eslint-plugin-securityadds rules that catch common Node.js security anti-patterns at the linting stage.
Dynamic Analysis (Against Your Live App)
Dynamic analysis tests your running API from the outside — the same way an attacker would. This catches issues that static analysis cannot: misconfigured headers, CORS policies, exposed endpoints, SSL problems, and behavior that only appears at runtime.
- Scantient — free external scan for headers, CORS, SSL, exposed paths, and API key exposure. Results in 60 seconds, no setup.
- OWASP ZAP — open-source DAST scanner. Powerful but requires configuration; good for deeper automated testing in CI.
- Burp Suite — the professional standard for manual API penetration testing. Use it for focused testing of specific endpoints.
- Postman / Insomnia — not security tools per se, but essential for manually probing API behavior: testing auth bypass, parameter manipulation, and response content.
See also: OWASP Top 10 for APIs: A Practical Checklist for 2026.
Security Headers: The 5-Minute Fix with Outsized Impact
Security headers are one of the highest-ROI security improvements you can make. They're a few lines of configuration that protect against entire categories of attack: clickjacking, XSS, protocol downgrade, MIME sniffing, and information leakage.
- Strict-Transport-Security (HSTS) — forces HTTPS for your domain and all subdomains. Prevents protocol downgrade attacks.
- Content-Security-Policy (CSP) — controls which scripts, styles, and resources can execute in your app. Mitigates XSS.
- X-Frame-Options — prevents your app from being embedded in an iframe. Blocks clickjacking.
- X-Content-Type-Options — prevents MIME type sniffing. Set to
nosniff. - Referrer-Policy — controls how much referrer information is sent with requests. Set to
strict-origin-when-cross-origin.
For implementation details: 5 Security Headers Every Indie Dev Should Set (And How to Check Them).
Missing security headers? Check all 5 in 60 seconds.
Scan Your API Free →AI APIs Need Extra Security Attention
If your app calls OpenAI, Anthropic, or a custom LLM, you have additional attack vectors that traditional API security doesn't cover. Prompt injection — where malicious user input hijacks your LLM's behavior — is now the AI equivalent of SQL injection.
Key considerations for AI APIs:
- Never embed your OpenAI API key in client-side code
- Validate and sanitize all user input before passing it to an LLM prompt
- Rate limit AI endpoints aggressively — they're expensive to abuse
- Treat LLM output as untrusted input before rendering it in your UI
Full guide: Securing Your AI App's API: What to Check Before Launch.
API Security Mistakes Developers Make in Production
The most common API security failures we've seen in real startup scans:
- API keys in client-side JavaScript bundles
- CORS set to
*from a development debugging session - Auth checks only in frontend components, not API routes
- Debug endpoints left exposed in production (
/api/admin,/.env) - Missing or misconfigured security headers
- SSL certificates about to expire (or expired)
- Rate limiting skipped because "we don't have many users yet"
Read the full breakdown: 7 API Security Mistakes Killing Your Startup.
The API Security Checklist
Run through this before launch — and re-run it every time you add a significant new endpoint or feature.
Authentication & Authorization
- ✅ All non-public API routes verify auth server-side
- ✅ JWTs: signature verified, short expiry, no secrets in payload,
nonealgorithm rejected - ✅ API keys: stored server-side only, scoped to minimum permissions, not in git
- ✅ OAuth: PKCE for public clients,
stateparameter validated - ✅ No hardcoded credentials in source code or environment files committed to git
Transport & Headers
- ✅ HTTPS enforced everywhere (HSTS header set)
- ✅ SSL certificate valid and monitored
- ✅ Content-Security-Policy configured
- ✅ X-Frame-Options set to
DENYorSAMEORIGIN - ✅ X-Content-Type-Options:
nosniff - ✅ Referrer-Policy configured
CORS & Access Control
- ✅ CORS locked to specific origin allowlist (no
*with credentials) - ✅ Methods and headers explicitly allowed, not wildcarded
- ✅ Preflight requests handled correctly
Input Validation & Data Handling
- ✅ All input validated with a schema (Zod, Joi, class-validator)
- ✅ Parameterized queries everywhere — no string-concatenated SQL
- ✅ API responses serialized explicitly — no raw database objects returned
- ✅ Error messages don't leak stack traces or internal details
Rate Limiting & Availability
- ✅ Rate limiting on all public endpoints
- ✅ Stricter limits on auth endpoints (login, password reset, OTP)
- ✅ AI/LLM endpoints rate limited separately
Exposed Endpoints & Operational Security
- ✅ No debug endpoints in production (
/api/debug,/.env,/.git) - ✅ Health check endpoints don't expose configuration or environment details
- ✅ Dependencies up to date; no known CVEs in production packages
Don't check the list manually — scan your API in 60 seconds
Scantient checks headers, CORS, SSL, exposed paths, and API key exposure automatically. No signup. No SDK. Free.
Scan Your API Free →Scan Your API Free — Results in 60 Seconds
External security scan: headers, CORS, SSL, exposed endpoints, API key exposure. No signup. No SDK.