KEPLIN Docs

A API GraphQL do modelo

As APIs de Tabela e o schema GraphQL gerado do modelo de dados — operações CRUD, filtros, ordenação, paginação, totais e enums.

Cada app do Keplin serve uma API GraphQL num endpoint próprio. O schema dessa API não se escreve à mão: é gerado a partir de duas fontes — as APIs que constróis no construtor e o modelo de dados da app. As tabelas do modelo tornam-se tipos GraphQL com os seus campos e relações; os enums do modelo tornam-se enums GraphQL; e uma API de Tabela transforma uma tabela em operações de leitura e escrita completas, com filtros, ordenação e paginação, sem escreveres uma linha de SQL.

Esta página cobre o endpoint, as APIs de Tabela e a linguagem de consulta que elas oferecem aos clientes.

O endpoint da app

Todas as operações de uma app são servidas num único endpoint GraphQL:

POST /api/graphql/<endereco-da-app>

Na app de exemplo, POST /api/graphql/gestao-clientes. O pedido é um JSON com query e variables, como em qualquer serviço GraphQL — o separador Docs de cada API dá-te exemplos prontos a copiar. Quando a app está publicada num endereço próprio, o mesmo serviço responde também em /api/graphql desse endereço.

Quem pode chamar o endpoint:

Quem chama Como se autentica O que vê
Os ecrãs da app Sessão do utilizador da app (automático) APIs publicadas
Sistemas externos Header x-api-key — ver Chaves de API APIs publicadas dentro do scope da key
Quem constrói Sessão na plataforma APIs publicadas E rascunhos (marcados como rascunho)
Anónimos Nada Apenas APIs públicas

Nota

As versões da app também contam: uma API key e os pedidos anónimos falam sempre com a versão principal (ou com a versão publicada do endereço usado); quem constrói vê a SUA versão de trabalho. Uma key nunca apanha, por acaso, aquilo que um developer está a meio de mudar.

Criar uma API de Tabela

  1. Cria uma API (Nova API) com o nome que vai servir de base às operações — por exemplo contas.
  2. No separador Construir, secção Pipeline, carrega no botão Tabela. O bloco Tabela ocupa o pipeline inteiro — não se combina com passos SQL, HTTP ou Script.
  3. Escolhe a tabela no selector Escolhe a tabela… — as tabelas aparecem agrupadas por datasource, com pesquisa por nome de tabela ou de datasource.
  4. Activa as Acções expostas e ajusta os Campos incluídos (ver abaixo).
  5. Gravar. Para publicar, precisa de tabela escolhida e pelo menos uma acção activa.

O bloco Tabela no construtor, com a tabela escolhida e as acções expostas.
O bloco Tabela no construtor, com a tabela escolhida e as acções expostas.

O selector de tabela: datasource → tabela, com pesquisa.
O selector de tabela: datasource → tabela, com pesquisa.

Nota

O selector só mostra tabelas importadas para o modelo de dados. Se estiver vazio, importa tabelas no separador Modelo de um datasource primeiro.

Acções expostas

Cada acção activa gera uma operação no schema, com o nome derivado da base — para a API contas:

Acção Operação gerada O que faz
Select getContas (query) Lista com filtros/ordenação/paginação. Traz consigo countContas, o total.
Insert addContas (mutation) Cria uma linha.
Update updateContas (mutation) Actualiza uma linha pela chave primária — parcial: só muda o que enviares.
Delete deleteContas (mutation) Apaga uma linha pela chave primária e devolve true.

A linha Acesso público (sem sessão) controla, acção a acção, o que os ecrãs públicos podem chamar — detalhes em APIs públicas.

Campos incluídos

A árvore Campos incluídos define a forma da resposta: desmarca os campos que não queres expor, e expande os campos de navegação para incluir entidades relacionadas — recursivamente, como num editor GraphQL visual. Numa API contas, expandir o navegador contactos faz com que os clientes possam pedir os contactos de cada conta na mesma chamada.

A árvore de campos de uma API de Tabela, com um campo de navegação expandido.
A árvore de campos de uma API de Tabela, com um campo de navegação expandido.

Atenção

Com Insert ou Update activos, os campos obrigatórios da tabela (não-nulos, sem valor automático) ficam sempre incluídos — sem eles não era possível criar linhas válidas. O construtor mostra-os marcados e bloqueados.

Ler dados: filtros, ordenação, paginação

A query de lista aceita quatro argumentos: where, order, take e skip. Um exemplo completo na app Gestão de Clientes:

query {
  getContas(
    where: { cidade: { eq: "Lisboa" }, estado: { neq: "ARQUIVADA" } }
    order: [{ nome: ASC }]
    take: 20
    skip: 0
  ) {
    id
    nome
    cidade
    contactos {
      nome
      email
    }
  }
}

O argumento where

Cada campo filtrável aceita operadores conforme o tipo:

Tipo do campo Operadores
Texto (e enums) eq, neq, contains, startsWith, endsWith, gt, gte, lt, lte, in, nin
Números (Int, Float) eq, neq, gt, gte, lt, lte, in, nin
Boolean eq, neq
ID eq, neq, in, nin

E dois combinadores para condições compostas: and e or, que recebem listas de filtros.

where: {
  or: [
    { cidade: { eq: "Lisboa" } }
    { cidade: { eq: "Porto" } }
  ]
  valorAnual: { gte: 10000 }
}

Regras úteis:

  • eq: null encontra os registos com o campo vazio; neq: null, os preenchidos.
  • Intervalos de datas: datas guardadas como texto ISO (ex. 2026-08-11) ordenam alfabeticamente como ordenam no tempo, por isso gt/lt/gte/lte em texto chegam para filtrar intervalos — dataCriacao: { gte: "2026-01-01", lt: "2026-07-01" }.
  • in recebe uma lista de valores; nin exclui-a.
  • Os valores do filtro vão sempre parametrizados para a base de dados — um contains com texto malicioso não é um risco.

Ordenar e paginar

  • order é uma lista de { campo: ASC } ou { campo: DESC } — vários itens ordenam por vários campos, pela ordem dada.
  • take limita o número de linhas (tecto de 10 000 por pedido) e skip salta as primeiras N — juntos fazem a paginação clássica.

O total: count

Cada API de Tabela com Select activo ganha também count<Nome>, que devolve o total de linhas do MESMO where. O par natural de uma tabela paginada é pedir a página e o total numa só operação, com aliases:

query {
  items: getContas(take: 10, skip: 0) { id nome }
  total: countContas
}

Com filtro, passa o mesmo where aos dois campos — o total conta exactamente as linhas que a lista devolveria sem paginação.

Escrever dados

  • addContas recebe os campos incluídos como argumentos (os obrigatórios da tabela são obrigatórios na mutation). Em algumas bases de dados a resposta é a linha criada; noutras, true — o separador Docs da API mostra a forma exacta no teu caso.
  • updateContas recebe a chave primária (obrigatória) e os restantes campos como opcionais — só actualiza o que enviares — e devolve a linha actualizada.
  • deleteContas recebe a chave primária e devolve true.
mutation ($nome: String!, $cidade: String) {
  addContas(nome: $nome, cidade: $cidade) {
    id
    nome
  }
}

Nota

As permissões da app aplicam-se aqui, sempre: se o utilizador da app só pode ver as contas da sua equipa, getContas e countContas devolvem — e contam — apenas essas, chame quem chamar (ecrã, relatório ou workflow).

Enums

Um enum expõe um conjunto fixo de valores no schema GraphQL — o estado de uma conta, a fase de uma oportunidade. Gerem-se na página APIs, separador Enums:

  1. Carrega em Novo enum.
  2. Dá um nome (ex. EstadoConta) e, se ajudar, uma descrição.
  3. Acrescenta valores com Adicionar valor — cada valor tem um identificador (value), um label e uma cor opcionais. A cor e o label são usados pelos ecrãs; o value é o que viaja na API.
  4. Gravar.

A página APIs, separador Enums — a app Gestão de Clientes ainda não tem enums criados.
A página APIs, separador Enums — a app Gestão de Clientes ainda não tem enums criados.

Criar um enum: valores com identificador, label e cor.
Criar um enum: valores com identificador, label e cor.

Um enum usa-se em dois sítios: como tipo de um campo do modelo (o campo passa a aceitar apenas aqueles valores, e nos filtros comporta-se como texto) e como tipo de argumento de uma API. No schema, os clientes vêem o enum com os seus valores — o autocompletar do ambiente de teste sugere-os.

Atenção

Eliminar um enum é permanente e os campos/argumentos que o usavam deixam de o referenciar. Prefere editar os valores a eliminar o enum.

Explorar o schema no GraphiQL

O separador Testar de qualquer API inclui o GraphiQL — o ambiente interactivo do endpoint da app. Escreves a operação à esquerda, executas, e vês a resposta à direita; o autocompletar conhece o schema inteiro, operações de Tabela incluídas. O botão Abrir em janela dá-te o mesmo ambiente a ecrã inteiro.

O GraphiQL no separador Testar, com a query de lista pronta a executar.
O GraphiQL no separador Testar, com a query de lista pronta a executar.

Como estás autenticado na plataforma, o GraphiQL executa como um cliente mas vê também os rascunhos — cada operação em rascunho aparece com a descrição "RASCUNHO" na documentação do schema. E responde sobre a tua versão de trabalho: o que estás a desenhar é o que estás a testar.

Porque não…?

  • Porque não vejo a operação getContas de fora? Ou a API está em rascunho (publica-a), ou a acção Select não está activa, ou a tua key não tem esse endpoint no scope.
  • Porque não aparece um campo na resposta? Não está marcado em Campos incluídos — os clientes só podem seleccionar o que a API incluir.
  • Porque devolve addContas um true em vez da linha? Depende da base de dados por trás da tabela. Quando precisares sempre da linha, segue com um getContas filtrado pela chave.
  • Porque mudou o schema sem eu tocar nas APIs? O schema é gerado do modelo: importar colunas novas, mudar um enum ou desactivar uma entidade reflecte-se na API na chamada seguinte.