Building APIs: What AI Skips Over
By The IT Hustle Team
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
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.
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
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.
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:
{ "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.
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.
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
## 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:
## 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.
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.
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 →