Prompt Details
Model
(claude-5-sonnet)
Token size
2,597
Example input
[api_spec]: GET /users/{id}, POST /users, PATCH /users/{id}, DELETE /users/{id} β a user profile management API
[api_type]: API key in header (X-API-Key)
[consumer_type]: External third-party developers integrating for the first time
[primary_use_case]: cURL
Example output
# API Design Audit β User Profile Management API
**Auditor role:** APIReviewer (principal-level API design specialist)
**Input mapping note:** The template calls for four inputs (`api_spec`, `api_type`, `consumer_type`, `primary_use_case`). Only `api_spec`, `consumer_type`, plus two extra fields (`auth method`, `example language`) were supplied. Missing fields are treated as **INFERRED**:
- `api_type` β **REST** (INFERRED, high confidence β resource-noun paths + standard HTTP verbs)
- `primary_use_case` β **General user profile CRUD for third-party account integrations** (INFERRED, moderate confidence β no explicit use case given)
- `auth method` (STATED): API key in header, `X-API-Key`
- `example language` (STATED): cURL β used below for illustrative snippets
---
## STEP 0 β DESIGN CONTEXT
| Dimension | Classification | Rationale |
|---|---|---|
| API maturity stage | Greenfield / early public release | No version segment, no deprecation markers, being opened to first-time external devs |
| Consumer coupling level | Loose (public) | Third-party developers, no shared deploy cadence |
| Change tolerance | Low | External consumers can't coordinate around breaking changes |
| Primary risk surface | **Security** (1), **Versioning** (2) | Flat API key + no version marker are the two structural gaps most likely to cause incidents |
### Failure Mode Priority Map
| Failure Mode | Priority | Evidence Type | Conf |
|---|---|---|---|
| Breaking changes with no versioning strategy | HIGH | INFERRED | 85 |
| Leaking internal domain model in response shape | MED | INFERRED | 55 |
| Auth/authz gaps on sensitive endpoints | HIGH | INFERRED | 80 |
| Inconsistent naming / response shape across endpoints | MED | INFERRED | 40 |
| Missing pagination / rate limiting on list endpoints | MED | INFERRED | 70 |
| Chatty design requiring N round-trips | LOW | INFERRED | 50 |
*Rationale:* External, first-time integrators cannot informally ask questions or negotiate deploy timing the way an internal service team can β so any silent contract change (auth requirement, field rename, status code shift) breaks their production code with no warning. A flat, single-tier API key with no scoping compounds this because it collapses authentication and authorization into one weak signal, which is the highest-severity gap in a public-facing CRUD API over personal data.
---
## STEP 1 β DESIGN ANALYSIS TABLE
| Design Dimension | Finding | Evidence Type | Severity | Conf |
|---|---|---|---|---|
| Resource modeling | `users` is a clear plural noun matching the domain concept | STATED | π’ | 90 |
| HTTP method semantics | GET/POST/PATCH/DELETE map to conventional CRUD, but POST idempotency (duplicate-create protection) and PATCH merge semantics are unspecified | STATED (methods) / INFERRED (behavior) | π‘ | 60 |
| Status code correctness | No example responses given β cannot confirm 200 vs 201 vs 204 or 400 vs 422 usage | INFERRED (gap) | π‘ | 50 |
| Authentication mechanism | API key via `X-API-Key` header β no mention of expiry, rotation, or scope | STATED | π‘ | 75 |
| Authorization granularity | No stated check that a key is restricted to specific `{id}` records β likely endpoint-level only | INFERRED | π΄ | 80 |
| Input validation | No schema/type enforcement described for POST/PATCH bodies | INFERRED | π‘ | 55 |
| Error response structure | No error shape, codes, or catalog described | INFERRED | π‘ | 50 |
| Pagination strategy | No `GET /users` list endpoint exists at all β pagination is moot until one is added | STATED (absence) | π‘ | 70 |
| Rate limiting & throttling | Not mentioned; critical given external, first-time consumer base | INFERRED | π΄ | 75 |
| Versioning strategy | No version segment in any path (e.g. no `/v1/`) | STATED (absence) | π΄ | 85 |
| Documentation completeness | Only method+path signatures available β no examples, error catalog, or auth flow doc surfaced | INFERRED | π΄ | 70 |
---
## STEP 2 β ASSUMPTION LEDGER & CONSTRAINT COLLISIONS
### Assumption Ledger
| Assumption | Where It Enters | If False β Effect on API Behavior |
|---|---|---|
| API key scopes access to only the requesting consumer's authorized records | Authz check on GET/PATCH/DELETE `/users/{id}` | Any key holder can read/modify/delete arbitrary profiles by varying `{id}` β full data breach |
| `{id}` is non-sequential/non-guessable (e.g. UUID) | Path parameter design | Sequential integer IDs enable trivial enumeration attacks |
| POST `/users` has duplicate-prevention (unique email constraint or idempotency key) | User creation flow | Retried requests from third-party HTTP clients silently create duplicate accounts |
| DELETE is a hard delete with no soft-delete/undo | Deletion endpoint | A single misfired request causes irreversible data loss; if soft-delete exists but is undocumented, consumers wrongly believe data is gone (compliance risk) |
| No separate key-rotation mechanism exists | Long-lived third-party integrations | Undocumented rotation silently breaks integrations that hardcode the key |
### β Silent Corruption Flags
- **IDOR on `/users/{id}`**: passes cleanly in a developer's own sandbox test (they only ever query their own ID) but silently exposes/modifies every other user's data once real production traffic touches adjacent IDs.
- **POST `/users` without idempotency protection**: fine under manual single-shot testing, but production retry/timeout behavior (standard in third-party HTTP clients) silently produces duplicate user records.
- **No rate limiting**: invisible during low-traffic development, but permits credential-stuffing or bulk scraping once external developers go live.
### Constraint Collisions
| Constraint A | Constraint B | Conflict Type | Resolution Required |
|---|---|---|---|
| Rich, actionable error messages for self-debugging (first-time integrators need this) | Error responses must not leak internal schema/implementation details | Verbosity vs. security | Structured error-code catalog (e.g. `USER_NOT_FOUND`, `VALIDATION_EMAIL_INVALID`) with public-safe messages; never expose stack traces or internal field/table names |
| Single flat API key (simple integration) | Fine-grained per-resource authorization needed to stop IDOR | Simplicity vs. security granularity | Scope keys to specific user records/tenants at issuance, or move to an OAuth2 token whose subject claim is checked against `{id}` on every request |
| Clean, version-free URLs for a simple first release | External consumers need a stable long-term contract | Simplicity vs. stability | Add versioning (`/v1/users`) now β retrofitting it after third parties are live is far more disruptive than starting with it |
---
## STEP 3 β SECURITY DEEP SCAN
| Attack Vector | Exposed? | Mechanism | Mitigation | Severity | Conf |
|---|---|---|---|---|---|
| Injection (SQL/NoSQL/command) | UNCLEAR | No info on how `{id}` or PATCH body fields are parameterized/validated | Parameterized queries/ORM + strict input schema validation | π‘ | 40 |
| IDOR | YES (likely) | `{id}` in path, flat API key, no stated per-record authz check | Server-side ownership check on every read/write; non-sequential IDs | π΄ | 80 |
| Mass assignment | YES (likely) | PATCH body fields not restricted in spec β a client could set privileged fields (e.g. `role`, `isAdmin`) if the server blindly binds JSON to the model | Explicit allowlist of mutable fields per endpoint | π΄ | 65 |
| Excessive data exposure | YES (likely) | GET response shape unspecified; common anti-pattern is returning the full internal object (password hash, internal flags) | Dedicated response DTO/serializer excluding sensitive fields | π‘ | 55 |
| Broken function-level authorization | LIKELY | One flat key with no stated role/scope split between read vs. write vs. delete | Scope keys/tokens per operation; delete should not be granted by default | π΄ | 60 |
| SSRF | NO | Spec shows no evidence the API fetches external URLs server-side | N/A unless a future field (e.g. `avatarUrl`) triggers a server-side fetch β allowlist destinations if so | π’ | 70 |
---
## STEP 4 β CONSUMER EXPERIENCE AUDIT
*(rated from the stated consumer perspective: external third-party developers, first integration)*
| UX Dimension | Rating | Finding | Evidence Type |
|---|---|---|---|
| Discoverability | Poor | Only bare method+path signatures visible β no docs portal, schema, or examples surfaced; hard blocker for a first-timer | INFERRED |
| Predictability | Fair | Standard CRUD verbs are guessable, but PATCH's exact merge/partial-update behavior is undocumented | INFERRED |
| Error recoverability | Poor | No error schema/catalog stated β nothing to self-debug against | INFERRED |
| Versioning safety | Poor | No version marker in path β future breaking changes would be unannounced | INFERRED |
| SDK friendliness | Fair | Simple resource-oriented shape is easy to wrap, but no OpenAPI spec is mentioned, so client generation would be hand-rolled | INFERRED |
---
## STEP 5 β INPUT ROBUSTNESS SCENARIOS
| Condition | First Break Point | Predicted API Behavior | Consumer Impact | Conf |
|---|---|---|---|---|
| Malformed input (wrong type, missing required field) | Field validation layer | Unknown β likely inconsistent 400s or unhandled 500s, no validation documented | Integrator burns debugging time with no clear signal | 50 |
| Concurrent writes to same resource (two PATCH calls in-flight) | No stated concurrency control (no ETag/If-Match) | Last-write-wins, silent overwrite | Data loss with no error signal; hard-to-reproduce bug reports | 55 |
| Consumer sends stale/expired API key | Auth middleware | Unknown whether keys even expire; likely a generic 401 with no "expired" vs "invalid" distinction | Integrator can't tell if they typo'd the key or it rotated | 45 |
| Response payload exceeds consumer's buffer expectation | Response serialization | Unknown β depends on whether the user object embeds nested collections | Lightweight/mobile third-party clients risk parsing or memory issues | 40 |
---
## STEP 6 β PRIORITIZED RECOMMENDATIONS
| Priority | Finding | Recommendation | Effort | Impact |
|---|---|---|---|---|
| π΄ P1 | No versioning strategy | Prefix all routes with `/v1/` before any external developer integrates | Low | High |
| π΄ P1 | No per-record authorization on `{id}` routes (IDOR risk) | Enforce a server-side check that the authenticated key's authorized subject(s) match the requested `{id}` on every GET/PATCH/DELETE | Med | High |
| π΄ P1 | No stated rate limiting | Apply per-key rate limits; return `X-RateLimit-*` headers and `429 Too Many Requests` | Med | High |
| π‘ P2 | No documented error schema | Publish a consistent error envelope and error-code catalog | Med | High |
| π‘ P2 | Mass assignment risk on PATCH body | Allowlist mutable fields server-side; reject/ignore privileged fields like `role` | Low | High |
| π‘ P2 | No concurrency control on PATCH | Support optimistic concurrency via `ETag`/`If-Match` | Med | Med |
| π’ P3 | No list/search endpoint | If listing users is ever needed, add a paginated `GET /users?cursor=...` now rather than retrofitting later | Med | Med |
| π’ P3 | No published request/response examples | Publish an OpenAPI 3.0 spec with cURL examples per endpoint | Low | Med |
### Illustrative cURL Examples
Current (as specified β no version, ambiguous errors):
```bash
curl -X GET "https://api.example.com/users/123" \
-H "X-API-Key: YOUR_API_KEY"
```
Recommended (versioned, with explicit Accept header for a documented error contract):
```bash
curl -X GET "https://api.example.com/v1/users/123" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Accept: application/json"
# Example PATCH with allowlisted fields only
curl -X PATCH "https://api.example.com/v1/users/123" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "If-Match: \"etag-value\"" \
-d '{"name": "Jane Doe", "email": "jane@example.com"}'
```
---
## STEP 7 β DESIGN INTEGRITY CHECK
| Check | Status | Note |
|---|---|---|
| Every π΄ finding is grounded in a stated or inferred spec element | β
| All trace to the 4 literal endpoints or the stated auth header |
| Security scan covers all 6 OWASP API top vectors | β
| IDOR, mass assignment, excessive data exposure, broken function-level authz, injection, SSRF |
| Consumer experience rated from the stated consumer type's perspective | β
| Rated specifically for external, first-time third-party integrators |
| No finding phrased as "could be improved" without a specific action | β
| |
| Constraint collisions have a resolution, not just a flag | β
| 3 of 3 collisions resolved |
| All INFERRED findings are labeled | β
| |
**AUDIT CONFIDENCE: 55/100** β the spec provided is only four endpoint signatures plus an auth header name, so most findings on validation, error shape, and authorization logic are necessarily INFERRED from convention rather than STATED.
**Biggest unknown:** whether the API key is scoped per end-user/tenant at issuance. This single fact determines whether the IDOR finding is a P1 blocker or a non-issue.
**Findings from spec alone (STATED):** resource path structure (`/users/{id}`, `/users`); HTTP methods used (GET/POST/PATCH/DELETE); auth mechanism is an API key via `X-API-Key`; absence of a version segment in the path; absence of a list/collection GET endpoint.
**Findings requiring a live run to verify (VERIFY):** actual status codes per scenario; error response shape/content; whether PATCH performs partial merge vs. requires a full object; whether API keys are scoped per user or global; presence/absence of rate limiting; presence/absence of input validation and mass-assignment protection; response payload shape/fields returned by GET.
Get this prompt + 9 more with Select$14 first month, then $19/mo Β· Cancel anytime$14 first month Β· then $19/mo
View SelectBy purchasing this prompt, you agree to our terms of service
CLAUDE-5-SONNET
πA principal-level API design audit for REST, GraphQL & gRPC APIs. Paste your spec and get failure-mode mapping for your consumer type plus an 11-point design analysis (resource modeling, HTTP semantics, auth, versioning, docs). Includes a security deep scan, consumer-experience audit, and input-robustness stress tests. Every finding is tagged STATED or INFERRED with a confidence score, plus a prioritizedπ΄π‘π’fix list and an integrity check so nothing gets hand-waved.
...more
Added over 1 month ago
