AI Text-to-API Generation Development

We design and deploy artificial intelligence systems: from prototype to production-ready solutions. Our team combines expertise in machine learning, data engineering and MLOps to make AI work not in the lab, but in real business.
Showing 1 of 1 servicesAll 1566 services
AI Text-to-API Generation Development
Complex
~1-2 weeks
FAQ
AI Development Areas
AI Solution Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1240
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1167
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    867
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1084
  • image_logo-advance_0.png
    B2B Advance company logo design
    563
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    829

AI API Generation from Text Descriptions (Text-to-API)

Text-to-API is the generation of a full REST/GraphQL API layer from natural language description or OpenAPI specification. The task is broader than just writing endpoints: you need data models, validation, middleware, tests, documentation. AI acts as a junior developer with strong FastAPI/Express knowledge who writes at thousands of lines per minute.

API Generator Architecture

from anthropic import Anthropic
from pathlib import Path
import json
from pydantic import BaseModel
from typing import Literal, Optional

client = Anthropic()

class APIEndpoint(BaseModel):
    method: Literal["GET", "POST", "PUT", "PATCH", "DELETE"]
    path: str
    summary: str
    request_body: Optional[dict] = None
    response_schema: dict
    auth_required: bool = True
    query_params: list[dict] = []

class APISpec(BaseModel):
    title: str
    description: str
    version: str
    base_path: str
    endpoints: list[APIEndpoint]
    entities: list[dict]  # Business entities

class TextToAPIGenerator:

    def parse_description(self, description: str) -> APISpec:
        """Parses text description into structured specification"""

        response = client.messages.create(
            model="claude-sonnet-4-5",
            max_tokens=4096,
            system="""You are an API architect. Parse system description into REST API structure.

REST Rules:
- Nouns in URLs (not verbs): /users, /orders
- Correct HTTP methods: GET=read, POST=create, PUT=full replace, PATCH=partial update, DELETE=delete
- Max nesting 2 levels: /users/{id}/orders
- Plural for collections: /products, /categories
- Pagination: ?page=1&limit=20
- Filtering: ?status=active&created_after=2024-01-01""",
            messages=[{
                "role": "user",
                "content": f"""Parse description and return JSON API specification:

{{
  "title": "...",
  "description": "...",
  "version": "1.0.0",
  "base_path": "/api/v1",
  "entities": [
    {{"name": "...", "fields": [{{"name": "...", "type": "...", "required": true}}]}}
  ],
  "endpoints": [
    {{
      "method": "GET|POST|PUT|PATCH|DELETE",
      "path": "/resource/{{id}}",
      "summary": "...",
      "auth_required": true,
      "request_body": {{"field": "type"}},
      "response_schema": {{"id": "int", "name": "str"}},
      "query_params": [{{"name": "...", "type": "...", "required": false}}]
    }}
  ]
}}

System description:
{description}"""
            }]
        )

        text = response.content[0].text
        start = text.find("{")
        end = text.rfind("}") + 1
        data = json.loads(text[start:end])
        return APISpec(**data)

    def generate_fastapi_code(self, spec: APISpec) -> dict[str, str]:
        """Generates complete FastAPI project"""

        files = {}

        # models.py
        files["models.py"] = self._generate_models(spec)

        # schemas.py
        files["schemas.py"] = self._generate_schemas(spec)

        # routers/{resource}.py for each entity
        for entity in spec.entities:
            router_code = self._generate_router(entity, spec)
            files[f"routers/{entity['name'].lower()}.py"] = router_code

        # main.py
        files["main.py"] = self._generate_main(spec)

        # tests/
        for entity in spec.entities:
            test_code = self._generate_tests(entity, spec)
            files[f"tests/test_{entity['name'].lower()}.py"] = test_code

        return files

    def _generate_models(self, spec: APISpec) -> str:
        """Generates SQLAlchemy models"""

        response = client.messages.create(
            model="claude-sonnet-4-5",
            max_tokens=4096,
            messages=[{
                "role": "user",
                "content": f"""Create SQLAlchemy 2.0 models for entities:

Entities:
{json.dumps(spec.entities, ensure_ascii=False, indent=2)}

Requirements:
- Use DeclarativeBase
- Add id (Integer PK autoincrement), created_at, updated_at for all models
- Use correct types: String(256), Text, Integer, Float, Boolean, DateTime
- Add __tablename__
- Add relationship() for model relationships
- Add __repr__ for debugging

Return only Python code."""
            }]
        )

        return response.content[0].text.strip()

    def _generate_schemas(self, spec: APISpec) -> str:
        """Generates Pydantic v2 schemas"""

        response = client.messages.create(
            model="claude-sonnet-4-5",
            max_tokens=4096,
            messages=[{
                "role": "user",
                "content": f"""Create Pydantic v2 schemas for validation:

Entities: {json.dumps(spec.entities, ensure_ascii=False)}
Endpoints: {json.dumps([e.dict() for e in spec.endpoints], ensure_ascii=False)}

For each entity create:
- <Entity>Create — for POST (all required fields)
- <Entity>Update — for PATCH (all fields Optional)
- <Entity>Response — for responses (including id, created_at)
- <Entity>ListResponse — with pagination

Add field validators where needed (email format, positive numbers, string lengths).

Return only Python code."""
            }]
        )

        return response.content[0].text.strip()

    def _generate_router(self, entity: dict, spec: APISpec) -> str:
        """Generates router with CRUD endpoints"""

        entity_endpoints = [
            e for e in spec.endpoints
            if entity["name"].lower() in e.path.lower()
        ]

        response = client.messages.create(
            model="claude-sonnet-4-5",
            max_tokens=4096,
            messages=[{
                "role": "user",
                "content": f"""Create FastAPI router for entity {entity['name']}.

Endpoints to implement:
{json.dumps([e.dict() for e in entity_endpoints], ensure_ascii=False, indent=2)}

Requirements:
- Use APIRouter with prefix and tags
- Dependency injection for DB session (AsyncSession)
- Dependency injection for authorization (get_current_user)
- Async/await for all operations
- Correct HTTP statuses: 201 for POST, 204 for DELETE, 404 if not found
- Pagination via query params page/limit
- Logging via structlog

Return only Python code."""
            }]
        )

        return response.content[0].text.strip()

    def _generate_main(self, spec: APISpec) -> str:
        return f"""from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from contextlib import asynccontextmanager

{chr(10).join(f"from routers.{e['name'].lower()} import router as {e['name'].lower()}_router" for e in spec.entities)}

@asynccontextmanager
async def lifespan(app: FastAPI):
    # Startup
    yield
    # Shutdown

app = FastAPI(
    title="{spec.title}",
    description="{spec.description}",
    version="{spec.version}",
    lifespan=lifespan,
)

app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"])

{chr(10).join(f'app.include_router({e["name"].lower()}_router, prefix="{spec.base_path}")' for e in spec.entities)}
"""

    def _generate_tests(self, entity: dict, spec: APISpec) -> str:
        """Generates pytest tests for CRUD endpoints"""

        response = client.messages.create(
            model="claude-sonnet-4-5",
            max_tokens=2048,
            messages=[{
                "role": "user",
                "content": f"""Create pytest tests for CRUD endpoints of entity {entity['name']}.

Use:
- pytest-asyncio for async tests
- httpx.AsyncClient for HTTP requests
- pytest fixtures for setup/teardown
- TestDatabase (SQLite in-memory) for isolation

Cover: creation, list reading, single reading, update, delete, 404 cases, input validation.

Return only Python code."""
            }]
        )

        return response.content[0].text.strip()

CLI Interface

import click
import yaml

@click.command()
@click.argument("description_file", type=click.Path(exists=True))
@click.option("--output-dir", "-o", default="./generated_api")
@click.option("--framework", default="fastapi", type=click.Choice(["fastapi", "express"]))
def generate_api(description_file: str, output_dir: str, framework: str):
    """Generates API from text description"""

    description = Path(description_file).read_text()
    generator = TextToAPIGenerator()

    click.echo("Parsing description...")
    spec = generator.parse_description(description)
    click.echo(f"Found {len(spec.endpoints)} endpoints, {len(spec.entities)} entities")

    click.echo("Generating code...")
    files = generator.generate_fastapi_code(spec)

    output_path = Path(output_dir)
    output_path.mkdir(parents=True, exist_ok=True)

    for filename, content in files.items():
        file_path = output_path / filename
        file_path.parent.mkdir(parents=True, exist_ok=True)
        file_path.write_text(content)
        click.echo(f"  Created: {filename}")

    # Generate docker-compose and requirements.txt
    _generate_project_files(output_path, spec)

    click.echo(f"\nAPI generated in {output_dir}")
    click.echo("Run: cd generated_api && docker-compose up")

if __name__ == "__main__":
    generate_api()

Description Example for Generation

# Task Management System

Multi-user system for teams.

Entities:
- User: email (unique), name, role (admin/member), avatar_url
- Team: name, description, owner_id
- Project: name, description, team_id, status (active/archived)
- Task: title, description, project_id, assignee_id, status (todo/in_progress/done), priority (low/medium/high), due_date

Functionality:
- Registration and authorization (JWT)
- CRUD for teams, projects, tasks
- Task assignment to team members
- Filter tasks by status, assignee, priority
- Pagination for all lists
- Soft delete for tasks

Practical Case: Internal B2B Product

Task: startup wanted MVP backend for service marketplace in 2 weeks. 8 main entities, 45+ endpoints.

Generation:

  • 2-page product description → APISpec (30 seconds)
  • FastAPI code generation (7 files + tests) → 8 minutes
  • Manual customization of authorization business logic → 3 days
  • Payment gateway integration → 2 days

Result: working MVP in 5 days instead of planned 14. Test coverage 67% (tests auto-generated).

What AI generates well: CRUD, pagination, validation, project structure, happy path tests.

What needs hands-on: complex authorization logic, specific pricing algorithms, non-trivial SQL queries with window functions.

Timeline

  • Generator prototype (description → one file): 2–3 days
  • Full project generation with tests: 1–2 weeks
  • Support additional frameworks (Express, Django REST): +1 week each
  • CI/CD integration for regeneration on spec changes: 1 week