the IT Hustle
ToolsPricingBlogAbout
AI CriticismAI-Assisted2026-03-18•13 min read

Building APIs: What AI Skips Over

By The IT Hustle Team

✨ AI-Assisted Content

This article was generated with AI assistance and reviewed by our team for accuracy and quality. All technical information and examples have been verified.

Ask AI to "build me an API" and you'll get CRUD endpoints in 30 seconds. Four routes: create, read, update, delete. Express or Flask boilerplate with zero thought about what happens when real traffic hits it.

API design is engineering. CRUD generation is typing. The difference between an API that lasts five years and one that gets rewritten in six months has nothing to do with the framework — it's about the decisions AI can't make for you.

I've built and consumed hundreds of APIs. I've dealt with the consequences of bad API design — breaking changes that cascade through 12 microservices, authentication schemes that leak data, pagination that melts database servers. Here's everything AI skips over.

REST Principles AI Gets Wrong

AI generates "REST" APIs that violate REST principles constantly. The most common mistakes:

Verbs in URLs

What AI generates:

POST /api/createUser

GET /api/getUsers

POST /api/deleteUser/123

POST /api/updateUserEmail

The right approach:

POST /api/users

GET /api/users

DELETE /api/users/123

PATCH /api/users/123

REST uses HTTP methods as the verbs. The URL identifies the resource — it's a noun. POST /api/createUser says "create" twice (POST already means create). This isn't pedantic — it's how clients, caches, and proxies understand your API.

Inconsistent Plural/Singular Nouns

AI mixes /user and /users randomly. Pick one convention and stick with it. The industry standard is plural: /users, /orders, /products. Even /users/123 (a single user) uses the plural collection name in the path.

Wrong HTTP Status Codes

AI returns 200 OK for everything. Created a resource? 200. Validation failed? 200 with an error message in the body. Deleted something? 200.

Status codes that matter:

200 — Success (GET, PATCH when returning the resource)

201 — Created (POST, with Location header pointing to new resource)

204 — No Content (DELETE, PATCH when not returning the resource)

400 — Bad Request (validation errors, malformed input)

401 — Unauthorized (no valid credentials)

403 — Forbidden (valid credentials but insufficient permissions)

404 — Not Found

409 — Conflict (duplicate creation, race condition)

422 — Unprocessable Entity (valid JSON but semantically wrong)

429 — Too Many Requests (rate limited)

500 — Internal Server Error (your code broke)

Status codes are part of your API contract. Clients depend on them for flow control. A mobile app needs to know the difference between "your token expired" (401 — redirect to login) and "you don't have permission" (403 — show an error message).

Authentication and Authorization

AI conflates these two concepts constantly. Authentication = who are you? Authorization = what can you do? They're separate concerns that require separate middleware.

AI will generate a JWT authentication flow that works for a demo. But it skips:

  • Token refresh strategies (access tokens should be short-lived; refresh tokens should be rotated)
  • Token revocation (what happens when a user logs out or is banned?)
  • Scopes and permissions (not every authenticated user can access every endpoint)
  • API key vs OAuth vs session-based auth — which is right for your use case
  • Rate limiting per authentication level (free tier vs paid tier)
  • CORS configuration for browser-based API consumers
Test your auth with curl:

curl -v -H "Authorization: Bearer YOUR_TOKEN" \

  https://api.example.com/users/me

Check for:

- 401 without token (not 500, not 200 with empty data)

- 401 with expired token (not a vague error message)

- 403 when accessing another user's data

Rate Limiting

AI-generated APIs have zero rate limiting. This is how you get a $50,000 cloud bill because someone scripted requests to your endpoint at 10,000 per second.

Every API needs rate limiting. No exceptions. Even internal APIs, because bugs can create infinite loops.

Rate limit response headers:

X-RateLimit-Limit: 100

X-RateLimit-Remaining: 42

X-RateLimit-Reset: 1709856000

Retry-After: 30

Rate limiting strategies:

  • Fixed window — 100 requests per minute. Simple but allows bursts at window boundaries
  • Sliding window — smoother, prevents boundary bursts
  • Token bucket — allows short bursts but enforces average rate. Best for most APIs
  • Per-user vs per-IP — authenticated users get per-user limits; anonymous traffic gets per-IP

Versioning: The Decision AI Can't Make

AI always picks URL versioning: /api/v1/users. It's the most common approach, but it's not always the best one. And AI never explains the trade-offs.

  • URL versioning (/v1/users) — simple, visible, but makes every version a completely separate API surface
  • Header versioning (Accept: application/vnd.api+json;version=2) — cleaner URLs but harder to test in a browser
  • Query parameter (?version=2) — easy to implement but pollutes query string
  • No versioning — evolve the API with backward-compatible changes, only version on breaking changes. This is what Stripe does.

The real question AI never asks: how often will you ship breaking changes, and who are your consumers? Internal APIs with one client might not need versioning at all. Public APIs with thousands of integrations need a careful deprecation strategy.

Error Response Design

AI generates error responses that are useless for debugging:

What AI generates:

{ "error": "Something went wrong" }

{ "success": false, "message": "Bad request" }

What a production API should return:

{

  "error": {

    "code": "VALIDATION_ERROR",

    "message": "Email address is required",

    "details": [

      {

        "field": "email",

        "constraint": "required",

        "message": "Email cannot be empty"

      }

    ],

    "request_id": "req_abc123"

  }

}

Good error responses include:

  • A machine-readable error code (not just a human message)
  • Field-level detail for validation errors
  • A request ID for tracing in logs
  • Consistent structure across all error types
  • Never leak stack traces, SQL queries, or internal paths to clients

Pagination: The Performance Cliff

AI defaults to offset-based pagination: ?page=5&limit=20. This works for small datasets. For large datasets, it's a performance cliff — OFFSET 100000 means the database still scans 100,000 rows before returning your 20.

Offset pagination (simple but slow at scale):

curl "https://api.example.com/users?page=500&limit=20"

Cursor-based pagination (fast at any depth):

curl "https://api.example.com/users?limit=20&after=user_abc123"

When to use which:

  • Offset — when users need to jump to arbitrary pages (admin tables, search results under 10k rows)
  • Cursor — for feeds, timelines, anything with frequent inserts, large datasets. Used by Twitter, Slack, Stripe
  • Keyset — cursor-based using the last record's sort key. Most database-efficient approach

Idempotency: The Concept AI Never Mentions

What happens when a client sends the same POST request twice? Maybe their network hiccupped. Maybe the user double-clicked. AI-generated APIs create two records. That's a bug.

Idempotent APIs produce the same result regardless of how many times the request is sent. GET, PUT, and DELETE are naturally idempotent. POST is not — you need to make it so.

Idempotency key pattern (used by Stripe):

curl -X POST https://api.example.com/payments \

  -H "Idempotency-Key: unique-request-id-abc" \

  -H "Content-Type: application/json" \

  -d '{"amount": 5000, "currency": "usd"}'

The server stores the idempotency key and its result. If the same key is sent again, it returns the cached result instead of creating a duplicate. This is critical for payment APIs, order processing, and any write operation where duplicates cause real-world problems.

API Security: The OWASP API Top 10

AI generates APIs with zero security posture. Here are the most common vulnerabilities, drawn from the OWASP API Security Top 10:

  • Broken Object-Level Authorization (BOLA) — User A can access User B's data by changing the ID in the URL. Every endpoint needs ownership checks, not just authentication
  • Excessive Data Exposure — AI returns the entire database record including internal fields, password hashes, tokens. Always use response serializers/DTOs
  • Mass Assignment — AI accepts whatever JSON the client sends and writes it to the database. A client can send {"role": "admin"} and escalate privileges
  • No rate limiting — already covered above, but it's a security issue too (brute force, credential stuffing)
  • SQL injection in filters — AI builds queries by string concatenation. Always use parameterized queries
Test for BOLA with curl:

## Log in as User A, try to access User B's data

curl -H "Authorization: Bearer USER_A_TOKEN" \

  https://api.example.com/users/USER_B_ID/orders

## This MUST return 403, not 200

Testing APIs Properly

AI-generated tests check the happy path. Real API testing covers edge cases that break production:

Test checklist for every endpoint:

## Happy path

curl -X POST .../users -d '{"email":"test@example.com"}'

## Missing required field

curl -X POST .../users -d '{}'

## Invalid data type

curl -X POST .../users -d '{"email": 12345}'

## Unauthorized access

curl .../users/123 (no auth header)

## SQL injection attempt

curl ".../users?name='; DROP TABLE users;--"

## Extremely large payload

curl -X POST .../users -d '{"bio":"A"}' (10MB string)

Use our cURL Builder to construct these test requests visually — set headers, auth tokens, request bodies, and copy the exact curl command.

Documentation: The API Is the Product

AI doesn't generate API documentation. And even when asked, it produces generic OpenAPI specs that are technically valid but useless for a developer trying to integrate.

Good API docs include examples for every endpoint, not just schema definitions. Look at Stripe's docs — every endpoint has a curl example, a response example, and explanations of when you'd use it. That's the standard.

  • Authentication setup with copy-paste examples
  • Request/response pairs for every endpoint
  • Error code reference with troubleshooting steps
  • Rate limit documentation
  • Changelog for breaking changes
  • SDKs or code examples in multiple languages

The Decisions AI Can't Make

API design is fundamentally about trade-offs. And trade-offs require understanding your users, your infrastructure, and your business constraints. AI has none of that context.

  • Should this be a REST API or GraphQL? (Depends on your client patterns)
  • How granular should your resources be? (Depends on your use cases)
  • What's your SLA? (Drives caching, redundancy, monitoring decisions)
  • Who are your consumers? (Internal team, third-party developers, mobile apps?)
  • What's your deprecation strategy? (Can you break clients or not?)

Use AI to generate boilerplate and CRUD scaffolding. But the architecture, security, and design decisions? Those are yours.

Building and testing APIs? Our cURL Builder helps you construct, test, and share HTTP requests visually — no more wrestling with curl flags and JSON escaping in the terminal.

IT
The IT Hustle Team

We build free developer tools and write about AI, automation, and developer productivity. 30 tools, 33 articles, and an AI Prompt Engine — all built to help workers navigate the AI era. Published by Salty Rantz LLC.

Our ToolsAll ArticlesAbout Us

The IT Hustle Weekly

What changed in AI this week and what it means for your job. Free tools, honest reviews, zero spam.

Generate Your Own Anti-Hallucination Prompts

Our AI Prompt Engine uses patent-pending technology to generate prompts with built-in verification and contradiction testing.

Try 3 Free Generations →

Company

  • About
  • Blog
  • Contact

Product

  • Tools
  • Pricing

Legal

  • Privacy Policy
  • Terms of Service
  • Disclaimer

© 2026 Salty Rantz LLC. All rights reserved.

Made for workers navigating tech upheaval.