APIs are the backbone of modern systems, and AI-assisted API design accelerates their creation, consistency, and correctness. When teams need to define a new API endpoint quickly—especially under time pressure, with evolving requirements, or with minimal documentation—AI can propose shapes, constraints, error codes, and even full contracts from natural language descriptions, input payloads, or existing code. This guide covers the practical workflow of designing APIs with AI assistance, from initial specification to validation and integration.
Designing an API from Natural Language
When a product manager or developer writes a specification in plain English, AI can generate a complete API contract. The key is to provide clear, self-contained input with minimal ambiguity.
Start with a prompt in a structured format:
Create a REST API endpoint to manage user profiles. The endpoint should support:
- Creating a new profile with name, email, and optional bio
- Retrieving a profile by ID
- Updating any subset of fields
- Searching profiles by name or email
- Returning a consistent response structure with metadata
Use curl to send this prompt to an AI service that understands OpenAPI (Swagger) specifications. The service expects a JSON body with a prompt field and returns an OpenAPI 3.0 document.
curl -X POST https://ai-api.example.com/openapi \
-H "Content-Type: application/json" \
-d '{
"prompt": "Create a REST API endpoint to manage user profiles. The endpoint should support:\n- Creating a new profile with name, email, and optional bio\n- Retrieving a profile by ID\n- Updating any subset of fields\n- Searching profiles by name or email\n- Returning a consistent response structure with metadata",
"format": "openapi",
"schema": {
"title": "User Profiles API",
"version": "1.0.0"
}
}'
The AI returns a full OpenAPI document. A typical response includes paths, components, info, and servers:
{
"openapi": "3.0.3",
"info": {
"title": "User Profiles API",
"version": "1.0.0"
},
"servers": [
{
"url": "https://api.example.com/v1"
}
],
"paths": {
"/profiles": {
"post": {
"summary": "Create a new user profile",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateProfileRequest"
}
}
}
},
"responses": {
"201": {
"description": "Profile created successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProfileResponse"
}
}
}
}
}
},
"get": {
"summary": "Search profiles by name or email",
"parameters": [
{
"name": "q",
"in": "query",
"schema": { "type": "string" },
"description": "Search term for name or email"
},
{
"name": "limit",
"in": "query",
"schema": { "type": "integer", "default": 10, "minimum": 1, "maximum": 100 }
}
],
"responses": {
"200": {
"description": "List of matching profiles",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProfileListResponse"
}
}
}
}
}
}
},
"/profiles/{id}": {
"get": {
"summary": "Retrieve a profile by ID",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": { "type": "string" }
}
],
"responses": {
"200": {
"description": "Profile found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProfileResponse"
}
}
}
},
"404": {
"description": "Profile not found"
}
}
},
"patch": {
"summary": "Update a profile partially",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": { "type": "string" }
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateProfileRequest"
}
}
}
},
"responses": {
"200": {
"description": "Profile updated"
},
"400": {
"description": "Invalid update payload"
}
}
}
}
},
"components": {
"schemas": {
"CreateProfileRequest": {
"type": "object",
"required": ["name", "email"],
"properties": {
"name": { "type": "string", "minLength": 1 },
"email": { "type": "string", "format": "email" },
"bio": { "type": "string", "nullable": true }
}
},
"UpdateProfileRequest": {
"type": "object",
"properties": {
"name": { "type": "string" },
"email": { "type": "string", "format": "email" },
"bio": { "type": "string", "nullable": true }
}
},
"ProfileResponse": {
"type": "object",
"properties": {
"id": { "type": "string" },
"name": { "type": "string" },
"email": { "type": "string" },
"bio": { "type": "string", "nullable": true },
"createdAt": { "type": "string", "format": "date-time" },
"updatedAt": { "type": "string", "format": "date-time" },
"metadata": {
"type": "object",
"properties": {
"version": { "type": "string" }
}
}
}
},
"ProfileListResponse": {
"type": "object",
"properties": {
"profiles": {
"type": "array",
"items": { "$ref": "#/components/schemas/ProfileResponse" }
},
"total": { "type": "integer" },
"page": { "type": "integer" },
"pageSize": { "type": "integer" }
}
}
}
}
}
The generated OpenAPI spec is ready to be used with openapi-generator, swagger-ui, or apidoc. The AI has inferred path parameters, query filters, and error responses without explicit instruction.
Common Pitfalls
- Ambiguous field names: A prompt saying “include user details” often leads to
userDetailsinstead ofdetails, oruservsprofile. Use explicit terms: “useprofileId, notuserId, for the profile identifier.” - Inconsistent response shapes: The AI may return
200withdataand201withprofile, leading to inconsistent client code. Always add ametadatasection to standardize responses. - Missing query parameters: Search endpoints often omit
limitandoffset, or misplaceqandsearch. Explicitly list required query parameters in the prompt. - Error codes not aligned: AI often returns
400for invalid input but forgets404for missing resources. Add: “Include error responses for400,404,409, and500.”
Validating and Refining the API
Once the AI generates the API, validate it against real data and refine the design.
Use openapi-lint to enforce consistency across multiple APIs:
npm install -g openapi-lint
openapi-lint --config .openapi-lint.json profile-api.yaml
The configuration file .openapi-lint.json defines rules:
{
"rules": {
"operationId": {
"required": true,
"format": "camelCase"
},
"pathParameters": {
"required": true,
"type": "string"
},
"responseCodes": {
"expected": [200, 201, 400, 404, 422, 500]
},
"schema": {
"required": ["title", "description"]
}
},
"ignored": [
"paths/*/parameters/*",
"components/schemas/ProfileResponse/metadata"
]
}
Run it on the AI-generated spec:
openapi-lint --config .openapi-lint.json openapi.yaml
Output:
openapi.yaml:12: error: Operation 'get /profiles/{id}' is missing operationId
openapi.yaml:25: warning: Response 400 should include 'title' and 'details' in error schema
openapi.yaml:100: error: Schema 'ProfileResponse' is missing description
For each failure, update the AI prompt with a refinement:
Refine the existing API to:
- Add operationId to all endpoints, using 'verbResource' format
- Ensure all 4xx responses include 'title' and 'details' fields
- Add a description to each schema, especially ProfileResponse and ProfileListResponse
- Use 'page' and 'size' instead of 'limit' and 'offset' for pagination
Send this refined prompt to the AI service:
curl -X POST https://ai-api.example.com/openapi \
-H "Content-Type: application/json" \
-d '{
"prompt": "Refine the existing API to:\n- Add operationId to all endpoints, using ''verbResource'' format\n- Ensure all 4xx responses include ''title'' and ''details'' fields\n- Add a description to each schema, especially ProfileResponse and ProfileListResponse\n- Use ''page'' and ''size'' instead of ''limit'' and ''offset'' for pagination",
"input": "openapi.yaml",
"format": "openapi"
}'
The AI returns an updated OpenAPI document with corrected structures and new fields.
Integrating the API into Code
Generate server code from the refined OpenAPI document using openapi-generator:
openapi-generator generate \
-i openapi.yaml \
-g nodejs-express-server \
-o ./api-server \
--package-name "user-profiles-api" \
--api-package "api" \
--model-package "models" \
--additional-properties=withInterfaces=true,usePromises=true
The generated code includes:
api/profilesApi.ts: interface definitions for the APImodels/ProfileResponse.ts: TypeScript interfaces for response structurescontrollers/profilesController.ts: route handlers for each endpoint
Check controllers/profilesController.ts:
export async function createProfile(
req: Request,
res: Response
): Promise<void> {
const { name, email, bio } = req.body;
const profile = await createProfileService({ name, email, bio });
res.status(201).json({
id: profile.id,
name: profile.name,
email: profile.email,
bio: profile.bio,
createdAt: profile.createdAt,
updatedAt: profile.updatedAt,
metadata: {
version: "1.0.0"
}
});
}
The AI has correctly inferred the metadata.version field and structured the 201 response.
Silent Failures in Integration
- Missing
metadatain201response: The AI generates201withid,name,email, but forgetsmetadata. The client expectsmetadata.version, but it’snull. The issue is subtle: the AI assumesmetadatais optional but not required. - Incorrect
400response shape: The AI returns400withmessageandcode, but the client expectstitleanddetails. The server must mapmessage→title,code→details, or update the OpenAPI spec. pageandsizeconfusion: The AI usespageandsize, but the client expectspageandpageSize. The server must normalizepageSize→size, or the OpenAPI spec must clarify the mapping.
Automating the Workflow
Create a CI pipeline that runs AI-assisted API design automatically.
Use GitHub Actions to trigger API generation on api/openapi.yaml changes:
name: AI-Assisted API Design
on:
push:
paths:
- "api/openapi.yaml"
jobs:
ai-design:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Generate API from AI
run: |
curl -X POST https://ai-api.example.com/openapi \
-H "Content-Type: application/json" \
-d '{
"prompt": "Refine the existing API to:\n- Add operationId to all endpoints, using ''verbResource'' format\n- Ensure all 4xx responses include ''title'' and ''details'' fields\n- Add a description to each schema, especially ProfileResponse and ProfileListResponse\n- Use ''page'' and ''size'' instead of ''limit'' and ''offset'' for pagination",
"input": "api/openapi.yaml",
"format": "openapi"
}' \
-o api/openapi-ai.yaml
- name: Validate API
run: |
npm install -g openapi-lint
openapi-lint --config .openapi-lint.json api/openapi-ai.yaml
- name: Generate Server Code
run: |
openapi-generator generate \
-i api/openapi-ai.yaml \
-g nodejs-express-server \
-o ./api-server \
--package-name "user-profiles-api" \
--api-package "api" \
--model-package "models" \
--additional-properties=withInterfaces=true,usePromises=true
- name: Commit and Push
run: |
git config --local user.email "[email protected]"
git config --local user.name "AI API Bot"
git add api/openapi-ai.yaml api-server
git commit -m "AI: refine and generate API code"
git push
This workflow ensures every API change is reviewed, validated, and implemented with AI assistance.
Final Checks Before Production
Before deploying the API, verify:
- All error responses include
titleanddetails 200and201responses includemetadatawithversion- Pagination uses
pageandsize, notlimitandoffset PATCH /profiles/{id}supports partial updates withnullvalues for optional fieldsGET /profilesreturnstotalandpagein theProfileListResponse
Use curl to test each endpoint:
curl -X GET "https://api.example.com/v1/profiles?q=john&size=5&page=2" \
-H "Accept: application/json"
Expected response:
{
"profiles": [
{
"id": "u123",
"name": "John Doe",
"email": "[email protected]",
"bio": "Software engineer",
"createdAt": "2024-06-01T10:00:00Z",
"updatedAt": "2024-06-10T15:30:00Z",
"metadata": {
"version": "1.0.0"
}
}
],
"total": 12,
"page": 2,
"pageSize": 5
}
If pageSize is missing or metadata.version is null, the API is not fully aligned with the AI-generated contract.
When to Use AI-Assisted API Design
- Rapid prototyping: When a new API is needed within a sprint, and team members are not API experts.
- Onboarding: Onboarding new developers by having AI generate a consistent API standard.
- Refactoring existing APIs: When a monolith is being split into microservices.
- Cross-team collaboration: When multiple teams define APIs that must interoperate.
The workflow is most effective when the team uses a shared OpenAPI document, and the AI is the central engine for specification, validation, and code generation.
This page was rewritten on 11 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.
Join the Newsletter
Get the latest updates and deep insights shipped directly to your inbox.