# FlutterFlow

FlutterFlow компілюється в застосунок, який тримає в руках ваш користувач, тож питання не в тому, які поля заповнити, а в тому, де опиниться ключ. Запит нижче надіслано на продакшен саме в тому вигляді, в якому його складає виклик; кроки в FlutterFlow написані за документацією FlutterFlow станом на 2026-09-17.

Спершу створіть ключ, як описано в розділі [Ключ для автоматизації](/integrations/#ключ-для-автоматизації), з областю `chart`.

<Aside type="caution" title="Ключ у звичайному виклику їде разом із застосунком">
Виклик, не позначений як приватний, виконується з пристрою, а його заголовок лежить усередині скомпільованої збірки для iOS, Android і вебу, де його може прочитати будь-хто. Зробіть виклик **приватним**: тоді FlutterFlow проводить його через Firebase Cloud Function, і ключ лишається на сервері. Власна перевірка FlutterFlow це завантажити код проєкту й пошукати ключ у файлах фронтенду, а вона доступна лише на платному тарифі.
</Aside>

## 1. Створіть виклик

Відкрийте **API Calls**, натисніть **+ Add**, виберіть **Create API Call** і заповніть:

- **API Call Name**: `Natal chart`.
- **Method Type**: `POST`.
- **URL**:

  ```
  https://api.astroway.info/v1/chart
  ```

- Вкладка **Headers**, **+ Add Header**: один рядок `X-Api-Key: ` і далі ваш ключ. Другий рядок `Content-Type: application/json`.
- Вкладка **Variables**: п'ять змінних типу String, `date`, `time`, `timezone`, `latitude`, `longitude`, кожна з типовим значенням із JSON нижче.
- Вкладка **Body**, у випадному списку **JSON**: вставте JSON і перетягніть у нього змінні.

```json
{
  "date": "1990-05-15",
  "time": "14:30:00",
  "timezone": "Europe/Kyiv",
  "latitude": "50.45",
  "longitude": "30.52"
}
```

Широта й довгота лишаються рядками навмисне: API приймає `"50.45"` як число, а рядок спрощує перетягування змінних.

Натисніть **Add Call**, відкрийте **Response & Test**, натисніть **Test API Call** і подивіться відповідь у **Test Response**. `data.input.timezoneOffset` повертається як `4`: саме такий зсув Київ тримав тієї дати.

## 2. Зробіть виклик приватним

У **Advanced Settings** виклику увімкніть **Make Private**, натисніть **Save**, далі **Deploy APIs**. Тепер виклик виконується у Firebase Cloud Function, тож проєкту потрібен підключений Firebase і тариф Firebase із Cloud Functions.

<Aside type="caution" title="Приватні виклики не успадковують заголовки групи">
Якщо покласти ключ на **API Group**, а не на сам виклик, FlutterFlow перестане його надсилати тієї ж миті, коли виклик стане приватним: заголовки групи приватними викликами не успадковуються. Додайте `X-Api-Key` на сам виклик, інакше перший приватний запуск поверне `401`.
</Aside>

Ще дві речі, про які документація FlutterFlow каже прямо: ключ, переданий із фронтенду, наприклад через remote config, лишається відкритим навіть у приватному виклику, а безпечна форма це заголовок, вписаний у сам виклик.

## 3. Прочитайте відповідь

У **JSON Paths** натисніть **+ Add JSON Path** і дайте кожному ім'я:

| Ім'я | JSON Path |
|---|---|
| `ascendant` | `$.data.houses.ascendant` |
| `sunLongitude` | `$.data.planets[0].longitude` |
| `moonLongitude` | `$.data.planets[1].longitude` |
| `offsetUsed` | `$.data.input.timezoneOffset` |

Знак це довгота, поділена на 30 і округлена донизу, як індекс у списку з дванадцяти назв: для прикладу Асцендент `159.26` дає `5`, тобто Діву. Достатньо кастомної функції на чотири рядки або списку з дванадцяти рядків і індексу.

## Веб-збірка не може звертатися до нас із браузера

Виміряно 2026-09-17 зі сторінки на сторонньому домені: `POST /v1/chart` відповідає на preflight без заголовка `access-control-allow-origin`, і Chrome блокує запит. Браузеру на чужому домені відповідають лише `/v1/public/*` і `/v1/embed/*`.

FlutterFlow проводить виклики через власний проксі в конструкторі, у Run mode і Test mode, тож виклик, який там працює, може впасти після публікації веб-застосунку. Два виходи, і перший ми рекомендуємо:

- **Зробіть виклик приватним**, як вище. Тоді він виконується в Cloud Function, а не в браузері, і це одразу знімає і питання ключа, і питання CORS.
- **Поставте перед нами власний бекенд**, якщо він у вас уже є. Налаштування проксі у FlutterFlow, разом із власним proxy URL, документовані для конструктора та режимів Run і Test; про опубліковану веб-збірку документація нічого не каже, тож розраховувати на них там не варто.

Публічний ключ `pk_` цього не вирішує: він дістає лише `/v1/public/*` і `/v1/embed/*`, а зі збірок для iOS і Android відхиляється зовсім, бо вони не надсилають веб-origin.

## Помилки

- **`401`** на приватному виклику: ключ лежить на групі, а не на виклику.
- **`400 INVALID_FIELD` з `timezone` у `details`**: зона порожня, це абревіатура на кшталт `EST` або не назва зони.
- **`400` з `date` чи `time` у `details`**: формат не `YYYY-MM-DD` / `HH:MM:SS`.
- **`403 ENDPOINT_NOT_IN_SCOPE`**: в області ключа немає `chart`.
- **`429 KEY_BUDGET_EXHAUSTED`**: ключ вичерпав власний бюджет; підніміть його в дашборді.

<Aside type="note">
Безкоштовний тариф FlutterFlow дозволяє два API-ендпоінти на проєкт і не має імпорту OpenAPI, тож на ньому виклик додається руками, і лишається ще один слот. API не геокодує: координати беруться з ваших власних полів або із сервісу геокодування, до якого у вас є ключ.
</Aside>
