Text-to-API: перетворюємо опис у готовий REST API
Розробка API з нуля — процес, де кожна помилка в дизайні або моделях даних виливається в години переписування коду. Ми стикалися з проєктами, де команди витрачали тижні на створення CRUD і документації, а бізнес-логіка залишалася незакритою. Text-to-API вирішує це: ви описуєте систему словами — ми генеруємо готовий код на FastAPI або Express з тестами, Docker і документацією. Наш досвід показує, що time-to-market скорочується в 3–5 разів, а витрати на шаблонний код — до 80%.
"Text-to-API економить до 80% часу на CRUD-операціях" — з досвіду наших проєктів.
Проблеми, які вирішує Text-to-API
Чому AI-генерація швидша?
Ручне написання ендпоїнтів, моделей даних, схем валідації та тестів займає до 70% часу бекенд-розробника. AI бере на себе шаблонну роботу: парсить опис, будує специфікацію OpenAPI, генерує моделі Pydantic, роутери та тести. Залишається лише бізнес-логіка, яка дійсно потребує уваги.
Які проблеми вирішуємо?
- Дизайн API. Неправильні URL, методи HTTP, статуси відповіді — часта біль. AI дотримується REST-конвенцій: іменники у множині, правильні коди (201 для POST, 204 для DELETE).
- Моделі та схеми. Узгодження типів полів, обов'язковості, вкладеності. Генератор створює SQLAlchemy моделі та Pydantic схеми з валідаторами.
- Тестування. Автоматично генеруються pytest-тести для кожного ендпоїнта, що покривають happy path, 404, валідацію вхідних даних. Тестове покриття сягає 70%.
Архітектура генератора та стек
В основі — мовні моделі (Claude, GPT-4) з тонким налаштуванням промптів через LangChain. Специфікація API парситься в Pydantic-моделі, потім генерується код. Використовуємо структурний вивід: модель повертає валідний JSON, який перетворюється на APISpec.
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] class TextToAPIGenerator: def parse_description(self, description: str) -> APISpec: response = client.messages.create( model="claude-sonnet-4-5", max_tokens=4096, system="""Ты — API-архитектор. Парсишь описание системы в структуру REST API. Правила REST: - Существительные в URL (не глаголы): /users, /orders - Правильные HTTP методы: GET=чтение, POST=создание, PUT=полная замена, PATCH=частичное обновление, DELETE=удаление - Вложенность максимум 2 уровня: /users/{id}/orders - Plural для коллекций: /products, /categories - Пагинация: ?page=1&limit=20 - Фильтрация: ?status=active&created_after=2024-01-01""", messages=[{ "role": "user", "content": f"""Разбери описание и верни JSON спецификацию API: {{ "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}}] }} ] }} Описание системы: {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]: files = {} files["models.py"] = self._generate_models(spec) files["schemas.py"] = self._generate_schemas(spec) for entity in spec.entities: router_code = self._generate_router(entity, spec) files[f"routers/{entity['name'].lower()}.py"] = router_code files["main.py"] = self._generate_main(spec) 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: response = client.messages.create( model="claude-sonnet-4-5", max_tokens=4096, messages=[{ "role": "user", "content": f"""Создай SQLAlchemy 2.0 модели для сущностей: Сущности: {json.dumps(spec.entities, ensure_ascii=False, indent=2)} Требования: - Используй DeclarativeBase - Добавь id (Integer PK autoincrement), created_at, updated_at для всех моделей - Используй правильные типы: String(256), Text, Integer, Float, Boolean, DateTime - Добавь __tablename__ - Добавь relationship() для связей между моделями - Добавь __repr__ для дебага Верни только Python код.""" }] ) return response.content[0].text.strip() def _generate_schemas(self, spec: APISpec) -> str: response = client.messages.create( model="claude-sonnet-4-5", max_tokens=4096, messages=[{ "role": "user", "content": f"""Создай Pydantic v2 схемы для валидации: Сущности: {json.dumps(spec.entities, ensure_ascii=False)} Endpoints: {json.dumps([e.dict() for e in spec.endpoints], ensure_ascii=False)} Для каждой сущности создай: - <Entity>Create — для POST (все обязательные поля) - <Entity>Update — для PATCH (все поля Optional) - <Entity>Response — для ответов (включая id, created_at) - <Entity>ListResponse — с пагинацией Добавь field validators где нужно (email формат, позитивные числа, длина строк). Верни только Python код.""" }] ) return response.content[0].text.strip() def _generate_router(self, entity: dict, spec: APISpec) -> str: 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"""Создай FastAPI роутер для сущности {entity['name']}. Endpoints для реализации: {json.dumps([e.dict() for e in entity_endpoints], ensure_ascii=False, indent=2)} Требования: - Используй APIRouter с prefix и tags - Dependency injection для DB session (AsyncSession) - Dependency injection для авторизации (get_current_user) - Async/await для всех операций - Правильные HTTP статусы: 201 для POST, 204 для DELETE, 404 если не найдено - Пагинация через query params page/limit - Логирование через structlog Верни только Python код.""" }] ) 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: response = client.messages.create( model="claude-sonnet-4-5", max_tokens=2048, messages=[{ "role": "user", "content": f"""Создай pytest тесты для CRUD endpoints сущности {entity['name']}. Используй: - pytest-asyncio для async тестов - httpx.AsyncClient для HTTP запросов - pytest fixtures для setup/teardown - TestDatabase (SQLite in-memory) для изоляции Покрой: создание, чтение списка, чтение одного, обновление, удаление, 404 случаи, валидацию входных данных. Верни только Python код.""" }] ) return response.content[0].text.strip() CLI-інтерфейс для швидкого старту
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): 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_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() Приклад опису для генерації
# Система керування задачами Багатокористувацька система для команд. Сутності: - User: email (унікальний), 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 Функціональність: - Реєстрація та авторизація (JWT) - CRUD для команд, проєктів, задач - Призначення задач учасникам команди - Фільтрація задач за статусом, виконавцем, пріоритетом - Пагінація всіх списків - Soft delete для задач Практичний кейс
Клієнт — B2B-стартап, якому потрібно було отримати MVP backend для маркетплейсу послуг за 2 тижні. 8 сутностей, 45+ ендпоїнтів.
Генерація:
- Опис продукту (2 сторінки) → APISpec за кілька секунд
- Генерація коду FastAPI (7 файлів + тести) — кілька хвилин
- Ручне доопрацювання авторизації — 3 дні
- Інтеграція платіжного шлюзу — 2 дні
Результат: працюючий MVP через 5 днів замість 14. Тестове покриття — 67% (згенеровано автоматично). Скоротили бюджет на розробку в 3 рази.
AI чудово справляється з CRUD, пагінацією, валідацією, структурою проєкту та тестами happy path. Ручного втручання потребують складні бізнес-правила, алгоритми ціноутворення та нетривіальні SQL-запити.
Процес роботи, терміни та результати
Етапи
- Аналіз вимог — вивчаємо опис, уточнюємо деталі, фіксуємо специфікацію.
- Генерація специфікації — AI парсить опис у APISpec (сутності, ендпоїнти, типи).
- Генерація коду — створюємо повний проєкт: моделі, схеми, роутери, тести, Docker.
- Тестування — запускаємо тести, виправляємо помилки, додаємо відсутні кейси.
- Деплой і документація — готуємо інструкцію, CI/CD (опціонально).
Терміни та вартість
Терміни залежать від складності проєкту:
- Прототип (один файл) — від 2 днів
- Повний проєкт з тестами — від 1 до 2 тижнів
- Додавання підтримки нового фреймворку — +1 тиждень
- Інтеграція в CI/CD — 1 тиждень
Вартість розраховується індивідуально. Зв'яжіться з нами для оцінки вашого проєкту.
Що ви отримуєте в результаті
| Компонент | Деталі |
|---|---|
| Специфікація | OpenAPI 3.0 (YAML/JSON) |
| Бекенд-код | FastAPI/Express з моделями, схемами, роутерами |
| Тести | pytest з покриттям до 70% |
| Документація | README, інструкція по запуску |
| Інфраструктура | Docker Compose, requirements.txt |
Порівняння ручної розробки та AI-генерації
| Критерій | Ручна розробка | AI-генерація |
|---|---|---|
| Час на CRUD | 3-5 днів | 2-10 хвилин |
| Тестове покриття | 40-60% | до 70% |
| Ризик помилок в моделях | високий | низький (дотримується конвенцій) |
| Документація | пишеться окремо | генерується автоматично |
Типові помилки при AI-генерації API
- Відсутність авторизації. AI не знає вашу систему ролей — потребує ручного налаштування.
- Неправильні HTTP статуси. Іноді модель генерує 200 замість 201 для POST — важливо перевірити.
- Пропущена валідація. Для специфічних бізнес-правил (унікальність email) потрібно додавати кастомні перевірки.
- Недостатнє тестування. Тести покривають happy path, але граничні випадки залишаються за кадром.
Наші інженери мають сертифікати AWS та досвід в AI-генерації коду більше 5 років. Гарантуємо відповідність найкращим практикам REST та повну документацію. Замовте демо-генерацію API за вашим описом — переконайтеся самі.







