Documentation

Tout ce qu'il faut pour brancher ton app sur ton backend Clicbase. L'API suit les conventions Supabase/PostgREST : si tu connais l'une, tu connais l'autre.

Démarrage rapide

1. Crée un projet dans le dashboard : tu obtiens une base PostgreSQL isolée, une URL d'API et tes clés (anon côté navigateur, service côté serveur uniquement).

2. Crée une table (éditeur SQL du dashboard) :

create table articles (
  id uuid primary key default gen_random_uuid(),
  title text not null,
  created_at timestamptz default now()
);
-- l'API la sert immédiatement, sans redéploiement

3. Lis-la depuis ton app (remplace <slug> par l'identifiant de ton projet) :

const res = await fetch(
  "https://clicbase.com/db/<slug>/articles?select=*&order=created_at.desc",
  { headers: { apikey: "<clé anon>" } }
);
const articles = await res.json();

Connecter une IA (MCP)

MCP est le protocole par lequel un assistant reçoit des outils plutôt que des explications. Une fois le serveur branché, tu demandes en langage courant : Claude crée tes tables, écrit tes requêtes, pose tes règles de sécurité et lit tes données, sans que tu recopies une clé nulle part.

Sur ton propre projet, c'est la variante clicbase-db-mcp. Les deux valeurs se trouvent dans le tableau de bord, en ouvrant ton projet puis sa section API: « API REST » donne l'URL, « Clé service » donne la clé.

claude mcp add ma-base \
  -e CLICBASE_DB_URL=https://clicbase.com/db/<slug> \
  -e CLICBASE_SERVICE_KEY=<clé service> \
  -e CLICBASE_READ_ONLY=1 \
  -- npx -y -p @clicbase/mcp clicbase-db-mcp

Cette section API affiche la commande déjà remplie, avec un bouton pour la copier · rien à assembler à la main.

Pour créer des projets, et non en administrer un seul, le serveur tout-en-un prend une clé de compte cbk_…, qui se génère dans le menu VPS ou Docker Clé API. Elle n'est affichée qu'une fois : le serveur n'en garde qu'une empreinte. C'est une permissionet non une identité, à la différence d'un mot de passe · elle a une portée, une expiration, et un clic la révoque sans rien casser ailleurs.

claude mcp add clicbase \
  -e CLICBASE_API_KEY=cbk_... \
  -e CLICBASE_READ_ONLY=1 \
  -- npx -y -p @clicbase/mcp clicbase-mcp

-pdésigne le paquet à installer, l'argument suivant la commande à lancer. Sans lui, npx cherche une commande portant le dernier segment du nom du paquet, et npx -y @clicbase/mcp échouait sur could not determine executable to run : le paquet en porte plusieurs. Réparé en 0.1.1, la forme -p reste la plus sûre.

À la main, dans ~/.claude.json ou claude_desktop_config.json :

{
  "mcpServers": {
    "clicbase": {
      "command": "npx",
      "args": ["-y", "@clicbase/mcp"],
      "env": {
        "CLICBASE_API_KEY": "cbk_...",
        "CLICBASE_READ_ONLY": "1"
      }
    }
  }
}

CLICBASE_READ_ONLY=1est dans la commande exprès : c'est le mode à garder par défaut. En lecture seule, les outils qui écrivent ne sont pas refusés, ils sont absents. Un outil présent qui répond « interdit » laisse l'assistant croire qu'un chemin existe, donc essayer, reformuler, insister. Un outil qui n'est pas dans la liste n'est jamais demandé.

Restent list_tables, describe_table, get_oauth_provider, clicbase_conventions, list_site_files, list_sftp_accounts, list_sites et list_projects. Partent run_sql, create_database, enable_realtime, enable_rls, create_policy, set_oauth_provider, set_email_smtp, get_credentials, read_site_file, create_sftp_account et delete_sftp_account.

create_sftp_account part aussi : il ne touche à aucune donnée, et il rend un mot de passe qui ouvre tout le dossier du site. Il fabrique un compte dédié, jamais le compte principal · celui-là est l'identité du site, il ne se révoque pas.

read_site_file part pour la même raison : lister les fichiers d'un site révèle une structure, lire leur contenu peut livrer des identifiants écrits en dur dans un config.php. Les fichiers cachés, eux, sont refusés à tout niveau · .env ne peut ni être déposé ni être lu.

get_credentials ne modifie rien, et il part quand même : il rend la clé service du projet, laquelle ouvre le SQL complet et contourne la RLS. Le garder reviendrait à retirer run_sqld'une main et à livrer de quoi le refaire de l'autre.

Sans cette ligne, le mode complet rend run_sql, donc du SQL arbitraire avec les droits du propriétaire de la base. Garde-le pour ta propre plateforme, sous tes yeux. Pour la base d'un client, ou pour un agent qui travaille sans personne devant l'écran, reste en lecture seule : aucune liste de mots interdits ne distingue un DROP TABLE prévu d'un DROP TABLE accidentel.

L'assistant n'arrive pas les mains vides. Le serveur pose ses conventions dans le contexte du modèle dès la connexion, avant le premier appel : la forme exacte d'une policy d'écriture, le fait qu'un grant n'enlève rien sans revoke, le notify pgrst, 'reload schema' qui suit toute DDL. Ces six pièges ont en commun de répondre 200 OK: un assistant qui les ignore croit avoir réussi. L'outil clicbase_conventions en rend le détail quand il en a besoin.

Le paquet est public et sous licence MIT : npmjs.com/package/@clicbase/mcp · code source sur github.com/clicbase/mcp. Une variante limitée à un seul projet, clicbase-db-mcp, prend CLICBASE_DB_URL et CLICBASE_SERVICE_KEY au lieu de la clé de compte.

API REST (tables)

Chaque table de ton schéma public est exposée sur /db/<slug>/<table> avec la syntaxe PostgREST. La sécurité se règle en base (RLS), pas dans ton code.

# Lire (filtres, tri, pagination)
GET /db/<slug>/articles?select=id,title&status=eq.published&order=created_at.desc&limit=10

# Créer
POST /db/<slug>/articles
Content-Type: application/json
{ "title": "Bonjour" }

# Modifier
PATCH /db/<slug>/articles?id=eq.<uuid>
{ "title": "Nouveau titre" }

# Supprimer
DELETE /db/<slug>/articles?id=eq.<uuid>

# En-têtes (toutes les requêtes)
apikey: <clé anon>
Authorization: Bearer <token utilisateur>   # après connexion (sinon rôle anon)

Authentification

Comptes email + mot de passe intégrés, confirmation d'email en option, OAuth Google si configuré. Le token retourné s'utilise en Authorization: Bearer sur l'API REST : la RLS voit alors l'utilisateur connecté.

# Inscription
POST /db/<slug>/auth/signup        { "email": "...", "password": "..." }

# Connexion
POST /db/<slug>/auth/login         { "email": "...", "password": "..." }
# → { "token": "...", "user": { ... } }

# Compatible clients Supabase (GoTrue)
POST /db/<slug>/auth/token?grant_type=password

# Mot de passe oublié / réinitialisation
POST /db/<slug>/auth/recover       { "email": "..." }
POST /db/<slug>/auth/reset         { "token": "...", "password": "..." }

# Utilisateur courant
GET  /db/<slug>/auth/user          (Authorization: Bearer <token>)

# OAuth Google (si activé sur le projet)
GET  /db/<slug>/auth/authorize/google?redirect_to=<url>

Storage (fichiers)

# Envoyer un fichier
POST /db/<slug>/storage/v1/object/<bucket>/<chemin/fichier.jpg>
(corps = fichier binaire, Authorization: Bearer <token>)

# Télécharger / servir
GET  /db/<slug>/storage/v1/object/<bucket>/<chemin>

# Image redimensionnée à la volée
GET  /db/<slug>/storage/v1/render/image/<bucket>/<chemin>?width=400

# Gérer les buckets
GET/POST /db/<slug>/storage/v1/bucket

Les buckets peuvent être publics, privés, ou « owner-scoped » (chaque utilisateur n'écrit que dans son dossier).

Realtime

Abonne-toi aux changements d'une table en websocket :

const ws = new WebSocket(
  "wss://clicbase.com/db/<slug>/realtime?apikey=<clé anon>"
);
ws.onopen = () =>
  ws.send(JSON.stringify({ type: "subscribe", table: "articles" }));
ws.onmessage = (e) => {
  const { event, record } = JSON.parse(e.data); // INSERT | UPDATE | DELETE
  console.log(event, record);
};

Functions

Du code serveur déployé depuis le dashboard, appelé en HTTP :

POST /db/<slug>/functions/v1/<nom-de-la-fonction>
apikey: <clé anon>
{ "n'importe": "quel JSON" }

Emails

Envoi d'emails transactionnels depuis ton projet (adresse à ton domaine), avec modèles gérés dans le dashboard :

# Envoi direct (clé service, côté serveur uniquement)
POST /db/<slug>/email/send
{ "to": "client@example.com", "subject": "...", "html": "..." }

# Envoi d'un modèle (variables substituées)
POST /db/<slug>/email/send-template
{ "template": "welcome", "to": "...", "vars": { "name": "Hina" } }

SDK JavaScript

Un client minimal et typé, sans dépendance :

npm install clicbase-js
import { createClient } from "clicbase-js";

const db = createClient("https://clicbase.com/db/<slug>", "<clé anon>");

// Auth
await db.auth.signUp({ email, password });
const { token, user } = await db.auth.signIn({ email, password });

// Tables (la RLS s'applique automatiquement au token)
const articles = await db.from("articles")
  .select("id,title").eq("status", "published")
  .order("created_at", { ascending: false }).limit(10).get();

await db.from("articles").insert({ title: "Bonjour" });

// Storage
await db.storage.upload("photos", "avatars/moi.jpg", file);
const url = db.storage.publicUrl("photos", "avatars/moi.jpg");

Tu utilises déjà @supabase/supabase-js ? Il fonctionne en pointant son URL sur https://clicbase.com/db/<slug> : l'API REST et le login (grant_type=password) suivent les mêmes conventions. C'est aussi la voie de la migration depuis Supabase, dans les deux sens.

Une question, un endpoint manquant dans cette doc ? contact@clicbase.com· réponse rapide, c'est le fondateur qui lit.