From idev
Verifies frontend API calls match backend endpoints (URL paths, HTTP methods, request/response types). Use after creating or modifying API endpoints, service functions, or DTOs, or when asked to validate API alignment, check FE-BE contracts, or generate API contract docs.
How this skill is triggered — by the user, by Claude, or both
Slash command
/idev:api-contract-validationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Verify that frontend API calls and backend API endpoints agree on URL paths, HTTP methods, request/response shapes, and field types. Catches type mismatches, missing fields, and wrong URLs before runtime.
Verify that frontend API calls and backend API endpoints agree on URL paths, HTTP methods, request/response shapes, and field types. Catches type mismatches, missing fields, and wrong URLs before runtime.
This skill compares frontend service calls against backend controller signatures to find mismatches. It does NOT assume any specific stack — it detects how each side defines its contracts.
Detect how the frontend defines API calls:
TypeScript/JavaScript (Axios/Fetch):
Grep service files for HTTP calls:
axios.get<ResponseType>("api/endpoint")
axios.post<ResponseType>("api/endpoint", requestBody)
fetch("api/endpoint", { method: "POST", body: ... })
Extract: URL, HTTP method, request body type, response type
React Query hooks:
Find useQuery/useMutation calls that wrap service functions
Extract: query key, service function reference
Vue/Angular:
Similar pattern — grep for HttpClient or $http calls
Extract per endpoint:
- URL path (e.g., "api/orders/get-all")
- HTTP method (GET, POST, PUT, DELETE)
- Request body type (TypeScript interface/type)
- Response type (TypeScript interface/type)
- Field names and types from the request/response interfaces
Detect how the backend defines API routes:
.NET:
[Route("api/orders")]
[HttpGet("get-all")] → full path: api/orders/get-all
Method signature: Task<IActionResult> GetAll()
[FromBody] OrderCreateDto dto → request body type
Return type: wrapped in GetResultDtoAsync → extract inner DTO
Express/NestJS:
router.get("/api/endpoint", handler)
@Get("/endpoint") → extract path
Request body: req.body typed or validated by schema
FastAPI:
@app.get("/api/endpoint", response_model=ResponseType)
Request body: Pydantic model
Django:
urlpatterns path("api/endpoint", view)
Serializer class defines request/response shape
Spring:
@GetMapping("/api/endpoint")
@RequestBody CreateDto dto → request body
Return type: ResponseEntity<Dto>
Extract per endpoint:
- URL path
- HTTP method
- Request body DTO (field names and types)
- Response DTO (field names and types)
For each endpoint, compare FE and BE:
FE: "api/orders/get-all" (GET)
BE: [Route("api/orders")] + [HttpGet("get-all")] → "api/orders/get-all" (GET)
Result: ✓ Match
FE type: { templateId: number, templateKey: string, templateName: string }
BE DTO: { TemplateId: int, TemplateKey: Guid, TemplateName: string }
Check: Do FE field names match BE field names (accounting for casing)?
templateId ↔ TemplateId → ✓ (camelCase ↔ PascalCase, auto-converted by JSON serializer)
templateKey ↔ TemplateKey → ✓
FE: templateKey: string
BE: TemplateKey: Guid
Question: Does Guid serialize to string in JSON? → Yes ✓
FE: createdDate: string
BE: CreatedDate: DateTime
Question: Does DateTime serialize to string (ISO format)? → Yes ✓
FE: templateId: number
BE: TemplateId: int
Question: Does int serialize to number? → Yes ✓
FE: isDefault: boolean
BE: IsDefault: bool
Question: Does bool serialize to boolean? → Yes ✓
.NET → TypeScript:
int, long → number
decimal, double, float → number
string → string
bool → boolean
DateTime → string (ISO 8601)
Guid → string
List<T> → T[]
IList<T> → T[]
T? (nullable) → T | null | undefined
Python → TypeScript:
int, float → number
str → string
bool → boolean
datetime → string
uuid → string
List[T] → T[]
Optional[T] → T | null
Java → TypeScript:
int, long, Integer, Long → number
String → string
boolean, Boolean → boolean
LocalDateTime → string
UUID → string
List<T> → T[]
API Contract Validation: api/orders
✓ GET /get-all → URL match, response types match
✓ GET /get-by-id/{id} → URL match, response types match
✓ POST /create → URL match, request body match, response match
✗ PUT /update/{key} → FE sends templateKey as string, BE expects Guid
Fix: Guid auto-parses from string — OK at runtime, but FE type should be string
✓ DELETE /delete/{key} → URL match
Missing in FE: GET /get-by-key/{key} (BE endpoint exists, no FE service call)
Missing in BE: (none)
→ Generate the service function following the project's detected conventions
(see the frontend-patterns skill cache at .claude/idev/frontend-patterns/cache.md)
→ Flag as error — this causes 404 at runtime
(see the lessons-learned skill log if present for past instances)
→ If auto-serializable (Guid→string, DateTime→string): warn but pass
→ If incompatible (number↔string, boolean↔string): fail and suggest fix
→ Check if JSON serializer handles casing (camelCase ↔ PascalCase)
→ If custom serialization: flag for manual review
Write to .claude/idev/api-contract-validation/cache.json:
{
"generated": "YYYY-MM-DD",
"contracts": [
{
"endpoint": "api/orders/get-all",
"httpMethod": "GET",
"feService": "relative/path/to/service.ts",
"feFunction": "getOrders",
"feResponseType": "Order[]",
"beController": "relative/path/to/Controller.cs",
"beMethod": "GetAll",
"beResponseType": "IList<OrderDto>",
"status": "valid|mismatch|missing-fe|missing-be",
"issues": []
}
],
"typeMapping": {
"serializationFormat": "System.Text.Json|Newtonsoft|json",
"casingConversion": "camelCase (auto)"
}
}
When asked to generate API contract docs (or after validating a full feature), write one compact doc per feature to .claude/idev/api-contracts/<feature>.md:
# Orders API Contract
> Updated: YYYY-MM-DD | Source: api-contract-validation
| Method | Endpoint | FE function | Request | Response | Status |
|--------|-----------------------|---------------|----------------|----------------|--------|
| GET | api/orders/get-all | getOrders | — | OrderDto[] | valid |
| POST | api/orders/create | createOrder | OrderCreateDto | OrderDto | valid |
| PUT | api/orders/update/{k} | updateOrder | OrderUpdateDto | OrderDto | type mismatch: key string↔Guid |
Notes:
- Auth: all endpoints require [Authorize]
- Casing: camelCase ↔ PascalCase (auto via System.Text.Json)
Rules:
.claude/idev/api-contract-validation/cache.json; generated docs live in .claude/idev/api-contracts/Creates bite-sized, testable implementation plans from specs or requirements, with file structure and task decomposition. Activates before coding multi-step tasks.
npx claudepluginhub theophiluschinomona/idev --plugin idev