Skip to content
← Centre d'aide

Construire votre propre application sur Tulina

DevelopersMis à jour le

Tulina est un backend que vous avez déjà : tableaux, pages, projets, recherche, stockage de fichiers, et des agents qui travaillent avec vos connecteurs. Tout ce que fait l'application Tulina passe par une API REST, et votre propre front peut utiliser la même.

Un portail client, un outil interne ou une application pour vos clients peut donc n'être qu'un front : Tulina stocke les données, fait le travail, et reste la console où votre équipe gère le tout.

Pour qui. Le développeur qui construit ce front. Il vous faut un compte Tulina qui a accès à ce que le front utilisera.

Sur quoi construire

BriqueCe qu'elle apporte à votre frontPoint de départ
CompteQui appelle, et dans quel espace de travailGET /api/me
TableauxDes données structurées : lignes, recherche, filtres, historique/api/datastores/…/rows
PagesDu contenu markdown dans des projets : docs, notes, base de connaissancesPOST /api/me/docs
ProjetsLes conteneurs des pages, fichiers et tableauxPOST /api/me/projects
RechercheUne requête sur les pages, procédures, tableaux et lignesGET /api/me/search
FichiersUploads, images et imports en volumePOST /api/me/upload-url
AgentsLe travail fait avec vos connecteurs : enrichir, envoyer un email, mettre à jour un CRMPOST /api/hooks/…

La référence de l'API liste chaque endpoint, rangé de la même façon.

La seule règle : appeler Tulina depuis votre serveur

Navigateur du visiteur
      ↓
Votre serveur      ← garde le jeton
      ↓
API Tulina

Deux raisons, et ce sont des limites, pas des conseils :

  • Un jeton agit en votre nom. Qui le détient peut faire tout ce que votre compte peut faire. Placez-le dans le code du navigateur et chaque visiteur l'a.
  • Les navigateurs sur votre domaine sont refusés. L'API ne répond qu'aux requêtes de navigateur venant de l'application Tulina elle-même. Un fetch depuis les pages de votre site échoue avant d'atteindre vos données.

Votre serveur garde donc le jeton et n'expose que les quelques routes dont votre front a besoin. Vos visiteurs ne deviennent jamais des utilisateurs Tulina : votre serveur décide de ce que chacun peut voir et faire.

Pas de serveur ? Vous n'en avez peut-être pas besoin

« Serveur » veut seulement dire du code qui s'exécute ailleurs que dans le navigateur du visiteur. Deux façons d'en avoir un sans gérer de machine :

  • Un outil no-code. n8n, Make et Zapier ont chacun une étape de requête HTTP : gardez le jeton dans l'outil, et laissez l'envoi d'un formulaire ajouter une ligne à votre tableau Tulina.
  • Une fonction serverless. Vercel, Netlify ou Cloudflare exécutent un seul fichier à la demande, avec le jeton dans une variable d'environnement. L'exemple plus bas en est une : déployé sur Vercel, ce fichier est le serveur.

Les appels depuis un serveur, ou depuis n8n, Make ou Zapier, fonctionnent d'où que ce soit — rien à configurer de notre côté. Vous voulez appeler Tulina directement depuis les pages de votre site ? Écrivez à tech@tulina.ai avec votre domaine et ce dont le front a besoin, et nous trouverons la façon sûre de le faire.

Mise en place

Créer un jeton. Dans Tulina, ouvrez Settings → Personal → API tokens et cliquez sur New token. Il n'est affiché qu'une fois : placez-le directement dans les variables d'environnement de votre serveur, jamais dans votre code ni dans votre dépôt.

Un jeton a les accès du compte qui l'a créé, et il n'expire pas de lui-même. Créez-le depuis un compte dont les accès correspondent à ce dont le front a besoin, et révoquez-le depuis le même écran dès qu'il fuite ou que le projet se termine.

Trouver vos identifiants. Les adresses de Tulina les portent :

app.tulina.ai/org/42/tables/317
app.tulina.ai/org/42/projects/12

42 est votre espace de travail, 317 un tableau, 12 un projet. Utilisez les numéros plutôt que les noms : un renommage ne casse pas un numéro.

Faire un premier appel. GET /api/me dit qui est le jeton et dans quel espace de travail l'appel s'est exécuté — l'appel à faire en premier, et un bon test de santé.

curl https://mcp.tulina.ai/api/me \
  -H "Authorization: Bearer $TULINA_TOKEN" \
  -H "X-Oto-Org: 42"

Quatre conventions

  • Deux en-têtes à chaque appel. Authorization: Bearer … et X-Oto-Org: <espace>. Sans le second, l'appel s'exécute dans votre espace principal — ce qui convient tant que vous n'en avez qu'un.
  • Des numéros, pas des noms. Voir plus haut.
  • Certains chemins portent l'action dans le corps. Projets, pages et agents ont chacun un seul chemin, et le op du corps dit quoi faire : {"op": "list"}, {"op": "get", …}, {"op": "create", …}. La référence liste chaque op.
  • Une seule forme d'erreur. {"error": "<code>", "detail": "<phrase>"}. Décidez sur error, qui est stable ; journalisez detail, qui dit quoi corriger.

Recettes

Afficher et modifier des données

Les tableaux sont le point de départ de la plupart des fronts : une liste de leads, de commandes, de tickets, de réservations.

# Une page de lignes : offset= pour la suivante, q= pour chercher, order_by= pour trier
curl "https://mcp.tulina.ai/api/datastores/317/rows?limit=50" \
  -H "Authorization: Bearer $TULINA_TOKEN" -H "X-Oto-Org: 42"

# Ajouter une ligne : le corps est la ligne, une clé par colonne
curl -X POST "https://mcp.tulina.ai/api/datastores/317/rows" \
  -H "Authorization: Bearer $TULINA_TOKEN" -H "X-Oto-Org: 42" \
  -H "Content-Type: application/json" \
  -d '{"name": "Ada Lovelace", "email": "ada@example.com"}'

La lecture renvoie {"rows": [ … ], "total": …, "offset": …, "limit": …}, et chaque ligne porte son _id. Pour modifier une ligne, PATCH …/rows/<_id> avec seulement les colonnes qui changent. Pour en écrire plusieurs, POST …/rows/batch avec {"rows": [ … ], "key": "email"} : les lignes dont l'email existe sont mises à jour, les autres créées.

Publier du contenu

Les pages sont du markdown, rangé dans des projets : articles d'aide, documents d'un client, base de connaissances.

# L'index des pages du projet 12 : titres et numéros, pas les contenus
curl -X POST https://mcp.tulina.ai/api/me/docs \
  -H "Authorization: Bearer $TULINA_TOKEN" -H "X-Oto-Org: 42" \
  -H "Content-Type: application/json" \
  -d '{"op": "list", "project_id": 12}'

Ensuite {"op": "get", "doc_id": …} renvoie une page avec son contenu, et {"op": "create", "project_id": 12, "title": "…", "body_md": "…"} en écrit une nouvelle.

Ajouter la recherche

Un seul appel cherche dans tout ce que le jeton peut lire — pages, procédures, tableaux, et les lignes qu'ils contiennent :

curl "https://mcp.tulina.ai/api/me/search?q=facture+acme&limit=10" \
  -H "Authorization: Bearer $TULINA_TOKEN" -H "X-Oto-Org: 42"

La réponse contient hits, avec total et truncated pour distinguer « 10 résultats » de « 10 sur 300 ». Ajoutez kinds=page pour ne chercher que dans les pages ; la référence liste les autres types.

Confier le travail à un agent

Votre front n'a pas à refaire ce que les agents de Tulina font déjà avec vos connecteurs : enrichir un contact, rédiger et envoyer un email, mettre à jour le CRM. Confiez plutôt la tâche à un agent.

  1. Dans Tulina, allez dans Agents → New agent → On an event, et choisissez la procédure qu'il suit et les outils qu'il peut utiliser.
  2. Sur la page de l'agent, Connect a sender affiche son Address et un Bearer token. Réglez ce qu'il reçoit sur Pass it to the agent.
  3. Votre serveur envoie l'événement :
curl -X POST "<l'adresse de l'agent>" \
  -H "Authorization: Bearer $AGENT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"email": "ada@example.com", "company": "Acme"}'

L'agent s'exécute en arrière-plan. Faites écrire le résultat par sa procédure là où votre front lit — une ligne dans un tableau, une page — et affichez-le depuis là.

Envoyer des fichiers

Les fichiers vont directement à Tulina, sans passer par la mémoire de votre serveur. Demandez un lien à usage unique, puis envoyez-y le contenu :

curl -X POST https://mcp.tulina.ai/api/me/upload-url \
  -H "Authorization: Bearer $TULINA_TOKEN" -H "X-Oto-Org: 42" \
  -H "Content-Type: application/json" \
  -d '{"target": "project_file", "project_id": 12, "filename": "contrat.pdf"}'

La réponse contient une url : envoyez-y le fichier en PUT, sans en-tête Authorization. Le même lien accepte une page (doc), une image (qui obtient une adresse publique), ou un fichier CSV ou NDJSON de lignes pour un tableau — la façon de charger des milliers de lignes d'un coup.

Un serveur minimal

Chaque recette suit le même schéma de votre côté : une route qui appelle Tulina avec le jeton, et ne transmet que ce dont le front a besoin. Le voici pour un front qui liste des leads et en ajoute, sous forme d'un route handler Next.js — n'importe quel langage serveur fonctionne de la même façon.

// app/api/leads/route.ts — s'exécute sur votre serveur. Le jeton n'atteint jamais le navigateur.
const TABLE = "https://mcp.tulina.ai/api/datastores/317/rows";
const headers = {
  Authorization: `Bearer ${process.env.TULINA_TOKEN}`,
  "X-Oto-Org": "42",
  "Content-Type": "application/json",
};

export async function GET() {
  const res = await fetch(`${TABLE}?limit=50`, { headers });
  const { rows } = await res.json();
  return Response.json(rows);
}

export async function POST(request: Request) {
  // Choisissez les champs acceptés : un visiteur ne doit pas pouvoir écrire n'importe quelle colonne.
  const { name, email } = await request.json();
  const res = await fetch(TABLE, {
    method: "POST",
    headers,
    body: JSON.stringify({ name, email }),
  });
  return Response.json(await res.json(), { status: res.status });
}

Vos pages appellent ensuite /api/leads sur votre propre domaine. Rien de Tulina n'atteint le navigateur.

Quand quelque chose échoue

errorCe que cela veut dire
missing_bearerL'en-tête Authorization manque.
invalid_api_tokenLe jeton est faux, ou il a été révoqué.
revision_conflictUne ligne a changé depuis la _revision envoyée avec ?expected_revision=. Relisez-la, puis réessayez.

Aller plus loin

La référence de l'API contient chaque endpoint, paramètre et réponse. Son bouton Ask Claude ouvre Claude avec la référence déjà dans le message : décrivez l'application que vous voulez, il écrit les appels avec vous.

Toujours bloqué ? Parlez-nous.

Essayez Tulina pendant 7 jours.

Combien de personnes utiliseront Tulina ?

En continuant, vous acceptez nos conditions d’utilisation et notre politique de confidentialité.