# FarMapp API — documentação API pública do FarMapp para consulta de farmácias e reserva de medicamentos. - Base URL: https://farmaperto.onrender.com - Auth: JWT Bearer (`Authorization: Bearer `) - Consulta pública: farmácias e avaliações sem conta. - Reservas, perfil e denúncias exigem sessão. - IDs de acesso de farmácia: 10 dígitos. ## Especificações - [OpenAPI 3.0](https://farmapp-2pf.pages.dev/openapi.json) (30 operações) - [Portal de developers](https://farmapp-2pf.pages.dev/developers) - [Autenticação da API](https://farmapp-2pf.pages.dev/developers/auth) - [Funções para agents (function-calling)](https://farmapp-2pf.pages.dev/api/functions.json) (30 funções, schemas autónomos sem `$ref`) - [Catálogo de API (RFC 9727)](https://farmapp-2pf.pages.dev/.well-known/api-catalog) - [Diretório de assinaturas HTTP (RFC 9421)](https://farmapp-2pf.pages.dev/.well-known/http-message-signatures-directory) ## Quando usar a API Este é o endpoint certo para tarefas concretas de agentes: - Localizar farmácias em Angola (Luanda) → `GET /api/farmacias?search=&search_type=farmacia` - Saber se um medicamento tem stock → `GET /api/farmacias?search=&search_type=medicamento - Factos de uma farmácia (horários, telefone, morada, serviços, avaliações) → `GET /api/farmacias/{id}` - Reservar um medicamento por 3 horas → login (`POST /api/auth/login`) + `POST /api/reservas` com `farmaciaId` e `itemStockId` lidos da API (nunca inventar IDs) - Consultar serviços e stock de uma farmácia autenticada → `GET /api/perfil/me` e `GET /api/perfil/stock` Fora de âmbito: aconselhamento médico, urgências e farmácias fora de Angola. Erros são sempre `{"erro": true, "mensagem": "", ...}` (4xx/5xx). ## Rate limiting (RFC 9652) Todas as respostas de `/api/*` (exceto `/api/health`) incluem headers de rate-limit no formato draft-7: - `RateLimit-Policy: 120;w=300` — limite e janela em segundos (`w=300` = 5 min). - `RateLimit: limit=120, remaining=119, reset=300` — restantes e tempo até reiniciar, em segundos. Limites por IP (janela de 5 minutos): - Pedidos sem autenticação: **120**/5 min. - Pedidos autenticados (header `Authorization`): **300**/5 min. - Endpoints de auth (`/api/auth/login`, `/register`, `/farmacia`, `/google`) e trajectória têm limites próprios mais restritos (sobrescrevem os globais): login/google 10/15 min, registo 10/hora, login farmácia 5/15 min, trajectória 2/5 min. **Self-throttling para agents**: lê `RateLimit`/`RateLimit-Policy` de cada resposta e, se `remaining` for baixo, pausa até `reset`. No limite, a API devolve **429** com `Retry-After` (segundos) e corpo `{"erro": true, "mensagem": "Tentaste demasiados pedidos. ..."}` — espera `Retry-After` segundos antes de repetir. ## Erros (schema tipado) Todas as respostas **4xx/5xx** devolvem o mesmo schema `Erro` — legível por máquinas, sem ambiguidades: ```json { "erro": true, "code": "NAO_ENCONTRADO", "mensagem": "Item não encontrado.", "detalhes": {} } ``` - `code` — identificador **estável** (reagir por ele, nunca pela `mensagem`): `NAO_AUTENTICADO`, `TOKEN_EM_FALTA`, `TOKEN_INVALIDO_OU_EXPIRADO`, `SEM_PERMISSAO`, `PEDIDO_INVALIDO`, `VALIDACAO`, `NAO_ENCONTRADO`, `CONFLITO`, `DEMASIADO_GRANDE` (413), `LIMITE_DE_PEDIDOS` (429), `ERRO_INTERNO`, `INDISPONIVEL`, `GATEWAY_INVALIDO`, `TIMEOUT`, `TIPO_NAO_SUPORTADO`. - `mensagem` — português, pronta a mostrar ao utilizador. - `detalhes` — opcional (ex. campos com erro na validação). - **Agentes**: decide a reação pelo `code` — ex. `NAO_AUTENTICADO`/`TOKEN_EM_FALTA` → novo login; `LIMITE_DE_PEDIDOS` → espera `Retry-After`; `NAO_ENCONTRADO`/`CONFLITO` → fluxo alternativo; `ERRO_INTERNO`/`INDISPONIVEL` → tentar mais tarde com backoff. - Contracto idêntico documentado na spec OpenAPI (`/openapi.json`, schema `Erro`). ## Versionamento e depreciação - **Versão atual: `1`** — o path `/api` é a v1 (sem prefixo). Todas as respostas de `/api/*` incluem `X-FarMapp-API-Version: 1`. - **Mudanças incompatíveis** nunca alteram a v1 silenciosamente: evoluem num path novo, `/api/v2` (e seguintes), mantendo a versão antiga a funcionar. - **Depreciação**: quando uma rota deixa de ser aconselhada, a API passa a responder com `Deprecation: true` e `Sunset: ` (ver RFC 8594). Agents devem migrar antes da data de `Sunset` — até lá a rota continua funcional e estável. - **Calendarização**: o período típico de depreciação é de **6 meses** entre o aviso (`Deprecation`) e a remoção (`Sunset`). Remoções só acontecem na data publicada em `Sunset`. - **Especificações**: `info.version` no OpenAPI (`/openapi.json`) é a versão do documento (ex. `2.8.0`); a **versão da API** é sempre a do header `X-FarMapp-API-Version`. Não usar a versão da spec como versão da API. ## Endpoints principais - `GET /api/health` — estado do serviço - `GET /api/farmacias` — listar farmácias (filtros q, municipio, bairro, medicamento, lat, lon) - `GET /api/farmacias/{id}` — detalhe (morada, telefones, horário, serviços, stock, avaliações) - `POST /api/auth/register` — criar conta - `POST /api/auth/login` — iniciar sessão - `POST /api/auth/farmacia` — login de farmácia (código de 10 dígitos) - `POST /api/auth/google` — login com Google - `POST /api/farmacias/{id}/avaliacoes` — avaliar farmácia - `POST /api/reservas` — reservar medicamento (válida 3 horas) - `PATCH /api/reservas/{id}/cancelar` — cancelar reserva (stock reposto) ## Function calling (LLMs) Em `/api/functions.json` está o manifesto compatível com function-calling: 30 funções com `name` = operationId da spec OpenAPI (único, `^[a-zA-Z0-9_-]+$`), `description` (inclui método HTTP + path e nota de autenticação) e `parameters` como JSON Schema autónomo — todos os `$ref` resolvidos, `nullable` convertido para `type: ["T","null"]`. Erros: ler `mensagem` do corpo `{"erro":true,"mensagem":...}`. - `GET /api/perfil/me` — perfil da farmácia - `GET /api/perfil/stock` — stock da farmácia Para a lista completa com schemas, ver o ficheiro openapi.json.