APIs designed without security in mind from the start tend to bolt it on later, unevenly, across endpoints added at different times by different people. A few principles applied from version one avoid most of this.
Authenticate explicitly, everywhere
Every endpoint should have a deliberate authentication decision, not an inherited default. Frameworks vary in what they do for undecorated routes — some are open by default. Make the decision explicit per-endpoint rather than relying on a framework default nobody reviewed.
Authorize per-resource, not just per-endpoint
Confirming a user is logged in isn't the same as confirming they're allowed to access the specific resource requested. This is the single most common gap in real-world APIs — an endpoint correctly requires login, but doesn't check whether this user owns this resource ID.
Validate input at the boundary
Validate structure, type, and range for every input as it enters the system, before it reaches business logic. Don't rely on the client to only send well-formed requests — assume every request is adversarial.
Rate limit from day one
Without rate limiting, a single client can exhaust resources or brute-force authentication endpoints. Adding it after a launch, once traffic patterns are established, is harder than designing it in from the start.
Return minimal information in errors
Detailed error messages help debugging but leak implementation details (stack traces, database structure, internal paths) to anyone probing the API. Return generic errors to clients; log detailed ones internally.
Version deliberately
Plan for versioning before you need it. An API with no versioning strategy tends to accumulate breaking changes applied unsafely to a single live version, or old vulnerable versions left running indefinitely because nobody planned their retirement.
Secure API design isn't a separate phase after functional design — the two happen at the same time, or the security half gets skipped under deadline pressure.