100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Python

API Security Basics

Foundational API security: strong authentication, rate limiting, input validation, and why hidden endpoints are not secure.

Web Application SecurityIntermediate11 min readJul 8, 2026
Analogies

Introduction

APIs are now the primary way applications talk to each other — mobile apps, single-page frontends, partner integrations, and internal microservices all communicate over APIs, often exposed directly to the internet. Because APIs are consumed by software rather than viewed by a human in a browser, some of the assumptions that protect traditional web pages don't apply, and API-specific controls are needed.

🏏

Cricket analogy: Just as IPL franchises now exchange player data and live scores directly between team apps and broadcasters via feeds rather than a fan reading a scoreboard, APIs let mobile apps and microservices talk machine-to-machine, so they need their own gatekeeping instead of relying on a human noticing a suspicious screen.

Explanation

Authentication for APIs typically uses API keys for service-to-service calls or OAuth access tokens for delegated user access, rather than browser cookies and login forms. Every request to a protected endpoint should present valid, verifiable credentials, and those credentials should be scoped as narrowly as possible — a key that only needs to read data should not also be able to write or delete it. Rate limiting caps how many requests a given client, key, or IP address can make in a time window; without it, an API is exposed to brute-force credential attacks, scraping, and denial-of-service style abuse, and a single compromised key can be throttled rather than allowed to hammer the backend without limit. Input validation matters just as much for APIs as for web forms — every field in a JSON or XML payload, every query parameter, and every path segment is attacker-controlled and must be validated for type, length, format, and business-rule correctness before use, exactly as with any other untrusted input. Finally, 'security through obscurity' — leaving an endpoint undocumented or hard to guess but with no real authentication or authorization check — is not a security control. Anyone who discovers the URL, whether through a leaked mobile app binary, browser dev tools, or simple guessing, gets full access; obscurity can be a minor speed bump at best, never a substitute for enforcing real authentication and authorization.

🏏

Cricket analogy: A stadium checks every player's official BCCI accreditation badge before letting them onto the field, and a substitute fielder's pass only permits fielding, not batting, just as scoped API keys should permit only the specific action needed, like read but not write.

Example

python
# BEFORE: unauthenticated 'hidden' endpoint, no validation, no rate limiting
@app.route("/internal/reset-usage-XJ29")  # security through obscurity
def reset_usage(request):
    account_id = request.args["account_id"]
    db.execute(f"UPDATE accounts SET usage=0 WHERE id={account_id}")
    return "ok"

# AFTER: real auth, scoped API key, input validation, rate limiting
@app.route("/api/v1/accounts/<account_id>/usage/reset")
@require_api_key(scope="usage:write")
@rate_limit(max_requests=5, per_seconds=60)
def reset_usage_secure(request, account_id, api_key):
    if not account_id.isdigit():
        raise ValueError("Invalid account_id")
    if not api_key.owns_account(int(account_id)):
        raise PermissionError("Not authorized for this account")
    db.execute("UPDATE accounts SET usage=0 WHERE id=%s", (int(account_id),))
    return {"status": "ok"}

Analysis

The 'before' endpoint relies entirely on its URL being hard to guess, has no authentication, builds SQL unsafely, and has no cap on how often it can be called — four independent weaknesses stacked on top of each other. The 'after' version requires a scoped API key (so only clients with usage:write can call it), checks that the key's owner actually controls the target account (authorization, not just authentication), validates the account_id format, uses a parameterized query, and rate-limits calls to stop abuse or brute-force account_id guessing. None of these controls depend on the URL staying secret, which is exactly the point: real security holds even after the endpoint is fully public knowledge.

🏏

Cricket analogy: A ground that only relies on fans not knowing the players' entrance, has no ticket check, lets anyone claim any seat, and never limits gate rushes is fixed by adding accreditation checks, seat-ownership verification, and crowd-flow limits, none of which depend on the gate staying secret.

Key Takeaways

  • Authenticate every request with API keys or OAuth tokens, scoped to the minimum access needed.
  • Rate limit requests per client to prevent brute-force, scraping, and abuse.
  • Validate every field, query parameter, and path segment as untrusted input.
  • Never rely on an endpoint being undocumented or hard to guess as a substitute for real authentication and authorization.

Practice what you learned

Was this page helpful?

Topics covered

#Python#CyberSecurityFundamentalsStudyNotes#CyberSecurity#APISecurityBasics#API#Security#Explanation#Example#APIs#StudyNotes#SkillVeris