REST API Design with AI: Prompts and OpenAPI Spec Generation

What is AI-assisted REST API design?

AI-assisted REST API design is the process of using LLMs to generate OpenAPI 3.1 specifications, validate naming conventions, model error catalogs, and produce pagination contracts from a structured domain description and architectural constraints. It matters because manually writing OpenAPI YAML for 30+ endpoints takes hours and introduces inconsistencies that cost frontend teams debugging time. The key distinction: AI removes mechanical work (YAML authoring, example filling, naming checks) while architectural decisions — versioning strategy, error format, idempotency rules — remain with the engineer.

TL;DR

  • -An OpenAPI spec generated from a well-structured prompt produces 4 downstream artifacts automatically: TypeScript types (openapi-typescript), a typed client (openapi-fetch/orval), backend request validation middleware, and a mock server (Prism).
  • -The 3-stage iterative prompt pattern (base spec → enhancements → validation review) produces a production-ready spec in 15–20 minutes versus hours of manual YAML.
  • -400 vs 422 is a critical distinction: 400 = syntactically broken request (malformed JSON); 422 = well-formed but semantically invalid (business rule violation) — frontend handles these differently.
  • -Cursor-based pagination is stable under new data insertion (no duplicate records on page shift); offset-based pagination is simpler but breaks when records are added between page loads.
  • -URL-based versioning (/api/v1/) is the correct default for most projects — header-based versioning is cleaner in theory but untestable in a browser and harder to document.

A bad API is one of the main reasons frontend timelines blow up. Not bugs, not performance. Inconsistent endpoint names, unpredictable error responses, no documentation. A single flawed contract between backend and frontend burns dozens of hours on both sides.

AI changes how API design works. It doesn’t replace the architect — it handles the tedious parts: generating OpenAPI specs, validating naming conventions, modeling error responses. With the right prompts, an LLM produces a spec that a frontend developer can read without a single follow-up question.

Below is the full cycle: from design principles to a finished AI-generated OpenAPI spec. Every step includes a prompt and a concrete result.

REST API Design Principles That Save Time

Before opening a chat with AI, lock down the rules. LLMs only produce good specs when given clear constraints. Without them, you get inconsistent naming and mismatched responses — the exact problems you were trying to solve.

Resources, not actions. URLs describe nouns, HTTP methods describe actions. /users + GET instead of /getUsers. /orders/{id} + DELETE instead of /deleteOrder. It sounds obvious, but without an explicit rule AI often drifts into RPC-style endpoints: /createUser, /updateOrder.

Plural nouns for collections. /users, /products, /orders. Singular is only acceptable for singleton resources like /users/{id}/profile.

Two levels of nesting, max. /users/{userId}/orders is fine. /users/{userId}/orders/{orderId}/items/{itemId}/reviews is not. Deep nesting makes client code harder to write and breaks caching. Break it out instead: /order-items/{itemId}/reviews.

Consistent response format. Every endpoint returns data in the same wrapper. Frontend developers shouldn’t have to guess whether they’ll get { data: [...] } or a bare array. Pick one shape for success and one for errors — then never deviate.

Idempotency of PUT and DELETE. Calling PUT /users/123 repeatedly with the same data returns the same result. Repeated DELETE /users/123 returns 204 or 404, but produces no side effects. This is critical for frontend retry logic and circuit breaker patterns.

Naming Conventions: How AI Helps Maintain Consistency

Naming conventions determine whether your API is still readable six months from now. On a project with 50+ endpoints, you can’t maintain consistency manually. One developer writes userId, another user_id, a third UserID. The choice between a single API behind a monolith and many APIs across services is a separate concern — see the monolith vs. microservices comparison before deciding scope.

AI handles validation. Prompt for checking naming conventions:

Analyze the following list of REST API endpoints.
Check for compliance with these rules:
- URLs: kebab-case for compound words (/order-items, not /orderItems)
- Query parameters: camelCase (pageSize, sortBy)
- Request/Response body: camelCase for JSON fields
- Path parameters: camelCase ({userId}, not {user_id})
- Collections: plural nouns
- Nesting: no deeper than 2 levels

For each violation, specify: endpoint, rule, current form, corrected form.

Endpoints:
[paste list here]

Result: a table with specific corrections.

For generating new endpoints from a domain model:

Given the domain model:
- User (id, email, name, role)
- Project (id, title, ownerId, status)
- Task (id, projectId, assigneeId, title, status, priority)

Generate a list of REST endpoints for CRUD operations.
Rules:
- Base path: /api/v1
- Only necessary nested resources (1 level)
- For each endpoint: method, path, brief description, response codes

Format: Markdown table.

AI generates the full endpoint list in seconds. What’s left is reviewing the business logic: does PATCH /tasks/{id}/status warrant a dedicated endpoint, or does PATCH /tasks/{id} cover it?

Versioning Strategies for REST APIs

Three approaches to versioning. Each with trade-offs.

URL-based: /api/v1/users. The most common approach. Easy to implement, easy for frontend. Downside: bumping versions means updating every URL. For a public API, old versions may need to stay alive for years.

Header-based: Accept: application/vnd.api.v2+json. The URL stays clean; the version lives in a header. Downside: harder to test (you can’t just open it in a browser), harder to document.

Query parameter: /api/users?version=2. The URL is stable and the version is explicit. Downside: it pollutes query parameters and conflicts with URL-based caching.

Prompt for choosing a strategy based on project context:

Context:
- Internal API for a mobile app and web client
- 3 consumer teams
- Release cycle: every 2 weeks
- Public API planned in 6 months

Compare three REST API versioning strategies (URL path, header, query param).
For each: pros, cons, example.
Give a recommendation with reasoning for the described context.

For most projects, URL-based versioning is the right call. AI isn’t much help picking a strategy — the answer’s almost always the same — but it’s useful for planning version migrations and generating deprecation headers.

Error Handling: A Unified Error Format via AI

Error responses shape the developer experience more than successful ones. When something breaks, the developer opens DevTools. If all they see is 500 Internal Server Error with no details, debugging turns into guesswork.

The RFC 9457 error format (Problem Details for HTTP APIs) solves this:

{
  "type": "https://api.example.com/errors/validation",
  "title": "Validation Error",
  "status": 422,
  "detail": "Request body contains invalid fields",
  "instance": "/api/v1/users",
  "errors": [
    {
      "field": "email",
      "message": "Must be a valid email address",
      "code": "INVALID_FORMAT"
    },
    {
      "field": "name",
      "message": "Must be between 2 and 100 characters",
      "code": "INVALID_LENGTH"
    }
  ]
}

Prompt for generating a complete error catalog:

Generate an error catalog for a project management REST API.
Domain: Users, Projects, Tasks.

Requirements:
- Format: RFC 9457 (Problem Details)
- Categories: validation, authentication, authorization, not_found, conflict, rate_limit, internal
- For each error: type (URI), title, status code, example detail, error code (UPPER_SNAKE_CASE)
- Error codes must be unique and machine-readable

Output format: table with columns: Category, Error Code, Status, Title, Example Detail.

AI generates a catalog of 20–30 errors that covers the typical scenarios. Once it exists, it’s the contract. Frontend uses error.code for programmatic handling (INVALID_FORMAT triggers a field hint), error.detail for debugging.

Common status codes and when to use them:

StatusWhenExample
400Invalid JSON, missing required fieldsRequest body fails to parse
401Missing or invalid tokenExpired JWT
403Token is valid but lacks permissionsUser is not the project owner
404Resource not foundNo project with that ID
409State conflictEmail already registered
422Business rule validation failureCan’t delete a project with active tasks
429Rate limit exceededToo many requests

A common mix-up: 400 vs 422. 400 means the request is syntactically broken — malformed JSON. 422 means the request is well-formed but semantically wrong — an email that doesn’t pass validation. Frontend handles these differently, so the distinction matters.

Generating an OpenAPI Spec with AI

An OpenAPI (Swagger) spec turns an API description into an executable contract. Frontend generates types and a client. Backend validates requests against it. QA derives test cases from it.

Writing OpenAPI YAML by hand for 30+ endpoints takes hours. AI cuts that to minutes. The key is a well-structured prompt.

Step 1: Base Specification

Generate an OpenAPI 3.1 spec in YAML for a task management REST API.

Resources:
- Users: CRUD, fields (id, email, name, role, createdAt, updatedAt)
- Projects: CRUD + list by user, fields (id, title, description, status, ownerId, createdAt)
- Tasks: CRUD + list by project + update status, fields (id, title, description, status, priority, projectId, assigneeId, createdAt, updatedAt)

Requirements:
- Base path: /api/v1
- Authentication: Bearer JWT
- Pagination: cursor-based (query params: limit, cursor)
- Error format: RFC 9457
- Naming: kebab-case in URLs, camelCase in JSON body
- Reusable schemas in components/schemas
- Examples for every endpoint (requestBody + responses)
- Tags for grouping by resource

Step 2: Iterative Improvement

The first pass always needs work. Give AI specific problems and it handles iteration well:

Improve the generated OpenAPI spec:

1. Add rate limiting headers to every response (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset)
2. Add ETag and If-None-Match for GET endpoints
3. Add Link header for pagination (RFC 8288)
4. Ensure all 4xx/5xx responses use the shared ProblemDetails schema
5. Add a discriminator for the status field in Task (open, in_progress, done, cancelled)

Step 3: Validation

Review the OpenAPI spec for:
- Consistency of naming conventions
- Completeness of error documentation (all endpoints must describe 400, 401, 403, 500)
- Presence of examples for all requestBody and response objects
- Correct use of $ref (no duplicated schemas)
- Correctness of HTTP methods (GET has no body, DELETE returns 204)

Output a list of issues with line numbers and suggested fixes.

Three steps, 15–20 minutes total. A spec that would normally take hours.

Pagination, Filtering, and Sorting: A Contract for Frontend

Pagination affects how easy it is for the frontend to work with lists. Two approaches, each with a tradeoff.

Offset-based (?page=2&pageSize=20) is easy to implement. Frontend can show page numbers. The problem: when new records are added, pages shift. A user on page 3 might see something they already saw on page 2.

Cursor-based (?cursor=eyJpZCI6MTIzfQ&limit=20) is stable. The cursor points to a record, not a position. No duplicates when new data arrives. Downside: “page 5 of 12” is gone. Best suited for infinite scroll.

Prompt for generating filter query parameters:

For the Tasks resource with these fields:
- status: enum (open, in_progress, done, cancelled)
- priority: enum (low, medium, high, critical)
- assigneeId: UUID
- projectId: UUID
- createdAt: datetime
- updatedAt: datetime

Generate a set of query parameters for filtering and sorting.
Rules:
- Filters: exact match and ranges (for dates)
- Multiple values as comma-separated: ?status=open,in_progress
- Sorting: ?sort=createdAt:desc,priority:asc
- Pagination: cursor-based
- Parameter format: camelCase

Output a table: Parameter, Type, Description, Example.

The result is a finished contract. Frontend knows exactly what to send. Backend knows exactly what to parse.

Prompt for Full API Contract Generation

This prompt combines all the principles from above. Use it at project kickoff to produce the first version of the API contract, then iterate.

Role: Senior API Architect.

Task: design a REST API for [domain description].

Input:
- Domain model: [list of entities with fields and relationships]
- Consumers: [web client, mobile app, external integrations]
- Non-functional requirements: [RPS, latency, authorization]

Output format: OpenAPI 3.1 YAML.

Architectural decisions:
- Versioning: URL-based (/api/v1/)
- Auth: Bearer JWT + refresh tokens
- Pagination: cursor-based
- Error format: RFC 9457 (Problem Details)
- Naming: kebab-case URLs, camelCase JSON
- Idempotency: Idempotency-Key header for POST

For every endpoint, include:
1. Summary and description
2. All query/path/header parameters with descriptions
3. RequestBody schema with example
4. Response schemas for 2xx and all possible 4xx/5xx
5. Security requirements
6. Tags for grouping

Additional sections:
- components/schemas for all models (with required fields)
- components/securitySchemes
- components/parameters for reusable parameters (pagination, sorting)
- components/responses for standard errors

Style: production-ready, suitable for codegen (openapi-generator).

Think of it as a technical brief for the AI. Tighter constraints mean fewer iterations. More on how to structure context for LLMs in the context engineering guide.

API Design Validation: Checklist Before Handing Off to Frontend

Review the spec before handing it off to frontend. AI helps here too, but the final call is yours.

Prompt for a design review:

Review the REST API spec as a Senior Frontend Developer.
Evaluate against these criteria:

1. Predictability: consistent patterns for identical operations?
2. Self-documentation: are endpoint and field names understandable without descriptions?
3. Integration ease: can a typed client be generated?
4. Error handling: is there enough information to show to the user?
5. Pagination: is it practical to implement infinite scroll and table pagination?
6. Filtering: does it cover the main UI scenarios?
7. Caching: are ETag and Cache-Control present?

For each criterion: rating (OK / Needs improvement), specific note, example fix.

Manual checklist:

  • All endpoints follow the same naming style
  • HTTP methods match their semantics (GET does not change state)
  • Every POST returns the created resource with 201 Created and a Location header
  • PUT and PATCH are distinct: PUT replaces the full resource, PATCH updates specific fields
  • DELETE returns 204 (no body) or 200 (with the deleted resource)
  • All lists support pagination
  • Filter query parameters are documented with allowed values
  • Error responses include machine-readable codes (not just text)
  • Security scheme is applied to all endpoints (except public ones)
  • No circular references in schemas

Automation: From Specification to Code

An AI-generated OpenAPI spec is where automation starts.

Frontend type generation. openapi-typescript reads the YAML and produces TypeScript types. Frontend developers get autocomplete for every response field.

npx openapi-typescript ./openapi.yaml -o ./src/api/types.ts

API client generation. openapi-fetch or orval generate a typed client with compile-time request validation.

Backend validation. Middleware checks incoming requests and outgoing responses against the schema. Contract violations get caught before they reach production.

Mock server. prism from Stoplight spins up a mock API straight from the OpenAPI file. Frontend can start integration before backend is done.

npx @stoplight/prism-cli mock openapi.yaml

One spec, four artifacts: types, a client, request validation, and a mock server. Frontend and backend can work in parallel without waiting on each other.

Takeaways: API Design as Engineering Discipline

REST API design with an AI assistant follows a clear sequence:

  1. Lock down principles and naming conventions before generating anything
  2. Generate a base OpenAPI spec via a structured prompt
  3. Iterate: error handling, pagination, headers
  4. Review from a frontend developer’s perspective — or ask AI to take that role
  5. Automate: types, client, mock server from a single spec

AI doesn’t replace knowing API design. It removes the tedious work: writing YAML, checking naming, filling in examples. The architectural calls — cursor vs. offset, URL vs. header versioning, error format — still belong to the engineer, and should be documented as Architecture Decision Records so the rationale survives team changes.

A spec built this way becomes the single source of truth. The same pattern of structured AI prompting works for generating a database schema from a PRD — different artifact, same discipline of locking down constraints before generation. Frontend knows the exact response format. Backend knows what to validate. QA knows what to test. One file instead of a thread of Slack messages asking “what does this endpoint actually return.”


Need help with API design and development? I help startups build AI products and automate processes — belov.works.

Frequently Asked Questions

How do you version a REST API without breaking existing clients when you need to change a response schema?
The safest path is additive-only changes in a minor version: add new fields, never remove or rename existing ones. Removing a field is a breaking change that requires a new major version (/api/v2/). If you must change a field's type or semantics, introduce the new field under a new name alongside the old one, deprecate the old field with a Sunset header and deprecation notice in the OpenAPI spec, then remove it in the next major version after a published sunset date. Tools like openapi-diff can automatically detect breaking changes in CI before a PR merges.
When should an API return 200 with an error in the response body instead of a proper 4xx status code?
Almost never. Embedding error information in a 200 response (sometimes called "200 OK with error") breaks HTTP semantics, breaks monitoring tools that alert on 4xx/5xx rates, and forces clients to parse the body before they know whether the request succeeded. The only legitimate use case is batch endpoints where a single request processes multiple items — some may succeed (200) and others fail, requiring a mixed-result response. For all other cases, use the correct HTTP status code and the RFC 9457 Problem Details format in the response body.
What is the right way to handle file uploads in a REST API designed with OpenAPI?
Use multipart/form-data for file uploads, not application/json. In OpenAPI 3.1, define the requestBody with content: multipart/form-data and a schema with a format: binary property for the file field. For large files (over 5 MB), consider a two-step upload pattern: the client requests a pre-signed upload URL from the API, uploads directly to object storage (S3, GCS) using the pre-signed URL, then notifies the API with the storage reference. This keeps large binary data out of your application servers and API gateway entirely, improving reliability and reducing infrastructure load.