An API is a product surface, not just a connection between screens and a database. Each endpoint should make clear who can perform an action, which records they can access, what data is accepted, and what information is safe to return. Building these checks into the design is more reliable than treating security as a final review.
The short version
Key takeaways
Authorize access to each requested resource, not only to the endpoint.
Validate and constrain input at the API boundary.
Return only the data the client needs and avoid leaking internal errors.
Protect secrets, log security-relevant events, and test negative cases.
A useful principle“Authentication identifies a caller; authorization decides whether that caller may access this specific resource.”
Make authorization specific
A signed-in user should not automatically be able to access every record of the same type. Check ownership, organization membership, and the requested action at the point where data is read or changed. Apply the same policy to list, detail, update, export, and background-job paths. Add tests for users who are unauthenticated, authenticated with insufficient permissions, and authorized for only some of the requested data.
Treat all input and output as boundaries
Validate request bodies, query parameters, uploaded files, and identifiers against explicit types, size limits, and allowed values. Prefer parameterized database operations and avoid constructing commands from raw user input. Return stable error messages that help clients recover without exposing stack traces, secrets, or internal implementation details. Minimize response fields to reduce accidental disclosure and document the expected behavior for invalid and partial requests.
Protect operations beyond the request handler
Keep credentials out of source code and client bundles, use appropriate secret storage, and define how credentials are rotated. Apply rate limits and abuse controls to sensitive or expensive operations. Log useful security events with enough context to investigate, while excluding passwords, tokens, and unnecessary personal data. Include dependency updates, access-control tests, and review of configuration changes in the normal delivery process.
Conclusion
Secure APIs come from consistent boundaries and explicit permissions. Make the safe behavior the default, test denials as carefully as successful requests, and revisit the controls when new features change who can do what.
Topics