npx skills add ...
npx skills add cloudflare/chanfana --skill write-endpoints
Comprehensive guide for building OpenAPI endpoints with chanfana - schema definition, request validation, CRUD operations, D1 database integration, and exception handling
npx skills add cloudflare/chanfana --skill write-endpoints
Use this skill when:
Define request validation for body, query, params, and headers:
Chanfana v3 uses Zod v4. Use the correct syntax:
Use native Zod schemas for all parameter types:
Always use await with getValidatedData():
In Zod v4, optional fields with .default() always have values in validated data. Use getUnvalidatedData() to detect what was actually sent:
All auto endpoints require a _meta property:
For composite primary keys in nested routes:
D1 endpoints extend CRUD endpoints with built-in database operations:
D1 endpoints include built-in security utilities:
| Exception | Status | Code | Default Message | Special Properties |
|---|---|---|---|---|
ApiException | 500 | 7000 | "Internal Error" | Base class |
InputValidationException | 400 | 7001 | "Input Validation Error" | path |
NotFoundException | 404 | 7002 | "Not Found" | - |
UnauthorizedException | 401 | 7003 | "Unauthorized" | - |
ForbiddenException | 403 | 7004 | "Forbidden" | - |
MethodNotAllowedException | 405 | 7005 | "Method Not Allowed" | - |
ConflictException | 409 | 7006 | "Conflict" | - |
UnprocessableEntityException | 422 | 7007 | "Unprocessable Entity" | path |
TooManyRequestsException | 429 | 7008 | "Too Many Requests" | retryAfter |
InternalServerErrorException | 500 | 7009 | "Internal Server Error" | isVisible: false |
BadGatewayException | 502 | 7010 | "Bad Gateway" | - |
ServiceUnavailableException | 503 | 7011 | "Service Unavailable" | retryAfter |
GatewayTimeoutException | 504 | 7012 | "Gateway Timeout" | - |
Basic Endpoints:
responses (required, even if just 200)contentJson() wrapper for JSON request/response bodiesawait this.getValidatedData<typeof this.schema>() for type-safe accessz.email() not z.string().email()):userId -> params: z.object({ userId: ... }))...ExceptionClass.schema() spreadCRUD Auto Endpoints:
_meta property is defined on the endpoint class_meta.model.schema is a valid Zod object schema_meta.model.primaryKeys is an array of primary key field names_meta.model.tableName is set (required for D1 endpoints)pathParameters in meta for composite primary keys_meta.tags is set to group related endpoints under OpenAPI tagsfilterFields, searchFields, orderByFields configured as neededD1 Endpoints:
dbName matches the binding name in wrangler.tomlconstraintsMessages defined for UNIQUE constraint handling{ Bindings: { DB: D1Database } }1. Missing contentJson wrapper
2. Not awaiting getValidatedData
3. Using Zod v3 syntax
4. Forgetting response schema
5. Primary key mismatch in nested routes
6. Optional fields with defaults in Zod v4
7. D1 binding name mismatch
8. Missing _meta in auto endpoints
9. Using nativeEnum in Zod v4