Aller au contenu
Développement medium

Hoppscotch : alternative open source à Postman

18 min de lecture

Hoppscotch est un client d'API open source, sous licence MIT, que vous pouvez héberger sur votre propre serveur. Il remplit le même rôle que Postman ou Insomnia (construire des requêtes HTTP, les organiser en collections, écrire des tests) avec une différence qui change tout en entreprise : vos collections, vos jetons et vos URLs internes ne quittent jamais votre infrastructure. Ce guide montre comment l'installer avec Docker Compose, écrire une collection de tests, puis rejouer ces tests en intégration continue grâce au CLI hopp. Tout a été validé sur la version 2026.6.0.

  • Situer Hoppscotch face à Postman, Insomnia et Bruno, et savoir quand il ne convient pas
  • Auto-héberger la Community Edition avec Docker Compose, base PostgreSQL comprise
  • Franchir les deux pièges qui empêchent le service de démarrer au premier lancement
  • Écrire une collection de tests d'API et la rejouer en une seule commande
  • Brancher ces tests sur une CI GitHub Actions qui échoue quand une API régresse

Postman reste l'outil le plus répandu, mais il a progressivement déplacé son centre de gravité vers le cloud. Les collections se synchronisent sur les serveurs de l'éditeur, le mode hors ligne s'est réduit, et un compte est demandé pour les usages collaboratifs. Pour une équipe qui manipule des jetons d'authentification et des URLs d'API internes, cela signifie que des éléments sensibles transitent vers un tiers.

Hoppscotch prend le problème à l'envers. Le cœur du produit est sous licence MIT et la version dite Community Edition s'installe sur votre serveur. Vous gardez la même ergonomie (un onglet, une requête, un bouton « envoyer ») mais la donnée reste chez vous. C'est l'argument décisif dans les contextes réglementés ou simplement lorsque la politique de sécurité interdit de sortir des identifiants du réseau.

Voici comment les outils se répartissent, sans complaisance.

OutilModèleStockage des collectionsPoint fortLimite
PostmanPropriétaire, freemiumCloud de l'éditeurÉcosystème très richeLa donnée sort de chez vous
HoppscotchOpen source MITChez vous si auto-hébergéLéger, web, auto-hébergeableÉcosystème plus jeune
InsomniaOpen source, éditeur KongCloud ou localInterface soignéeCompte demandé par défaut
BrunoOpen sourceFichiers dans votre dépôt GitCollections versionnéesPas de collaboration serveur

Le choix se fait sur un critère simple. Si vous voulez que vos collections vivent dans Git aux côtés du code, Bruno est plus direct. Si vous voulez un service partagé par l'équipe, avec des espaces de travail et une console d'administration, mais hébergé par vos soins, Hoppscotch est le bon candidat. Et si vous ne testez qu'un endpoint de temps en temps, curl ou HTTPie suffisent largement.

Le lab tient sur un poste de développement ordinaire. Il vous faut :

  • Docker et le plugin Compose en place, avec les bases vues dans le guide Docker Compose
  • Node.js 22 minimum pour le CLI, car les versions antérieures ne sont pas supportées
  • Environ 2 Go de RAM libres et les ports 3000, 3100 et 3170 disponibles
  • Des notions d'API REST : méthodes HTTP, codes de statut, corps JSON

L'image officielle est dite AIO (all-in-one) : elle embarque l'application web, la console d'administration et le backend dans un seul conteneur, qui expose trois ports distincts. Il ne manque qu'une base PostgreSQL pour stocker les comptes et les collections.

Créez un dossier de travail et déposez-y ce fichier compose.yaml. Les images sont épinglées par empreinte (sha256), afin qu'une reconstruction six mois plus tard installe exactement la même version.

name: hoppscotch
services:
db:
image: postgres@sha256:742f40ea20b9ff2ff31db5458d127452988a2164df9e17441e191f3b72252193 # postgres:17-alpine
environment:
POSTGRES_USER: hoppscotch
POSTGRES_PASSWORD: hoppscotch
POSTGRES_DB: hoppscotch
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U hoppscotch"]
interval: 5s
timeout: 5s
retries: 10
hoppscotch:
image: hoppscotch/hoppscotch@sha256:4e95eb2c49bde22b94b2aaa889b15d0a1bf995ba5c23e368f7e905d977053072 # 2026.6.0
env_file: .env
restart: unless-stopped
ports:
- "3000:3000" # application
- "3100:3100" # console d'administration
- "3170:3170" # backend (API et GraphQL)
depends_on:
db:
condition: service_healthy
volumes:
db-data:

La directive restart: unless-stopped n'est pas un confort : elle est indispensable, pour une raison expliquée juste après.

Hoppscotch se configure entièrement par variables d'environnement. Voici le minimum viable pour un lab local, dans un fichier .env placé à côté du compose.yaml.

Fenêtre de terminal
DATABASE_URL=postgresql://hoppscotch:hoppscotch@db:5432/hoppscotch
# Secrets : à régénérer avant toute mise en service réelle
JWT_SECRET=changez_moi_absolument
SESSION_SECRET=changez_moi_aussi
DATA_ENCRYPTION_KEY=0123456789abcdef0123456789abcdef
TOKEN_SALT_COMPLEXITY=10
MAGIC_LINK_TOKEN_VALIDITY=3
REFRESH_TOKEN_VALIDITY=604800000
ACCESS_TOKEN_VALIDITY=86400000
# false uniquement parce que le lab tourne en HTTP sur localhost
ALLOW_SECURE_COOKIES=false
VITE_ALLOWED_AUTH_PROVIDERS=EMAIL
REDIRECT_URL=http://localhost:3000
WHITELISTED_ORIGINS=http://localhost:3170,http://localhost:3000,http://localhost:3100
VITE_BASE_URL=http://localhost:3000
VITE_SHORTCODE_BASE_URL=http://localhost:3000
VITE_ADMIN_URL=http://localhost:3100
VITE_BACKEND_GQL_URL=http://localhost:3170/graphql
VITE_BACKEND_WS_URL=ws://localhost:3170/graphql
VITE_BACKEND_API_URL=http://localhost:3170/v1

DATA_ENCRYPTION_KEY doit faire exactement 32 caractères : c'est elle qui chiffre les données sensibles en base. Les variables préfixées VITE_ sont lues par le navigateur, pas par le serveur. Elles doivent donc contenir les URLs telles que votre poste les voit. Si vous publiez l'application sur un autre port que 3000, ou derrière un nom de domaine, ces valeurs doivent suivre, faute de quoi l'interface s'affichera mais appellera un backend introuvable.

Deux comportements du produit surprennent au premier lancement. Les connaître évite une demi-heure de perplexité.

  1. Jouer les migrations de base avant tout démarrage. Le backend refuse de démarrer tant que le schéma n'existe pas en base, avec le message Database migration not found. La documentation suggère d'entrer dans le conteneur, ce qui est impossible puisqu'il vient précisément de s'arrêter. Passez par un conteneur jetable :

    Fenêtre de terminal
    docker compose run --rm --entrypoint sh hoppscotch \
    -c "cd /dist/backend && pnpm exec prisma migrate deploy"

    La sortie doit se terminer par All migrations have been successfully applied.

  2. Lancer la pile :

    Fenêtre de terminal
    docker compose up -d
  3. Comprendre le premier arrêt volontaire. Au tout premier démarrage, le backend remplit sa table de configuration, affiche Stopping app in 5 seconds... puis s'arrête de lui-même. C'est voulu. Sans restart: unless-stopped, le conteneur reste mort et vous croyez à un plantage. Avec la politique de redémarrage, Docker le relance et l'instance devient saine.

  4. Vérifier que le service répond :

    Fenêtre de terminal
    curl -s http://localhost:3170/ping

    La réponse attendue est Success. L'application est alors accessible sur http://localhost:3000 et la console d'administration sur http://localhost:3100.

L'interface reprend les codes d'un client d'API classique : la requête au centre, les collections à droite, et les onglets pour le corps, les en-têtes, l'authentification et les scripts de test.

Interface de Hoppscotch auto-hébergé, avec la barre d'URL, les onglets de requête et le panneau des collections

La console d'administration, elle, vous accueille au premier accès avec un assistant de configuration. Il réclame un moyen d'authentification : soit un relais SMTP (les comptes se connectent alors par lien envoyé par courriel), soit un fournisseur OAuth. Tant que ce choix n'est pas fait, personne ne peut créer de compte.

Écran d'accueil de la console d'administration de Hoppscotch, demandant de configurer SMTP ou OAuth

Le premier compte créé devient administrateur. Sur une instance réelle, renseignez les variables MAILER_* vers votre relais SMTP. Pour un lab, le plus simple est d'ajouter un conteneur Mailpit, qui capture les messages au lieu de les envoyer : les liens de connexion s'affichent dans une boîte locale, sans dépendre d'un vrai serveur de mail.

C'est ici que Hoppscotch dépasse le simple client graphique. Une collection est un fichier JSON qui contient des requêtes et, pour chacune, un script de test en JavaScript. Le CLI hopp rejoue ce fichier hors de tout navigateur, ce qui le rend utilisable dans une chaîne d'intégration continue.

Le CLI exige Node.js 22 ou plus récent. Plutôt que d'installer Node globalement, épinglez la version par projet avec mise, puis installez le paquet en fixant sa version.

Fenêtre de terminal
mise use node@22.22.0
npm install -g @hoppscotch/cli@0.31.3
hopp -v

Notez le drapeau : c'est bien -v ou --ver, et non --version que la documentation laisse supposer. La version affichée porte encore la mention ALPHA, ce qui invite à épingler la version du CLI dans vos pipelines plutôt qu'à suivre aveuglément la dernière publiée.

Une collection minimale ressemble à ceci. Elle interroge une API de démonstration, vérifie le code de statut et le contenu de la réponse. La variable baseUrl, écrite entre doubles chevrons dans le champ endpoint, sera fournie par un fichier d'environnement séparé.

{
"v": 6,
"name": "API httpbin",
"folders": [],
"auth": { "authType": "inherit", "authActive": true },
"headers": [],
"requests": [
{
"v": "11",
"id": "req-status",
"name": "Le service repond",
"method": "GET",
"endpoint": "<<baseUrl>>/get",
"params": [],
"headers": [],
"preRequestScript": "",
"testScript": "pw.test(\"Le code de retour est 200\", () => {\n pw.expect(pw.response.status).toBe(200);\n});",
"auth": { "authType": "none", "authActive": false },
"body": { "contentType": null, "body": null },
"requestVariables": [],
"responses": {}
}
]
}

Deux détails de format coûtent cher, car ils ne sont pas documentés et le message d'erreur ne les désigne pas. Les champs auth et headers sont obligatoires au niveau de la collection, pas seulement au niveau de chaque requête : sans eux, le CLI rejette le fichier avec un laconique MALFORMED_COLLECTION. En pratique, exportez une collection depuis l'interface plutôt que de l'écrire à la main, puis versionnez ce fichier dans votre dépôt.

Le fichier d'environnement, lui, porte les valeurs qui changent d'un contexte à l'autre. Chaque variable veut un couple initialValue et currentValue : l'ancien format à clé value, encore visible dans de nombreux tutoriels, produit une erreur MALFORMED_ENV_FILE.

{
"v": 2,
"id": "env-lab",
"name": "lab",
"variables": [
{
"key": "baseUrl",
"initialValue": "http://localhost:8080",
"currentValue": "http://localhost:8080",
"secret": false
}
]
}

Les scripts de test utilisent l'espace de noms pw. Vous disposez de pw.test() pour nommer un cas, de pw.expect() pour l'assertion, et de pw.response pour accéder au statut et au corps de la réponse. Un test qui vérifie une valeur métier s'écrit aussi simplement que cela :

pw.test("Le corps envoye est bien recu", () => {
pw.expect(pw.response.body.json.equipe).toBe("plateforme");
});

Une seule commande suffit, l'environnement étant passé avec -e :

Fenêtre de terminal
hopp test -e env-lab.json httpbin.json

La sortie liste chaque requête, chaque assertion, puis un récapitulatif du type Test Cases: 0 failed 5 passed. Le point qui compte pour l'automatisation est ailleurs : le CLI renvoie 0 si tout passe et 1 dès qu'un test échoue. C'est ce code de retour qui permettra à une CI de bloquer une régression, sans avoir à analyser la sortie texte.

Comme le CLI est un simple paquet npm et qu'il respecte les codes de retour, l'intégrer à GitHub Actions tient en quelques lignes. Le drapeau --reporter-junit produit en plus un rapport JUnit que la plateforme sait afficher.

name: Tests API
on:
push:
branches: [main]
pull_request:
permissions: {}
jobs:
hopp:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: '22'
- name: Installer le CLI Hoppscotch
run: npm install -g @hoppscotch/cli@0.31.3
- name: Jouer la collection
run: hopp test -e collections/env-ci.json collections/httpbin.json --reporter-junit rapport.xml
- name: Publier le rapport
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: rapport-tests-api
path: rapport.xml

Les actions sont épinglées par empreinte de commit et les permissions réduites au strict nécessaire, conformément à ce que vérifient des outils comme actionlint. L'étape de publication porte if: always() pour que le rapport remonte même quand les tests échouent, moment où il est justement le plus utile.

Gardez un fichier d'environnement distinct par contexte (env-ci.json, env-recette.json) : seule l'URL de base change, la collection reste la même. Les valeurs sensibles, elles, n'ont rien à faire dans ces fichiers versionnés ; passez-les par les secrets de la plateforme et marquez la variable correspondante en secret.

Un lab en localhost tolère les raccourcis, une instance partagée non. Quatre points méritent votre attention avant d'ouvrir le service à l'équipe.

Les secrets du fichier .env doivent être générés, jamais recopiés d'un tutoriel. JWT_SECRET, SESSION_SECRET et surtout DATA_ENCRYPTION_KEY protègent les jetons stockés en base : une valeur d'exemple laissée en place revient à publier vos identifiants d'API. Un openssl rand -hex 16 fournit les 32 caractères attendus par la clé de chiffrement.

Le service doit tourner derrière HTTPS, avec un reverse proxy qui termine le TLS. Repassez alors ALLOW_SECURE_COOKIES à true : c'est cette variable qui empêche le cookie de session de circuler en clair. Les URLs VITE_* et WHITELISTED_ORIGINS doivent refléter le nom de domaine public, pas localhost.

La console d'administration, sur le port 3100, donne accès à la configuration de l'instance et à la liste des comptes. Elle n'a aucune raison d'être jointe depuis Internet : restreignez-la au réseau interne ou placez-la derrière une authentification supplémentaire. Enfin, RATE_LIMIT_TTL et RATE_LIMIT_MAX plafonnent le nombre de requêtes par adresse IP et limitent l'intérêt d'une attaque par force brute sur les liens de connexion.

Les erreurs rencontrées lors de la mise en place de ce guide, et ce qui les corrige.

SymptômeCauseSolution
Database migration not found puis arrêtLe schéma n'existe pas encore en baseJouer prisma migrate deploy dans un conteneur jetable avant le démarrage
Le conteneur s'arrête avec le code 0 après Stopping app in 5 seconds...Arrêt volontaire après l'initialisation de la configurationAjouter restart: unless-stopped au service
L'interface s'affiche mais aucune requête ne partLes variables VITE_* pointent vers un backend inaccessibleAligner VITE_BACKEND_API_URL et WHITELISTED_ORIGINS sur les ports réellement publiés
MALFORMED_COLLECTIONauth ou headers absents au niveau de la collectionAjouter les deux champs, ou réexporter la collection depuis l'interface
MALFORMED_ENV_FILEFormat d'environnement obsolète à clé valueUtiliser initialValue et currentValue
Bind for 0.0.0.0:3000 failedLe port est déjà pris par un autre serviceChanger le port publié et les variables VITE_* correspondantes
Aucun courriel de connexion ne parvientRelais SMTP absent ou mal configuréVérifier les variables MAILER_*, ou utiliser mailpit en local

Les réponses ci-dessous reprennent les questions les plus posées sur Hoppscotch : son modèle open source, son positionnement face à Postman et les erreurs de format qui bloquent le CLI. Chacune renvoie à la section du guide qui la traite en détail.

  • Hoppscotch est un client d'API open source (MIT) qui s'auto-héberge : vos collections et vos jetons restent chez vous.
  • L'installation passe par une image AIO et une base PostgreSQL, avec trois ports distincts pour l'application, l'administration et le backend.
  • Deux pièges bloquent le premier démarrage : les migrations à jouer avant tout lancement et l'arrêt volontaire du backend qui impose une politique de redémarrage.
  • Les variables VITE_* sont lues par le navigateur : elles doivent refléter les URLs réellement publiées, sinon l'interface appelle un backend fantôme.
  • Le CLI hopp rejoue une collection hors navigateur et renvoie 1 en cas d'échec, ce qui suffit à casser une CI sur une régression d'API.
  • Le format des fichiers est strict et peu documenté : auth et headers au niveau collection, initialValue et currentValue côté environnement.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn