L'API REST
Lire et écrire dans OIO depuis vos propres outils.
L'API REST expose les pages, les blocs, les bases de données et les commentaires en JSON. Elle s'authentifie avec une clé d'API.
- S'authentifier
- Principaux points d'entrée
- Exemple
- Lire les lignes d'une grande base par pages
- Synchroniser un tableau depuis un autre outil
- Ce qui est refusé, et pourquoi
S'authentifier
Deux en-têtes sont acceptés, au choix :
Authorization: Bearer oio_votre_cle
X-API-Key: oio_votre_cle
Une requête sans clé valide reçoit un code 401. Une requête portant sur une ressource
hors du périmètre de la clé reçoit un 403 — et jamais le contenu.
Principaux points d'entrée
| Méthode et chemin | Effet |
|---|---|
GET /api/search?q=… |
Rechercher dans les titres et les contenus |
GET /api/pages/{id}/blocks |
Lire les blocs d'une page |
POST /api/pages/{id}/blocks |
Ajouter un bloc |
PATCH /api/blocks/{id} |
Modifier un bloc |
DELETE /api/blocks/{id} |
Supprimer un bloc |
POST /api/pages/{id}/blocks/reorder |
Réordonner les blocs |
GET /api/databases |
Lister les bases de données |
GET /api/databases/{id}/rows |
Lire les lignes d'une base |
GET /api/databases/{id}/rows/count |
Compter les lignes d'une base |
POST /api/databases/{id}/rows |
Ajouter une ligne |
POST /api/databases/{id}/rows/upsert |
Ajouter ou mettre à jour une ligne |
DELETE /api/databases/{id}/rows/{pageId} |
Mettre une ligne à la corbeille |
GET /api/notifications |
Lire vos notifications |
POST /api/pages/{id}/comments |
Déposer un commentaire |
Exemple
curl -H "Authorization: Bearer oio_votre_cle" \
https://votre-instance/api/pages/42/blocks
Lire les lignes d'une grande base par pages
GET /api/databases/{id}/rows renvoie, par défaut, toutes les lignes de la base dans un
tableau JSON — le format d'origine, inchangé pour ne casser aucun script existant. Pour lire
une grande base par pages, ajoutez page (à partir de 1) et, si besoin, pageSize (50
par défaut, 200 au maximum) :
GET /api/databases/12/rows?page=1&pageSize=50
Dès que page est présent, la réponse change de forme : un objet plutôt qu'un tableau nu,
recherche/filtres/tri (mêmes paramètres search, filters, sorts qu'en mode non paginé)
appliqués avant la découpe en pages, jamais sur un sous-ensemble déjà chargé :
{
"rows": [ /* au plus pageSize lignes */ ],
"page": 1,
"pageSize": 50,
"total": 340,
"matchedTotal": 340
}
total est le nombre de lignes de la base (l'archive comprise seulement si
includeArchived=1) ; matchedTotal est le nombre de lignes qui correspondent à la
recherche/aux filtres en cours — les deux nombres du compteur « 12 sur 340 » affiché dans
l'interface. GET /api/databases/{id}/rows/count (mêmes paramètres) renvoie ces deux nombres
seuls, sans charger aucune ligne — pratique pour n'afficher qu'un total.
Les colonnes Relation (elle référence des pages par identifiant, pas par titre) et Formule (calculée, jamais stockée) ne sont pas triables ni filtrables en pagination : un tri ou un filtre qui les cible est silencieusement ignoré plutôt que de produire un résultat trompeur.
Synchroniser un tableau depuis un autre outil
Quand une autre application tient la donnée de référence — vos inscrits, vos clients, vos commandes — vous voulez que le tableau OIO en reflète l'état, sans le dupliquer à chaque envoi. C'est le rôle de l'upsert : vous désignez une colonne qui identifie la ligne (souvent l'adresse e-mail), et OIO se charge de créer la ligne la première fois, puis de la mettre à jour les fois suivantes.
Les colonnes se désignent par leur nom, tel qu'il apparaît en en-tête de votre tableau.
curl -X POST \
-H "X-API-Key: oio_votre_cle" \
-H "Content-Type: application/json" \
-d '{
"matchProperty": "Email",
"matchValue": "jean@exemple.fr",
"title": "Jean Dupont",
"values": {
"Email": "jean@exemple.fr",
"Inscription": "En cours",
"Rôle": "Développeur"
}
}' \
https://votre-instance/api/databases/12/rows/upsert
La réponse indique si la ligne vient d'être créée, et signale les colonnes que votre envoi mentionnait sans qu'elles existent dans le tableau :
{
"pageId": 87,
"title": "Jean Dupont",
"created": true,
"matchedCount": 0,
"values": { "Email": "jean@exemple.fr", "Inscription": "En cours", "Rôle": "Développeur" },
"ignoredProperties": []
}
Quelques comportements à connaître avant de brancher votre synchronisation :
- Seules les colonnes que vous envoyez sont écrites. Celles que vous omettez gardent leur valeur : vous pouvez donc n'envoyer que ce qui a changé, et laisser intactes les colonnes que vos collègues remplissent à la main dans OIO.
- Une valeur vide efface la colonne. C'est ce qui permet de propager une donnée supprimée chez vous. Pour ne pas toucher une colonne, ne la mentionnez pas du tout.
- Une colonne inconnue n'interrompt rien. Son nom est renvoyé dans
ignoredProperties: le reste de la ligne est bien écrit, et vous voyez immédiatement quel intitulé ne correspond à rien — le plus souvent une faute de frappe ou un accent. - Une colonne « Auteur » ne s'écrit jamais. Elle reflète automatiquement le créateur de
la ligne et refuse toute valeur envoyée — elle apparaît elle aussi dans
ignoredProperties, comme une colonne inconnue. - La valeur par défaut d'une liste déroulante ne s'applique pas ici. Elle est réservée aux lignes créées depuis le tableau ; l'upsert n'écrit que ce que vous transmettez.
- Les listes de choix s'enrichissent toutes seules. Une valeur absente des options existantes y est ajoutée, avec une couleur prise dans la palette. Vous n'avez pas à déclarer vos statuts à l'avance.
- La casse compte, par défaut :
Jean@Exemple.fretjean@exemple.frsont deux lignes distinctes. Ajoutez"caseSensitive": falsepour que les deux graphies désignent la même. - En cas de doublons, c'est la ligne la plus ancienne qui est mise à jour, et
matchedCountvous indique combien de lignes correspondaient — un chiffre supérieur à 1 signale un ménage à faire dans le tableau.
Une requête sans colonne clé, sans valeur de correspondance, ou désignant une colonne clé
qui n'existe pas dans le tableau, est refusée avec un code 400 et un message explicite.
Ce qui est refusé, et pourquoi
Une clé en lecture seule reçoit un 403 sur toute écriture, y compris un commentaire.
Une clé restreinte à certaines pages ne voit pas les autres — elles n'apparaissent ni dans
les recherches, ni dans les listes, ni dans les autocomplétions. Une page absente d'un
résultat peut donc simplement être hors du périmètre de la clé.