# FlutterFlow

FlutterFlow compila-se numa aplicação que o teu utilizador tem na mão, por isso a questão não é quais campos preencher, mas sim para onde vai a chave. O pedido abaixo foi enviado para produção exatamente como foi construído na chamada; os passos no FlutterFlow foram escritos de acordo com a documentação do FlutterFlow em 2026-09-17.

Primeiro, cria uma chave como descrito na secção [Chave para automação](/integrations/#chave-para-automação), com o âmbito `chart`.

<Aside type="caution" title="A chave numa chamada normal viaja com a aplicação">
Uma chamada não marcada como privada é executada a partir do dispositivo, e o seu cabeçalho fica dentro da compilação para iOS, Android e web, onde qualquer pessoa pode lê-lo. Faz a chamada **privada**: então o FlutterFlow executa-a através do Firebase Cloud Function, e a chave fica no servidor. A verificação própria do FlutterFlow é descarregar o código do projeto e procurar a chave nos ficheiros frontend, e isso só está disponível no plano pago.
</Aside>

## 1. Cria uma chamada

Abre **API Calls**, pressiona **+ Add**, seleciona **Create API Call** e preenche:

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

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

- Separador **Headers**, **+ Add Header**: uma linha `X-Api-Key: ` e depois a tua chave. Segunda linha `Content-Type: application/json`.
- Separador **Variables**: cinco variáveis do tipo String, `date`, `time`, `timezone`, `latitude`, `longitude`, cada uma com o valor padrão do JSON abaixo.
- Separador **Body**, no dropdown **JSON**: insere o JSON e arrasta as variáveis para ele.

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

A latitude e longitude ficam como strings intencionalmente: a API aceita `"50.45"` como número, e a string facilita o arrasto das variáveis.

Pressiona **Add Call**, abre **Response & Test**, pressiona **Test API Call** e vê a resposta em **Test Response**. `data.input.timezoneOffset` retorna como `4`: esse é o deslocamento que Kiev tinha naquela data.

## 2. Torna a chamada privada

Nas **Advanced Settings** da chamada, ativa **Make Private**, pressiona **Save**, depois **Deploy APIs**. Agora a chamada é executada no Firebase Cloud Function, por isso o projeto precisa do Firebase conectado e do plano Firebase com Cloud Functions.

<Aside type="caution" title="As chamadas privadas não herdam cabeçalhos de grupo">
Se colocares a chave no **API Group** e não na própria chamada, o FlutterFlow deixará de a enviar assim que a chamada se tornar privada: as chamadas privadas não herdam cabeçalhos de grupo. Adiciona `X-Api-Key` na própria chamada, caso contrário o primeiro lançamento privado retornará `401`.
</Aside>

Mais duas coisas que a documentação do FlutterFlow diz diretamente: a chave passada do frontend, por exemplo através de remote config, fica exposta mesmo numa chamada privada, e a forma segura é o cabeçalho escrito na própria chamada.

## 3. Lê a resposta

Em **JSON Paths**, pressiona **+ Add JSON Path** e dá a cada um um nome:

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

O sinal é a longitude dividida por 30 e arredondada para baixo, como índice na lista de doze nomes: por exemplo, o Ascendente `159.26` dá `5`, ou seja, Virgem. Basta uma função personalizada de quatro linhas ou uma lista de doze linhas com um índice.

## A compilação web não pode contactar-nos a partir do navegador

Medido em 2026-09-17 a partir de uma página num domínio externo: `POST /v1/chart` responde ao preflight sem o cabeçalho `access-control-allow-origin`, e o Chrome bloqueia o pedido. Apenas `/v1/public/*` e `/v1/embed/*` respondem a browsers em domínios externos.

O FlutterFlow executa as chamadas através do seu próprio proxy no construtor, no modo Run e no modo Test, por isso a chamada que funciona lá pode falhar após a publicação da aplicação web. Duas soluções, e a primeira recomendamos:

- **Torna a chamada privada**, como acima. Então é executada no Cloud Function, não no navegador, e isso resolve logo a questão da chave e a questão do CORS.
- **Coloca o teu próprio backend à nossa frente**, se já tens um. A configuração de proxy no FlutterFlow, com o teu próprio proxy URL, está documentada para o construtor e para os modos Run e Test; sobre a compilação web publicada, a documentação não diz nada, por isso não se deve contar com ela lá.

A chave pública `pk_` não resolve isto: ela só acede a `/v1/public/*` e `/v1/embed/*`, e as compilações para iOS e Android rejeitam-na completamente porque não enviam o web-origin.

## Erros

- **`401`** numa chamada privada: a chave está no grupo, não na chamada.
- **`400 INVALID_FIELD` com `timezone` em `details`**: o fuso está vazio, é uma abreviatura como `EST` ou não é o nome do fuso.
- **`400` com `date` ou `time` em `details`**: o formato não é `YYYY-MM-DD` / `HH:MM:SS`.
- **`403 ENDPOINT_NOT_IN_SCOPE`**: o âmbito da chave não tem `chart`.
- **`429 KEY_BUDGET_EXHAUSTED`**: a chave esgotou o seu próprio orçamento; aumenta-o no painel.

<Aside type="note">
O plano gratuito do FlutterFlow permite dois endpoints de API por projeto e não tem importação OpenAPI, por isso no dele a chamada é adicionada manualmente, e fica ainda um slot. A API não geocodifica: as coordenadas vêm dos teus próprios campos ou de um serviço de geocodificação para o qual tens a chave.
</Aside>
