Files
personotes/API.md
2025-11-12 17:16:13 +01:00

13 KiB

PersoNotes REST API Documentation

Version: v1 Base URL: http://localhost:8080/api/v1

Table des matières


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)

{
  "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)

{
  "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)

{
  "content": "---\ntitle: Ma note\ntags: [test]\n---\n\n# Contenu"
}

Option 2 : Body + FrontMatter séparés (recommandé pour création)

{
  "body": "\n# Mon contenu\n\nTexte ici...",
  "frontMatter": {
    "title": "Ma note",
    "tags": ["test", "exemple"]
  }
}

Erreur (ErrorResponse)

{
  "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

{
  "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 :

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

{
  "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

---
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 :

# 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 :

{
  "body": "\n# Ma nouvelle note\n\nContenu ici...",
  "frontMatter": {
    "title": "Ma nouvelle note",
    "tags": ["test", "exemple"]
  }
}

Ou avec content complet :

{
  "content": "---\ntitle: Ma note\ntags: [test]\n---\n\n# Contenu"
}

Body Markdown brut :

# Ma nouvelle note

Contenu ici...

Réponse : 201 Created (nouvelle note) ou 200 OK (mise à jour)

{
  "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 :

# 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

{
  "message": "Note deleted successfully",
  "path": "projet/old-note.md"
}

Erreurs :

  • 404 Not Found : Note inexistante
  • 500 Internal Server Error : Erreur de suppression

Exemple curl :

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 :

#!/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 :

#!/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 :

curl -s http://localhost:8080/api/v1/notes | \
  jq '.notes[] | select(.tags | contains(["projet"])) | .path'

Compter les notes par dossier :

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 :

#!/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 :

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 :

# 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 :

curl -s http://localhost:8080/api/v1/notes | \
  jq -r '.notes[] | select(.tags | length == 0) | .path'

Statistiques :

#!/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.