L'API GraphQL du modèle
Les APIs de Table et le schéma GraphQL généré à partir du modèle de données — opérations CRUD, filtres, tri, pagination, totaux et enums.
Chaque app de Keplin sert une API GraphQL sur un endpoint qui lui est propre. Le schéma de cette API ne s'écrit pas à la main : il est généré à partir de deux sources — les APIs que vous construisez dans le constructeur et le modèle de données de l'app. Les tables du modèle deviennent des types GraphQL avec leurs champs et leurs relations ; les enums du modèle deviennent des enums GraphQL ; et une API de Table transforme une table en opérations de lecture et d'écriture complètes, avec filtres, tri et pagination, sans que vous écriviez une ligne de SQL.
Cette page couvre l'endpoint, les APIs de Table et le langage de requête qu'elles offrent aux clients.
L'endpoint de l'app
Toutes les opérations d'une app sont servies sur un unique endpoint GraphQL :
POST /api/graphql/<adresse-de-l-app>
Dans l'app d'exemple, POST /api/graphql/gestao-clientes. La requête est un JSON
avec query et variables, comme sur n'importe quel service GraphQL — l'onglet
Docs de chaque API vous donne des exemples prêts à copier. Quand l'app est
publiée à une adresse propre, le même service répond aussi sur /api/graphql de
cette adresse.
Qui peut appeler l'endpoint :
| Qui appelle | Comment il s'authentifie | Ce qu'il voit |
|---|---|---|
| Les écrans de l'app | Session de l'utilisateur de l'app (automatique) | Les APIs publiées |
| Les systèmes externes | Header x-api-key — voir Clés d'API |
Les APIs publiées dans le scope de la clé |
| Celui qui construit | Session sur la plateforme | Les APIs publiées ET les brouillons (marqués comme brouillon) |
| Les anonymes | Rien | Uniquement les APIs publiques |
Nota
Les versions de l'app comptent aussi : une clé API et les requêtes anonymes parlent toujours à la version principale (ou à la version publiée de l'adresse utilisée) ; celui qui construit voit SA version de travail. Une clé n'attrape jamais, par hasard, ce qu'un développeur est en train de changer.
Créer une API de Table
- Créez une API (Nouvelle API) avec le nom qui
servira de base aux opérations — par exemple
contas. - Dans l'onglet Construire, section Pipeline, cliquez sur le bouton Table. Le bloc Table occupe tout le pipeline — il ne se combine pas avec des étapes SQL, HTTP ou Script.
- Choisissez la table dans le sélecteur Choisissez la table… — les tables apparaissent groupées par datasource, avec une recherche par nom de table ou de datasource.
- Activez les Actions exposées et ajustez les Champs inclus (voir plus bas).
- Enregistrer. Pour publier, il faut une table choisie et au moins une action active.


Nota
Le sélecteur ne montre que les tables importées dans le modèle de données. S'il est vide, importez d'abord des tables dans l'onglet Modèle d'un datasource.
Actions exposées
Chaque action activée génère une opération dans le schéma, avec le nom dérivé de
la base — pour l'API contas :
| Action | Opération générée | Ce qu'elle fait |
|---|---|---|
| Select | getContas (query) |
Liste avec filtres/tri/pagination. Elle apporte avec elle countContas, le total. |
| Insert | addContas (mutation) |
Crée une ligne. |
| Update | updateContas (mutation) |
Met à jour une ligne par sa clé primaire — partiel : ne change que ce que vous envoyez. |
| Delete | deleteContas (mutation) |
Supprime une ligne par sa clé primaire et renvoie true. |
La ligne Accès public (sans session) contrôle, action par action, ce que les écrans publics peuvent appeler — détails dans APIs publiques.
Champs inclus
L'arborescence Champs inclus définit la forme de la réponse : décochez les
champs que vous ne voulez pas exposer, et développez les champs de navigation
pour inclure les entités liées — récursivement, comme dans un éditeur GraphQL
visuel. Dans une API contas, développer le navigator contactos permet aux
clients de demander les contacts de chaque compte dans le même appel.

Atenção
Avec Insert ou Update actifs, les champs obligatoires de la table (non nuls, sans valeur automatique) sont toujours inclus — sans eux, il ne serait pas possible de créer des lignes valides. Le constructeur les montre cochés et verrouillés.
Lire des données : filtres, tri, pagination
La query de liste accepte quatre arguments : where, order, take et skip.
Un exemple complet dans l'app Gestion des Clients :
query {
getContas(
where: { cidade: { eq: "Lisboa" }, estado: { neq: "ARQUIVADA" } }
order: [{ nome: ASC }]
take: 20
skip: 0
) {
id
nome
cidade
contactos {
nome
email
}
}
}
L'argument where
Chaque champ filtrable accepte des opérateurs selon le type :
| Type du champ | Opérateurs |
|---|---|
| Texte (et enums) | eq, neq, contains, startsWith, endsWith, gt, gte, lt, lte, in, nin |
Nombres (Int, Float) |
eq, neq, gt, gte, lt, lte, in, nin |
Boolean |
eq, neq |
ID |
eq, neq, in, nin |
Et deux combinateurs pour des conditions composées : and et or, qui reçoivent
des listes de filtres.
where: {
or: [
{ cidade: { eq: "Lisboa" } }
{ cidade: { eq: "Porto" } }
]
valorAnual: { gte: 10000 }
}
Des règles utiles :
eq: nulltrouve les enregistrements dont le champ est vide ;neq: null, ceux qui sont remplis.- Intervalles de dates : les dates conservées en texte ISO (ex.
2026-08-11) se trient alphabétiquement comme elles se trient dans le temps, doncgt/lt/gte/lteen texte suffisent pour filtrer des intervalles —dataCriacao: { gte: "2026-01-01", lt: "2026-07-01" }. inreçoit une liste de valeurs ;ninl'exclut.- Les valeurs du filtre partent toujours paramétrées vers la base de données —
un
containsavec du texte malveillant n'est pas un risque.
Trier et paginer
orderest une liste de{ champ: ASC }ou{ champ: DESC }— plusieurs éléments trient par plusieurs champs, dans l'ordre donné.takelimite le nombre de lignes (plafond de 10 000 par requête) etskipsaute les N premières — ensemble, ils font la pagination classique.
Le total : count
Chaque API de Table avec Select actif gagne aussi count<Nom>, qui renvoie
le total de lignes du MÊME where. Le duo naturel d'une table paginée est de
demander la page et le total en une seule opération, avec des alias :
query {
items: getContas(take: 10, skip: 0) { id nome }
total: countContas
}
Avec un filtre, passez le même where aux deux champs — le total compte
exactement les lignes que la liste renverrait sans pagination.
Écrire des données
addContasreçoit les champs inclus comme arguments (ceux qui sont obligatoires dans la table le sont dans la mutation). Sur certaines bases de données, la réponse est la ligne créée ; sur d'autres,true— l'onglet Docs de l'API montre la forme exacte dans votre cas.updateContasreçoit la clé primaire (obligatoire) et les autres champs comme facultatifs — il ne met à jour que ce que vous envoyez — et renvoie la ligne mise à jour.deleteContasreçoit la clé primaire et renvoietrue.
mutation ($nome: String!, $cidade: String) {
addContas(nome: $nome, cidade: $cidade) {
id
nome
}
}
Nota
Les permissions de l'app s'appliquent ici, toujours : si l'utilisateur de l'app
ne peut voir que les comptes de son équipe, getContas et countContas ne
renvoient — et ne comptent — que ceux-là, quel que soit l'appelant (écran,
rapport ou workflow).
Enums
Un enum expose un ensemble fixe de valeurs dans le schéma GraphQL — l'état d'un compte, la phase d'une opportunité. Ils se gèrent sur la page APIs, onglet Enums :
- Cliquez sur Nouvel enum.
- Donnez un nom (ex.
EstadoConta) et, si cela aide, une description. - Ajoutez des valeurs avec Ajouter une valeur — chaque valeur a un identifiant (value), un libellé et une couleur facultatifs. La couleur et le libellé sont utilisés par les écrans ; le value est ce qui voyage dans l'API.
- Enregistrer.


Un enum s'utilise à deux endroits : comme type d'un champ du modèle (le champ n'accepte plus que ces valeurs, et dans les filtres il se comporte comme du texte) et comme type d'argument d'une API. Dans le schéma, les clients voient l'enum avec ses valeurs — l'autocomplétion de l'environnement de test les suggère.
Atenção
Supprimer un enum est définitif et les champs/arguments qui l'utilisaient cessent de le référencer. Préférez modifier les valeurs plutôt que supprimer l'enum.
Explorer le schéma dans GraphiQL
L'onglet Tester de n'importe quelle API inclut GraphiQL — l'environnement interactif de l'endpoint de l'app. Vous écrivez l'opération à gauche, vous exécutez, et vous voyez la réponse à droite ; l'autocomplétion connaît tout le schéma, opérations de Table incluses. Le bouton Ouvrir dans une fenêtre vous donne le même environnement en plein écran.

Comme vous êtes authentifié sur la plateforme, GraphiQL s'exécute comme un client mais voit aussi les brouillons — chaque opération en brouillon apparaît avec la description « RASCUNHO » dans la documentation du schéma. Et il répond au sujet de votre version de travail : ce que vous dessinez est ce que vous testez.
Pourquoi ne… ?
- Pourquoi je ne vois pas l'opération
getContasde l'extérieur ? Soit l'API est en brouillon (publiez-la), soit l'action Select n'est pas active, soit votre clé n'a pas cet endpoint dans son scope. - Pourquoi un champ n'apparaît-il pas dans la réponse ? Il n'est pas coché dans Champs inclus — les clients ne peuvent sélectionner que ce que l'API inclut.
- Pourquoi
addContasrenvoie-t-il untrueau lieu de la ligne ? Cela dépend de la base de données derrière la table. Quand vous avez toujours besoin de la ligne, enchaînez avec ungetContasfiltré par la clé. - Pourquoi le schéma a-t-il changé sans que je touche aux APIs ? Le schéma est généré à partir du modèle : importer de nouvelles colonnes, changer un enum ou désactiver une entité se reflète dans l'API dès l'appel suivant.