Convenções de URL e endpoints gratuitos
Se vês um 404 num pedido típico, o mais provável é o prefixo estar errado ou estares a procurar o Swagger UI num caminho fora do padrão. Esta página fixa todos os URL canónicos e aliases.
Prefixo do caminho
Seção intitulada “Prefixo do caminho”Todos os endpoints vivem sob /v1/. Não há outros prefixos.
✅ https://api.astroway.info/v1/chart✅ https://api.astroway.info/v1/health❌ https://api.astroway.info/api/chart - 404 (missing /v1/ prefix)❌ https://api.astroway.info/api/v1/chart - 404 (our internal path, not exposed)❌ https://api.astroway.info/v1/v1/chart - 308 redirect to /v1/chart (typical SDK base-URL bug fix)Se usaste por engano /api/<endpoint>, devolvemos 404 com o campo error.code = "WRONG_PREFIX" e uma dica - o teu SDK pode tratar isto e sugerir o caminho correto.
Isto não é um proxy de LLM
Seção intitulada “Isto não é um proxy de LLM”AstroWay é uma API de cálculos astrológicos, não um proxy para LLM. Se vens com a memória muscular do OpenAI SDK e tentas simplesmente mudar o base_url para o nosso, não vai funcionar:
❌ POST /v1/chat/completions - doesn't exist❌ POST /v1/completions - doesn't exist❌ GET /v1/models - doesn't exist (deliberately)❌ POST /v1/embeddings - doesn't existNão publicamos a lista de fornecedores de IA por duas razões:
- Não é acionável para o integrador. Chamas
/v1/interpret/natalou/v1/horoscope/daily, e o nosso servidor escolhe sozinho o LLM entre vários fornecedores com fallback automático. Mudar de fornecedor não altera a forma da resposta, apenas a latência e, ocasionalmente, a redação. - Liberdade operacional. A cadeia muda sem aviso (exclusão do HuggingFace em 2026-05-18, adição de NIM/ZAI). Se anunciássemos um
models[]concreto, isso tornar-se-ia de facto um contrato.
A IA está presente apenas como detalhe de implementação em /v1/interpret/* (natal, sinastria, trânsitos), /v1/horoscope/* (horóscopo diário/semanal), /v1/dev-assistant (assistente da documentação) e /v1/reports/* (narrativas em PDF). Os restantes 750+ endpoints são Swiss Ephemeris determinístico, sem IA.
Especificação OpenAPI 3.1
Seção intitulada “Especificação OpenAPI 3.1”O endereço canónico é /v1/openapi.json. Para facilitar integrações, foram acrescentados aliases:
| Alias | Para onde | Porque existe |
|---|---|---|
/v1/swagger.json | 301 → /v1/openapi.json | Convenção Swagger 2.0 / openapi-generator |
/v1/api-docs/swagger.json | 301 → /v1/openapi.json | Predefinição do springdoc |
/v1/v3/api-docs | 301 → /v1/openapi.json | Spring Boot 3 |
/v1/v2/api-docs | 301 → /v1/openapi.json | Spring Boot 2 |
/v1/swagger/v1/swagger.json | 301 → /v1/openapi.json | ASP.NET Core |
/v1/swagger, /v1/swagger-ui, /v1/swagger-ui.html | 302 → /v1/docs | Host do Swagger UI |
O Swagger UI interativo está disponível em /v1/docs (também espelhado na documentação do navegador em /docs/api/).
Endpoints de sistema gratuitos
Seção intitulada “Endpoints de sistema gratuitos”Estes caminhos não precisam de chave de API nem gastam créditos - podem ser chamados a partir de qualquer frontend, monitorização ou health-check.
| Caminho | O que devolve |
|---|---|
GET /v1/health | {status, version, uptime_seconds, timestamp} - liveness probe rápido |
GET /v1/health/deep | Verificação de acessibilidade por base de dados (para UptimeRobot / Pingdom), 503 se pelo menos uma BD estiver indisponível |
GET /v1/version | {version, build_commit, started_at, uptime_seconds, docs_url} - self-check detalhado para SDK |
GET /v1/openapi.json | Especificação OpenAPI 3.1 completa com exemplos + x-codeSamples |
GET /v1/docs | Swagger UI interativo |
GET /v1/reference/* | Referências canónicas (signos, planetas, casas, aspetos) - rate limit por IP, sem chave |
GET /v1/i18n/langs, GET /v1/i18n/dict/:lang | Lista de idiomas e dicionários de UI - para widgets |
Endpoints gratuitos que exigem registo
Seção intitulada “Endpoints gratuitos que exigem registo”Os endpoints de conta estão disponíveis apenas com token JWT (emitido no login), mas não gastam créditos do saldo do plano.
| Prefixo | O que é |
|---|---|
/v1/auth/* | Registo, login, refresh, reposição de palavra-passe |
/v1/me, /v1/me/* | Perfil, estatísticas, chamadas recentes |
/v1/keys, /v1/keys/* | Gestão de chaves de API |
/v1/admin/* | Painel de administração (requer api_role = admin) |
/v1/messages | Feedback a partir do widget (anónimo, rate limit) |
/v1/dev-assistant, /v1/dev-assistant/stream | Assistente de IA para a documentação (anónimo, limite próprio) |
/v1/widget-config | Feature flags de runtime para o widget |
/v1/embed/* | Widgets iframe incorporáveis (rate limit por IP) |
/v1/oauth/* | Login com Google / GitHub |
/v1/books/* | Birth Book - JWT de scope próprio (emitido pelo mu-plugin do WordPress) |
Endpoints de cálculo pagos
Seção intitulada “Endpoints de cálculo pagos”Todos os cálculos astrológicos gastam créditos do teu plano. O custo exato de cada um está na página Custo de cada endpoint. Em resumo:
| Tier | Créditos | Exemplos |
|---|---|---|
| 0 | 0 | /v1/reference/* - referências públicas, sem chave |
| ½ | 5 | /v1/kabbalah/sephiroth, /v1/fixed-stars/catalog - tabelas estáticas |
| 1 | 10 | /v1/planets, /v1/sun-times, /v1/moon-phase |
| 2 | 20 | /v1/chart, /v1/harmonics, /v1/horary |
| 3 | 50 | /v1/synastry, /v1/progressions, /v1/acg |
| 4 | 100 | /v1/transit-calendar, /v1/group-synastry |
| 5 | 250 | /v1/rectification/trutine, narrativas de IA /v1/reports/ai/* |
| 6 | 500 | /v1/rectification |
| 7 | 5000 | Relatórios PDF: /v1/reports/natal, /v1/reports/synastry |
Descontos de cache: X-Cache: HIT (cache de idempotência de 5 min) - 0 créditos. Endpoints de IA (/interpret/*) - 50% de desconto em cache hit.
Os cabeçalhos da resposta contêm X-Credits-Used, X-Credits-Remaining, X-Credits-Limit - os SDK podem acompanhar o saldo automaticamente.
Idioma das respostas
Seção intitulada “Idioma das respostas”O idioma define-se com ?lang= ou com o cabeçalho Accept-Language. São suportados 21 idiomas.
Os campos de conjuntos fechados (signos, planetas, dias da semana, fases da Lua, vocabulário de Human Design, nomes dos Arcanos Maiores do Tarot) são devolvidos duas vezes: o identificador inglês fica no seu lugar como contrato estável, e ao lado chega um objeto localized com a tradução:
{ "phaseName": "Waxing Gibbous", "moonSign": "Capricorn", "localized": { "phaseName": "Zunehmender Mond", "moonSign": "Steinbock", "sunSign": "Löwe" }}Compara os valores em inglês, mostra localized. Estes nomes vêm de uma tabela explícita de termos no código, e não de tradução automática: a terminologia não pode ser traduzida palavra a palavra, senão uma fase da Lua transforma-se num termo financeiro.
Em Human Design, os centros em localized.centers têm como chaves os mesmos identificadores que centers[].name, por isso a correspondência faz-se pela chave e não pela string traduzida. No Tarot, o mesmo faz localized.cards, com o slug da carta como chave.
Os campos de conjuntos abertos continuam, por agora, em inglês e estão documentados como tal: themes[] no planeta do dia, palavras-chave e significados das cartas de Tarot, nomes dos canais e portas de Human Design. Os nomes dos Arcanos Menores são montados a partir de formas fixas de posto e naipe, por isso todo o baralho de 78 cartas está localizado e nameLocalized é true para ele; o campo só fica false onde a tabela não consegue dar o nome. Traduz os conjuntos abertos do teu lado ou espera por dicionários próprios.
Resposta compacta: fields e precision
Seção intitulada “Resposta compacta: fields e precision”Um agente paga por cada token que lê. POST /v1/chart devolve cerca de 32 KB, e o modelo normalmente precisa de duas colunas disso, e cada longitude chega com catorze casas decimais onde ninguém trabalha com mais precisão do que um minuto de arco.
Dois parâmetros de query resolvem isto no último passo, por isso funcionam em todos os endpoints:
fields- lista de caminhos separados por vírgulas, relativos adata. O caminho aplica-se a cada elemento de um array, por issoplanets.namesignifica o nome de cada planeta, e não uma chave do array.precision- inteiro de 0 a 15, arredonda todos os números não inteiros da resposta. Os inteiros não são tocados: um identificador não é uma medição.
curl -X POST "https://api.astroway.info/v1/chart?fields=planets.name,planets.longitude&precision=2" \ -H "X-Api-Key: aw_live_..." -H "Content-Type: application/json" \ -d '{"date":"1990-05-15","time":"14:30:00","timezone":"Europe/Kyiv","latitude":50.45,"longitude":30.52}'Este par de parâmetros num mapa natal dá 511 bytes em vez de 32 410, ou seja, uma resposta sessenta vezes menor.
Um caminho que nada encontrou não desaparece em silêncio. Chega no campo _fields_unmatched ao lado da resposta: parte dos campos é mesmo opcional e está ausente numa resposta concreta, por isso isto não é um erro. Já uma lista em que nenhum caminho corresponde é uma gralha, e devolve 400 FIELDS_UNKNOWN com a enumeração. Um objeto vazio em vez do mapa seria uma resposta errada dada com confiança.
Ambos os parâmetros vão na query e não num cabeçalho, e isso é intencional: a cache de respostas usa como chave o método, o caminho, o corpo, a query ordenada e o plano. Um modo num cabeçalho repetiria o incidente de 2026-08-22, quando Accept-Language não entrava na chave e uma resposta em alemão foi entregue ao pedido seguinte como se fosse em ucraniano.
A modelação da resposta aplica-se apenas a data. O envelope, _footer e _warning ficam intactos.
O mesmo funciona via MCP. Cada ferramenta em mcp.astroway.info aceita fields e precision ao lado dos seus parâmetros e passa-os à API pela mesma query. Um mapa natal via MCP pesava 91 737 bytes, porque os dados chegavam duas vezes: como bloco de texto indentado e como campo estruturado. Com os mesmos três caminhos e precision: 2 são 1 182 bytes.
| Chamada de mapa natal | Bytes |
|---|---|
| MCP, como era até 21.09.2026 | 91 737 |
| MCP, sem indentação no bloco de texto | 72 484 |
MCP, precision: 2 | 61 356 |
MCP, três caminhos em fields mais precision: 2 | 1 182 |
REST, três caminhos em fields mais precision=2 | 559 |
Hora de nascimento desconhecida
Seção intitulada “Hora de nascimento desconhecida”Uma parte significativa dos utilizadores finais não sabe a hora exata de nascimento. Se se usar um meio-dia convencional e calcular o mapa como de costume, a resposta vai trazer um ascendente e cúspides das casas que parecem fiáveis, mas erram cerca de um signo por cada duas horas de erro.
Por isso, em vez de time podes passar timeUnknown: true:
curl -X POST https://api.astroway.info/v1/chart \ -H "X-Api-Key: aw_live_..." \ -H "Content-Type: application/json" \ -d '{"date":"1990-03-15","timeUnknown":true,"timezoneOffset":2,"latitude":50.45,"longitude":30.52}'O que a API devolve neste modo:
| Campo | Valor |
|---|---|
planets | calculados para o meio-dia local |
aspects | calculados, mas os aspetos com a Lua não são fiáveis (ver abaixo) |
houses | null |
houseAspects | null |
chartSect | null |
siderealTime | null |
timeUnknown | bloco com a explicação: o que exatamente foi omitido e onde a Lua pode estar |
O bloco timeUnknown.moon contém a longitude da Lua no início e no fim do dia, o arco percorrido durante o dia (11.8-15.4°), a lista de signos em que esteve e a flag changesSign. A Lua pode mudar de signo durante o dia, por isso vale a pena mostrar este intervalo ao utilizador em vez de o esconder atrás de um único número.
A flag é aceite por /v1/chart e /v1/synastry (na sinastria pode ser definida para cada um dos parceiros separadamente). Os restantes endpoints dependem das casas ou dos ângulos e respondem 400 TIME_UNKNOWN_UNSUPPORTED: é melhor um erro explícito do que uma flag ignorada em silêncio e um ascendente inventado na resposta.
Versionamento da API
Seção intitulada “Versionamento da API”Versão major no URL (/v1/). As breaking changes chegam apenas com /v2/, nunca in-place. Detalhes em Versionamento.
GET /v1/version devolve o deploy atual:
curl https://api.astroway.info/v1/version# {# "version": "2.71.0",# "build_commit": "abc1234",# "started_at": "2026-05-27T10:42:00Z",# "uptime_seconds": 12345,# "docs_url": "https://api.astroway.info/docs/api/"# }Os SDK podem chamar isto no arranque para depurar “porque é que de repente o comportamento é outro” - o campo build_commit identifica o deploy com exatidão.
As chamadas erradas que vemos com mais frequência
Seção intitulada “As chamadas erradas que vemos com mais frequência”Da análise dos logs de produção de 90 dias, 5 erros típicos de integradores:
/api/<endpoint>em vez de/v1/<endpoint>: hábito do wp-json do WordPress. Agora devolvemos um 404 em JSON com uma dica./v1/v1/<endpoint>: o SDK está configurado combaseUrl = .../v1e acrescenta/v1/Xpor cima. Agora é um redirect 308./swagger.jsonem vez de/v1/openapi.json: auto-probe do Postman/Insomnia. Agora é um redirect 301./v1/me,/v1/auth/keys/mesemAuthorization: Bearer <jwt>→ 401. Verifica se o token é enviado no cabeçalho./v1/embed/natalcom chave de API em vez de token de embed → 401. Os endpoints de embed aceitam um token de embed público do dashboard, não uma chave de API.
Relacionado
Seção intitulada “Relacionado”- Início rápido: o primeiro pedido em 5 minutos
- Autenticação: JWT, chaves de API, tokens de embed
- Custo de cada endpoint: tabela exata de créditos
- Erros: lista de códigos de erro
- OpenAPI 3.1: especificação completa