OTOMY
DIGITAL PRODUCTS6 juin 20266 min

Construire une API REST en 48h avec Supabase Edge Functions

Vous pensez qu'une API REST robuste nécessite des semaines de développement ? Avec Supabase Edge Functions, 48 heures suffisent pour passer de l'idée au déploiement. Voici le guide complet, étape par étape.

M

Par

Melissa Slimani

Construire une API REST en 48h avec Supabase Edge Functions

Pourquoi Supabase Edge Functions change la donne pour vos API REST

Chez Otomy, on accompagne des PME françaises et algériennes dans la création de produits digitaux performants. Et un constat revient sans cesse : les fondateurs perdent des semaines à mettre en place une infrastructure backend alors qu'ils pourraient déjà valider leur produit sur le marché.

Supabase Edge Functions, basées sur Deno Deploy, permettent d'écrire des fonctions serverless en TypeScript, déployées instantanément sur un CDN mondial. Combinées à la base de données PostgreSQL de Supabase, à l'authentification intégrée et au stockage, elles forment un backend complet en quelques heures.

Voici comment nous construisons une API REST complète en 48 heures — pas un POC bancal, mais une API prête pour la production.


Heures 0-4 : Architecture et modélisation des données

Avant d'écrire la moindre ligne de code, on pose les fondations.

Définir les ressources de l'API

Prenons un cas concret : une API de gestion de commandes pour un e-commerce algérien.

Ressources identifiées :

  • /orders — CRUD complet
  • /products — lecture seule pour le catalogue
  • /customers — gestion des profils clients
  • /webhooks — notifications vers n8n ou Make

Modéliser la base de données

Dans le SQL Editor de Supabase :

CREATE TABLE products (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  name TEXT NOT NULL,
  price NUMERIC(10,2) NOT NULL,
  stock INTEGER DEFAULT 0,
  created_at TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE orders (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  customer_id UUID REFERENCES auth.users(id),
  status TEXT DEFAULT 'pending' CHECK (status IN ('pending','confirmed','shipped','delivered')),
  total NUMERIC(10,2) NOT NULL,
  created_at TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE order_items (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  order_id UUID REFERENCES orders(id) ON DELETE CASCADE,
  product_id UUID REFERENCES products(id),
  quantity INTEGER NOT NULL,
  unit_price NUMERIC(10,2) NOT NULL
);

Astuce Otomy : Activez immédiatement les Row Level Security (RLS) policies. C'est non négociable en production.


Heures 4-16 : Développement des Edge Functions

Initialiser le projet

supabase init
supabase functions new orders-api

Structure d'une Edge Function RESTful

Voici le pattern que nous utilisons systématiquement pour gérer plusieurs méthodes HTTP dans une seule fonction :

// supabase/functions/orders-api/index.ts
import { serve } from "https://deno.land/std@0.177.0/http/server.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";

const corsHeaders = {
  "Access-Control-Allow-Origin": "*",
  "Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type",
};

serve(async (req) => {
  if (req.method === "OPTIONS") {
    return new Response("ok", { headers: corsHeaders });
  }

  const supabase = createClient(
    Deno.env.get("SUPABASE_URL")!,
    Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!
  );

  const url = new URL(req.url);
  const id = url.searchParams.get("id");

  try {
    switch (req.method) {
      case "GET": {
        const query = id
          ? supabase.from("orders").select("*, order_items(*)").eq("id", id).single()
          : supabase.from("orders").select("*, order_items(*)").order("created_at", { ascending: false });
        const { data, error } = await query;
        if (error) throw error;
        return new Response(JSON.stringify(data), {
          headers: { ...corsHeaders, "Content-Type": "application/json" },
        });
      }
      case "POST": {
        const body = await req.json();
        const { data, error } = await supabase.from("orders").insert(body).select().single();
        if (error) throw error;
        return new Response(JSON.stringify(data), {
          status: 201,
          headers: { ...corsHeaders, "Content-Type": "application/json" },
        });
      }
      case "PATCH": {
        if (!id) throw new Error("ID requis pour la mise à jour");
        const body = await req.json();
        const { data, error } = await supabase.from("orders").update(body).eq("id", id).select().single();
        if (error) throw error;
        return new Response(JSON.stringify(data), {
          headers: { ...corsHeaders, "Content-Type": "application/json" },
        });
      }
      default:
        return new Response("Méthode non autorisée", { status: 405, headers: corsHeaders });
    }
  } catch (err) {
    return new Response(JSON.stringify({ error: err.message }), {
      status: 400,
      headers: { ...corsHeaders, "Content-Type": "application/json" },
    });
  }
});

Validation des données

Utilisez Zod pour valider les entrées :

import { z } from "https://deno.land/x/zod@v3.22.4/mod.ts";

const OrderSchema = z.object({
  customer_id: z.string().uuid(),
  total: z.number().positive(),
  items: z.array(z.object({
    product_id: z.string().uuid(),
    quantity: z.number().int().positive(),
    unit_price: z.number().positive(),
  })).min(1),
});

Heures 16-30 : Authentification, sécurité et intégrations

Sécuriser l'API avec JWT

Supabase gère l'authentification nativement. Extrayez le token JWT de chaque requête :

const authHeader = req.headers.get("Authorization");
const { data: { user }, error } = await supabase.auth.getUser(
  authHeader?.replace("Bearer ", "")
);
if (!user) return new Response("Non autorisé", { status: 401, headers: corsHeaders });

Connecter n8n ou Make pour l'automatisation

Après la création d'une commande, déclenchez un workflow via webhook :

await fetch(Deno.env.get("N8N_WEBHOOK_URL")!, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ event: "order.created", data: newOrder }),
});

Ce webhook peut déclencher dans n8n : envoi d'email de confirmation, notification Slack, mise à jour du stock, ou sync avec un ERP.

Rate limiting basique

Stockez les compteurs dans Supabase KV ou une table dédiée pour limiter les abus.


Heures 30-42 : Tests et documentation

Tests automatisés

deno test --allow-net --allow-env supabase/functions/tests/

Écrivez des tests pour chaque endpoint. Utilisez Claude AI pour générer rapidement les cas limites à partir de votre schéma Zod.

Documentation avec OpenAPI

Générez une spec OpenAPI 3.0 et hébergez-la sur votre frontend Vercel ou Netlify. Les consommateurs de votre API vous remercieront.


Heures 42-48 : Déploiement et monitoring

Déployer en production

supabase functions deploy orders-api --project-ref votre-ref-projet

C'est tout. Votre API REST est live sur le edge, avec une latence inférieure à 50ms dans la plupart des régions.

Monitoring

  • Supabase Dashboard : logs en temps réel des Edge Functions
  • Logflare : intégré nativement pour l'analyse des logs
  • Uptime Robot ou Better Stack : monitoring de disponibilité

Checklist finale avant mise en production

  • ✅ RLS activé sur toutes les tables
  • ✅ Validation Zod sur tous les inputs
  • ✅ Authentification JWT vérifiée
  • ✅ CORS configuré (remplacer * par vos domaines)
  • ✅ Variables d'environnement en secrets Supabase
  • ✅ Tests automatisés passants
  • ✅ Webhooks n8n/Make opérationnels
  • ✅ Documentation OpenAPI publiée

Ce que vous obtenez en 48 heures

Composant Outil
Base de données Supabase PostgreSQL
API serverless Supabase Edge Functions (Deno)
Authentification Supabase Auth (JWT)
Automatisation n8n / Make via webhooks
Hébergement frontend Vercel / Netlify
Monitoring Logflare + Better Stack

Le résultat : une API REST complète, sécurisée, scalable, déployée mondialement — sans gérer un seul serveur.

Chez Otomy, c'est exactement cette approche que nous appliquons pour les PME qui veulent lancer un produit digital rapidement, que ce soit en France ou en Algérie. La vitesse d'exécution n'est pas l'ennemie de la qualité — à condition de choisir les bons outils.

OTOMY

Prêt à automatiser votre activité ?

Réservez un appel gratuit — 30 minutes pour identifier ce qu'on peut automatiser.