# FlutterFlow

Το FlutterFlow μεταγλωττίζεται σε μια εφαρμογή που κρατάει ο χρήστης σου, οπότε το ζήτημα δεν είναι ποια πεδία να συμπληρώσεις, αλλά πού θα καταλήξει το κλειδί. Το παρακάτω αίτημα στάλθηκε στην παραγωγή ακριβώς όπως το συνθέτει η κλήση· τα βήματα στο FlutterFlow γράφτηκαν σύμφωνα με την τεκμηρίωση του FlutterFlow από 2026-09-17.

Αρχικά, δημιούργησε ένα κλειδί, όπως περιγράφεται στην ενότητα [Κλειδί για αυτοματοποίηση](/integrations/#κλειδί-για-αυτοματοποίηση), με πεδίο `chart`.

<Aside type="caution" title="Το κλειδί σε μια κανονική κλήση ταξιδεύει μαζί με την εφαρμογή">
Μια κλήση που δεν έχει επισημανθεί ως ιδιωτική εκτελείται από τη συσκευή, και η κεφαλίδα της βρίσκεται μέσα στην μεταγλωττισμένη έκδοση για iOS, Android και web, όπου μπορεί να διαβαστεί από οποιονδήποτε. Κάνε την κλήση **ιδιωτική**: τότε το FlutterFlow τη δρομολογεί μέσω μιας Firebase Cloud Function, και το κλειδί παραμένει στον διακομιστή. Ο έλεγχος του FlutterFlow είναι να κατεβάσει τον κώδικα του έργου και να αναζητήσει το κλειδί στα αρχεία του frontend, και αυτός είναι διαθέσιμος μόνο σε επί πληρωμή πακέτο.
</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 αναφέρει ρητά: ένα κλειδί που μεταδίδεται από το frontend, για παράδειγμα μέσω 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`, δηλαδή την Παρθένο. Αρκεί μια προσαρμοσμένη συνάρτηση τεσσάρων γραμμών ή μια λίστα με δώδεκα συμβολοσειρές και έναν δείκτη.

## Η web-έκδοση δεν μπορεί να μας καλέσει από το πρόγραμμα περιήγησης

Μετρήθηκε 2026-09-17 από μια σελίδα σε τρίτο τομέα: το `POST /v1/chart` απαντά στο preflight χωρίς την κεφαλίδα `access-control-allow-origin`, και ο Chrome μπλοκάρει το αίτημα. Στο πρόγραμμα περιήγησης σε ξένο τομέα απαντούν μόνο τα `/v1/public/*` και `/v1/embed/*`.

Το FlutterFlow δρομολογεί κλήσεις μέσω του δικού του proxy στον builder, στο Run mode και στο Test mode, οπότε μια κλήση που λειτουργεί εκεί μπορεί να αποτύχει μετά τη δημοσίευση της web-εφαρμογής. Δύο λύσεις, και την πρώτη συνιστούμε:

- **Κάνε την κλήση ιδιωτική**, όπως παραπάνω. Τότε εκτελείται σε μια Cloud Function, όχι στο πρόγραμμα περιήγησης, και αυτό λύνει αμέσως τόσο το ζήτημα του κλειδιού όσο και το ζήτημα του CORS.
- **Βάλε το δικό σου backend μπροστά μας**, αν το έχεις ήδη. Οι ρυθμίσεις proxy στο FlutterFlow, μαζί με το δικό σου proxy URL, τεκμηριώνονται για τον builder και τις λειτουργίες Run και Test· η τεκμηρίωση δεν αναφέρει τίποτα για τη δημοσιευμένη web-έκδοση, οπότε δεν πρέπει να βασίζεσαι σε αυτές εκεί.

Το δημόσιο κλειδί `pk_` δεν το λύνει αυτό: ανακτά μόνο τα `/v1/public/*` και `/v1/embed/*`, και απορρίπτεται εντελώς από τις εκδόσεις για iOS και Android, επειδή δεν στέλνουν web-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-endpoints ανά έργο και δεν έχει εισαγωγή OpenAPI, οπότε σε αυτό η κλήση προστίθεται χειροκίνητα, και απομένει ακόμη μία θέση. Το API δεν γεωκωδικοποιεί: οι συντεταγμένες λαμβάνονται από τα δικά σου πεδία ή από μια υπηρεσία γεωκωδικοποίησης για την οποία έχεις κλειδί.
</Aside>
