12 типів PDF-репортів — natal, transit-yearly, synastry, business, career, love, money, child, lal-kitab, human-design, tarot, vedic-kundli — донедавна жили як 12 окремих роутів. Кожен має свою схему, свій chart-payload, свій pricing tier. Це чесно по REST-канону, але створює DX-проблему на двох рівнях:
- SDK surface. TypeScript-клієнт носить 12 методів
client.reports.natal(),client.reports.synastry(), … Кожен новий тип репорту = breaking change у public API SDK (мінорна версія з новим методом). - MCP-каталог. Hosted MCP-сервер експонує 686 інструментів — кожен з 12 reports займає окремий tool entry. AI-агент, який ходить через MCP, має просканувати 12 tool descriptions, щоб обрати правильний. Це шум у tool selection.
Новий ендпоінт POST /v1/reports/generate — один dispatcher з report_type enum.
API контракт
Section titled “API контракт”curl -X POST https://api.astroway.info/v1/reports/generate \ -H "X-Api-Key: aw_live_..." \ -H "Content-Type: application/json" \ -d '{ "report_type": "natal", "chart": { "date": "1990-05-15", "time": "14:30", "timezoneOffset": 3, "latitude": 50.45, "longitude": 30.52, "name": "Test" }, "language": "uk", "whitelabel": { "themeColor": "#ff5500", "reportName": "My Cosmic Map" } }'12 валідних значень report_type: natal, transit-yearly, synastry, business, career, love, money, child, lal-kitab, human-design, tarot, vedic-kundli.
Per-type валідація
Section titled “Per-type валідація”Різні типи потребують різних payload-полів. Dispatcher робить валідацію у handler-і й повертає типізований 400:
report_type | Required fields | Error code на missing |
|---|---|---|
natal, business, career, love, money, child, lal-kitab, human-design, vedic-kundli, transit-yearly | chart | MISSING_CHART |
synastry | chart1, chart2 | MISSING_CHARTS |
tarot | (optional) seed | — |
Тобто report_type керує не лише render-маршрутом, а й валідаційними правилами на тіло запиту.
SDK перехід
Section titled “SDK перехід”Зворотна сумісність повна: всі 12 type-specific ендпоінтів залишаються живими. Новий /v1/reports/generate — additive surface, не replacement. Це значить існуючий код не зламається, але новий код може писатися компактніше:
// Стара модель — direct method per typeconst pdf1 = await client.reports.natal.create({ chart, whitelabel });const pdf2 = await client.reports.synastry.create({ chart1, chart2 });const pdf3 = await client.reports.tarot.create({ seed: "abc" });
// V2 — generic dispatcherconst pdf1 = await client.reports.generate({ report_type: "natal", chart, whitelabel });const pdf2 = await client.reports.generate({ report_type: "synastry", chart1, chart2 });const pdf3 = await client.reports.generate({ report_type: "tarot", seed: "abc" });Що краще — залежить від use-case. Direct-метод дає кращий type narrowing (TS-компілятор знає, що client.reports.synastry.create() вимагає chart1 + chart2). Generic-dispatcher дає менший surface area для динамічних use-case’ів — наприклад, коли користувач обирає тип звіту через UI dropdown і ви не хочете 12-разовий switch у клієнтському коді.
MCP-каталог: 12 → 1
Section titled “MCP-каталог: 12 → 1”На hosted MCP-сервері (mcp.astroway.info) було 12 окремих tools, кожен з повним описом параметрів. Після додавання generate ми не видаляємо старі (зворотна сумісність) — але новий tool astroway_reports_generate має один опис із report_type enum:
Tool: astroway_reports_generateDescription: Generates a PDF/HTML astrology report. Pass report_type to select template.Parameters: report_type (enum): "natal" | "transit-yearly" | "synastry" | "business" | ... chart (object, required for most types): birth chart data chart1, chart2 (objects, required for synastry) language (string): "uk" | "en" | ... whitelabel (boolean | object): branding overrideAI-агент при отриманні задачі “згенеруй мені натальний звіт для дати X” отримує один кандидат з очевидним descriptor, замість 12 кандидатів з overlapping descriptions. Це покращує tool selection accuracy на агентному рівні.
Pricing — без сюрпризів
Section titled “Pricing — без сюрпризів”Dispatcher не додає окремої вартості. Кожен report_type форвардиться на свого внутрішнього рендерера, який має свій pricing tier:
natal→ TIER_7transit-yearly→ TIER_8synastry,business,career,love,money,child,lal-kitab,human-design,vedic-kundli→ відповідні тіриtarot→ TIER_4
Конкретні credit-числа дивись на сторінці Pricing. Виклик POST /v1/reports/generate з report_type: "natal" коштує точно стільки ж, як прямий POST /v1/reports/natal.
Whitelabel inline працює однаково
Section titled “Whitelabel inline працює однаково”Новий whitelabel: BrandingObject inline-режим (релізований 2026-05-19) працює через generic dispatcher без змін:
curl -X POST https://api.astroway.info/v1/reports/generate \ -H "X-Api-Key: aw_live_..." \ -H "Content-Type: application/json" \ -d '{ "report_type": "synastry", "chart1": { ... }, "chart2": { ... }, "whitelabel": { "companyName": "Acme Astrology", "logoUrl": "https://cdn.example.com/logo.png", "themeColor": "#ff5500" } }'Один dispatch + один inline whitelabel = повноцінна white-label інтеграція з мінімальним SDK surface.
OpenAPI 3.1
Section titled “OpenAPI 3.1”GenerateReport — окремий компонент у /v1/openapi.json. Він використовує oneOf за report_type discriminator, що дає коректний codegen у Python (Pydantic) та PHP (typed unions через psalm/phpstan-style hints).
Наступний codegen-реліз SDK додасть метод client.reports.generate() у всіх трьох пакетах (TS / Python / PHP). До того часу можете викликати через generic HTTP-клієнт у вашому SDK — пейлоад документований у OpenAPI.
Коли використовувати який стиль
Section titled “Коли використовувати який стиль”| Сценарій | Recommended |
|---|---|
| Користувач обирає тип звіту з UI dropdown | generate (динамічно) |
| Бекенд знає точно один тип на endpoint | direct (natal, synastry, …) — кращий тайпинг |
| Інтеграція через MCP / AI-агент | generate (менше tool noise) |
| Існуючий код на v1.0 SDK | залишити direct, мігрувати поступово |
Окремої migration-урджентності немає — direct-ендпоінти не deprecated. Це чисто DX-покращення для тих, кому 12-методна поверхня заважає.
Той самий Swiss Ephemeris, що й у Solar Fire — у 4 рядках коду.
Безкоштовний ключ без картки. 5 000 викликів на місяць до першої оплати.