# PersoNotes REST API Documentation Version: **v1** Base URL: `http://localhost:8080/api/v1` ## Table des matières - [Vue d'ensemble](#vue-densemble) - [Authentification](#authentification) - [Formats de données](#formats-de-données) - [Endpoints](#endpoints) - [Lister les notes](#lister-les-notes) - [Récupérer une note](#récupérer-une-note) - [Créer/Mettre à jour une note](#créermettre-à-jour-une-note) - [Supprimer une note](#supprimer-une-note) - [Codes de statut HTTP](#codes-de-statut-http) - [Exemples d'utilisation](#exemples-dutilisation) --- ## Vue d'ensemble L'API REST de PersoNotes permet de gérer vos notes Markdown via HTTP. Elle supporte : - **Listage** : Récupérer la liste de toutes les notes avec métadonnées - **Lecture** : Télécharger une note en JSON ou Markdown brut - **Écriture** : Créer ou mettre à jour une note - **Suppression** : Supprimer une note définitivement ### Caractéristiques - ✅ **Versionnée** : `/api/v1` pour assurer la compatibilité future - ✅ **Content Negotiation** : Support JSON et Markdown selon le header `Accept` - ✅ **Idempotence** : PUT crée ou met à jour (idempotent) - ✅ **Automatisation** : Front matter géré automatiquement - ✅ **Ré-indexation** : Recherche mise à jour automatiquement après chaque modification - ✅ **Support sous-dossiers** : Organisation hiérarchique native --- ## Authentification **Version actuelle : Aucune authentification requise** ⚠️ **IMPORTANT** : L'API n'a pas d'authentification. Si vous exposez le serveur publiquement : 1. Utilisez un reverse proxy (nginx, Caddy) avec authentification 2. Implémentez Basic Auth ou API Key 3. Utilisez un VPN ou tunnel SSH --- ## Formats de données ### Note complète (NoteResponse) ```json { "path": "projet/backend.md", "title": "Backend API", "content": "---\ntitle: Backend API\n...\n---\n\n# Content", "body": "\n# Content", "frontMatter": { "title": "Backend API", "date": "10-11-2025", "last_modified": "10-11-2025:14:30", "tags": ["projet", "backend"] }, "lastModified": "10-11-2025:14:30", "size": 1024 } ``` ### Métadonnées de note (NoteMetadata) ```json { "path": "projet/backend.md", "title": "Backend API", "tags": ["projet", "backend"], "lastModified": "10-11-2025:14:30", "date": "10-11-2025", "size": 1024 } ``` ### Requête de création/modification (NoteRequest) Deux options : **Option 1 : Content complet** (recommandé pour migration) ```json { "content": "---\ntitle: Ma note\ntags: [test]\n---\n\n# Contenu" } ``` **Option 2 : Body + FrontMatter séparés** (recommandé pour création) ```json { "body": "\n# Mon contenu\n\nTexte ici...", "frontMatter": { "title": "Ma note", "tags": ["test", "exemple"] } } ``` ### Erreur (ErrorResponse) ```json { "error": "Bad Request", "message": "Invalid path", "code": 400 } ``` --- ## Endpoints ### Lister les notes Récupère la liste de toutes les notes avec leurs métadonnées. **Endpoint** : `GET /api/v1/notes` **Paramètres** : Aucun **Réponse** : `200 OK` ```json { "notes": [ { "path": "projet/backend.md", "title": "Backend API", "tags": ["projet", "backend"], "lastModified": "10-11-2025:14:30", "date": "10-11-2025", "size": 1024 }, { "path": "daily/2025-11-10.md", "title": "Notes du 10 novembre", "tags": ["daily"], "lastModified": "10-11-2025:09:15", "date": "10-11-2025", "size": 2048 } ], "total": 2 } ``` **Exemple curl** : ```bash curl http://localhost:8080/api/v1/notes ``` --- ### Récupérer une note Télécharge une note spécifique. Le format dépend du header `Accept`. **Endpoint** : `GET /api/v1/notes/{path}` **Paramètres** : - `{path}` : Chemin relatif de la note (ex: `projet/backend.md`) **Headers** : - `Accept: application/json` (défaut) : Retourne JSON avec métadonnées - `Accept: text/markdown` : Retourne Markdown brut - `Accept: text/plain` : Retourne Markdown brut **Réponse JSON** : `200 OK` ```json { "path": "projet/backend.md", "title": "Backend API", "content": "---\ntitle: Backend API\ndate: 10-11-2025\nlast_modified: 10-11-2025:14:30\ntags:\n - projet\n - backend\n---\n\n# Backend API\n\nContenu de la note...", "body": "\n# Backend API\n\nContenu de la note...", "frontMatter": { "title": "Backend API", "date": "10-11-2025", "last_modified": "10-11-2025:14:30", "tags": ["projet", "backend"] }, "lastModified": "10-11-2025:14:30", "size": 1024 } ``` **Réponse Markdown** : `200 OK` ```markdown --- title: Backend API date: 10-11-2025 last_modified: 10-11-2025:14:30 tags: - projet - backend --- # Backend API Contenu de la note... ``` **Erreurs** : - `404 Not Found` : Note inexistante **Exemples curl** : ```bash # Récupérer en JSON curl http://localhost:8080/api/v1/notes/projet/backend.md \ -H "Accept: application/json" # Récupérer en Markdown brut curl http://localhost:8080/api/v1/notes/projet/backend.md \ -H "Accept: text/markdown" # Sauvegarder dans un fichier curl http://localhost:8080/api/v1/notes/projet/backend.md \ -H "Accept: text/markdown" \ -o backend.md ``` --- ### Créer/Mettre à jour une note Crée une nouvelle note ou met à jour une note existante (idempotent). **Endpoint** : `PUT /api/v1/notes/{path}` **Paramètres** : - `{path}` : Chemin relatif de la note (ex: `projet/nouvelle-note.md`) **Headers** : - `Content-Type: application/json` : Envoyer du JSON - `Content-Type: text/markdown` : Envoyer du Markdown brut **Body JSON** : ```json { "body": "\n# Ma nouvelle note\n\nContenu ici...", "frontMatter": { "title": "Ma nouvelle note", "tags": ["test", "exemple"] } } ``` Ou avec `content` complet : ```json { "content": "---\ntitle: Ma note\ntags: [test]\n---\n\n# Contenu" } ``` **Body Markdown brut** : ```markdown # Ma nouvelle note Contenu ici... ``` **Réponse** : `201 Created` (nouvelle note) ou `200 OK` (mise à jour) ```json { "path": "projet/nouvelle-note.md", "title": "Ma nouvelle note", "content": "---\ntitle: Ma nouvelle note\n...", "body": "\n# Ma nouvelle note\n\nContenu ici...", "frontMatter": { "title": "Ma nouvelle note", "date": "10-11-2025", "last_modified": "10-11-2025:14:35", "tags": ["test", "exemple"] }, "lastModified": "10-11-2025:14:35", "size": 256 } ``` **Comportement** : - ✅ Crée automatiquement les dossiers parents - ✅ Génère le front matter si absent - ✅ Met à jour `last_modified` automatiquement - ✅ Préserve `date` pour notes existantes - ✅ Ré-indexe automatiquement pour la recherche **Erreurs** : - `400 Bad Request` : Chemin invalide ou JSON malformé - `415 Unsupported Media Type` : Content-Type non supporté - `500 Internal Server Error` : Erreur d'écriture **Exemples curl** : ```bash # Créer avec JSON curl -X PUT http://localhost:8080/api/v1/notes/projet/test.md \ -H "Content-Type: application/json" \ -d '{ "body": "\n# Test\n\nCeci est un test.", "frontMatter": { "title": "Note de test", "tags": ["test"] } }' # Créer avec Markdown brut curl -X PUT http://localhost:8080/api/v1/notes/projet/simple.md \ -H "Content-Type: text/markdown" \ -d "# Simple note Contenu simple sans front matter." # Upload depuis un fichier curl -X PUT http://localhost:8080/api/v1/notes/projet/from-file.md \ -H "Content-Type: text/markdown" \ --data-binary @local-file.md ``` --- ### Supprimer une note Supprime définitivement une note. **Endpoint** : `DELETE /api/v1/notes/{path}` **Paramètres** : - `{path}` : Chemin relatif de la note (ex: `projet/old-note.md`) **Réponse** : `200 OK` ```json { "message": "Note deleted successfully", "path": "projet/old-note.md" } ``` **Erreurs** : - `404 Not Found` : Note inexistante - `500 Internal Server Error` : Erreur de suppression **Exemple curl** : ```bash curl -X DELETE http://localhost:8080/api/v1/notes/projet/old-note.md ``` --- ## Codes de statut HTTP | Code | Signification | Description | |------|---------------|-------------| | `200` | OK | Requête réussie | | `201` | Created | Note créée avec succès | | `400` | Bad Request | Requête invalide (chemin, JSON, etc.) | | `404` | Not Found | Note inexistante | | `405` | Method Not Allowed | Méthode HTTP non supportée | | `415` | Unsupported Media Type | Content-Type non supporté | | `500` | Internal Server Error | Erreur serveur | --- ## Exemples d'utilisation ### Synchronisation de notes **Télécharger toutes les notes** : ```bash #!/bin/bash # Télécharger toutes les notes localement mkdir -p notes-backup # Récupérer la liste curl -s http://localhost:8080/api/v1/notes | jq -r '.notes[].path' | while read path; do # Créer les dossiers parents mkdir -p "notes-backup/$(dirname "$path")" # Télécharger la note curl -s http://localhost:8080/api/v1/notes/"$path" \ -H "Accept: text/markdown" \ -o "notes-backup/$path" echo "✓ Downloaded: $path" done echo "Backup terminé!" ``` **Uploader un dossier de notes** : ```bash #!/bin/bash # Uploader toutes les notes .md d'un dossier find ./my-notes -name "*.md" | while read file; do # Calculer le chemin relatif relpath="${file#./my-notes/}" # Upload curl -X PUT http://localhost:8080/api/v1/notes/"$relpath" \ -H "Content-Type: text/markdown" \ --data-binary @"$file" echo "✓ Uploaded: $relpath" done echo "Upload terminé!" ``` ### Recherche et filtrage **Lister toutes les notes avec un tag spécifique** : ```bash curl -s http://localhost:8080/api/v1/notes | \ jq '.notes[] | select(.tags | contains(["projet"])) | .path' ``` **Compter les notes par dossier** : ```bash curl -s http://localhost:8080/api/v1/notes | \ jq -r '.notes[].path' | \ xargs -n1 dirname | \ sort | uniq -c ``` ### Création automatique de notes **Note quotidienne** : ```bash #!/bin/bash # Créer une note quotidienne TODAY=$(date +%Y-%m-%d) TITLE="Notes du $(date +%d/%m/%Y)" curl -X PUT http://localhost:8080/api/v1/notes/daily/${TODAY}.md \ -H "Content-Type: application/json" \ -d "{ \"body\": \"\\n# ${TITLE}\\n\\n## Tasks\\n- [ ] TODO\\n\\n## Notes\\n\", \"frontMatter\": { \"title\": \"${TITLE}\", \"tags\": [\"daily\"] } }" echo "Note quotidienne créée: daily/${TODAY}.md" ``` ### Intégration avec d'autres outils **Exporter en HTML avec Pandoc** : ```bash curl -s http://localhost:8080/api/v1/notes/projet/doc.md \ -H "Accept: text/markdown" | \ pandoc -f markdown -t html -o doc.html echo "Exporté en HTML: doc.html" ``` **Recherche full-text avec jq** : ```bash # Chercher "API" dans tous les titres curl -s http://localhost:8080/api/v1/notes | \ jq '.notes[] | select(.title | contains("API"))' ``` ### Script de maintenance **Vérifier les notes sans tags** : ```bash curl -s http://localhost:8080/api/v1/notes | \ jq -r '.notes[] | select(.tags | length == 0) | .path' ``` **Statistiques** : ```bash #!/bin/bash # Afficher des statistiques sur les notes STATS=$(curl -s http://localhost:8080/api/v1/notes) TOTAL=$(echo "$STATS" | jq '.total') TOTAL_SIZE=$(echo "$STATS" | jq '[.notes[].size] | add') AVG_SIZE=$(echo "$STATS" | jq '[.notes[].size] | add / length | floor') echo "📊 Statistiques des notes" echo "========================" echo "Total de notes: $TOTAL" echo "Taille totale: $(numfmt --to=iec-i --suffix=B $TOTAL_SIZE)" echo "Taille moyenne: $(numfmt --to=iec-i --suffix=B $AVG_SIZE)" echo "" echo "Top 5 tags:" echo "$STATS" | jq -r '.notes[].tags[]' | sort | uniq -c | sort -rn | head -5 ``` --- ## Bonnes pratiques ### Sécurité 1. **Ne pas exposer publiquement sans authentification** 2. **Utiliser HTTPS en production** 3. **Valider les chemins côté client** (éviter `../` malveillants) 4. **Limiter la taille des uploads** (si nécessaire, ajouter un middleware) ### Performance 1. **Pagination** : L'API liste ne pagine pas actuellement (toutes les notes en une requête). Pour beaucoup de notes (>1000), envisager d'ajouter `?limit=` et `?offset=` 2. **Cache** : Utiliser un proxy cache (Varnish, nginx) pour GET 3. **Compression** : Activer gzip sur le reverse proxy ### Workflow recommandé 1. **Backup régulier** : Script cron qui télécharge toutes les notes 2. **Versioning Git** : Synchroniser le dossier de notes avec Git 3. **CI/CD** : Valider le format Markdown avec des linters 4. **Monitoring** : Logger les accès API pour audit --- ## Support et contribution - **Issues** : Rapporter les bugs sur GitHub - **Documentation** : Ce fichier (`API.md`) - **Code source** : `internal/api/rest_handler.go` --- ## Changelog ### v1 (2025-11-10) - ✨ Première version de l'API REST - ✅ Endpoints: LIST, GET, PUT, DELETE - ✅ Content negotiation JSON/Markdown - ✅ Support sous-dossiers - ✅ Gestion automatique du front matter - ✅ Ré-indexation automatique --- **Note** : Cette API coexiste avec l'interface web HTML. Les deux peuvent être utilisées simultanément sans conflit.