TimeManager — API publique (résumé d'usage) ========================================= Ce document résume l'usage des endpoints exposés par l'app TimeManager (routes dans [appinfo/routes.php](https://github.com/te-online/timemanager/blob/main/appinfo/routes.php)). Les implémentations serveur se trouvent dans [lib/Controller/TApiController.php](https://github.com/te-online/timemanager/blob/main/lib/Controller/TApiController.php) et la logique de transformation/stockage dans [lib/Db/StorageHelper.php](https://github.com/te-online/timemanager/blob/main/lib/Db/StorageHelper.php). Authentification ----------------- - L'API est une API Nextcloud : il faut une session authentifiée ou utiliser l'authentification HTTP Basic (utilisateur + mot de passe d'application). Dans les scripts automatisés, préférez un `app password`. - Pour les requêtes JSON, envoyez `Content-Type: application/json`. Résumé des endpoints -------------------- - `GET /api/items` — lecture / recherche d'items (clients / projets / tâches / temps). Usage UI/interop (paramètres de filtrage dépendants de l'implémentation). Le contrôleur `TApiController` ne contient pas de méthode `get` explicite dans la version actuelle du dépôt ; ce endpoint peut être géré par un héritage du framework ou un code serveur externe. - `POST /api/items` — création d'un item (implémentation: création d'un client via `post($name, $note)`). Exemple minimal : envoyer `{"name":"Mon client","note":"…"}`. - `POST /api/updateObjects` — endpoint principal de synchronisation bidirectionnelle. Accepta un objet JSON contenant `lastCommit` et `data` (structure détaillée ci‑dessous). Retourne les objets modifiés depuis le commit fourni plus un nouveau `commit` si des changements ont été appliqués. - `POST /api/sync-web` — alias/variante utilisée par le client web (`updateObjectsFromWeb`) ; se comporte comme `updateObjects`. - `GET /api/hoursInPeriod` — statistique/aggrégation des heures sur une période. Paramètres détaillés ci‑dessous. Détail : `POST /api/updateObjects` --------------------------------- Attendu : un JSON avec ces champs racine : - `lastCommit` : string — le commit connu côté client (vide ou absent si première synchronisation). - `data` : objet contenant 4 entités : `clients`, `projects`, `tasks`, `times`. Chaque entité doit être un objet contenant trois tableaux : `created`, `updated`, `deleted`. Exemple minimal : ``` { "lastCommit": "", "data": { "clients": { "created": [ { "name": "Client A" } ], "updated": [], "deleted": [] }, "projects": { "created": [], "updated": [], "deleted": [] }, "tasks": { "created": [], "updated": [], "deleted": [] }, "times": { "created": [], "updated": [], "deleted": [] } } } ``` Champs usuels par entité (voir `StorageHelper::convertToEntityObject` pour la liste complète) - clients: `name`, `note`, `email`, `phone`, `city`, `postcode`, `street`, `web`, `uuid`, `commit`, `created`, `changed`. - projects: `name`, `client_uuid`, `note`, `color`, `uuid`, `commit`, `created`, `changed`. - tasks: `name`, `project_uuid`, `uuid`, `commit`, `created`, `changed`. - times: `start`, `end`, `task_uuid`, `note`, `uuid`, `commit`, `created`, `changed`. Comportement serveur (synthèse) - Le serveur vérifie que chaque entité a bien les trois sous-tableaux `created`, `updated`, `deleted` et renverra une erreur HTTP 406 si la structure est invalide. - Pour les objets `created`, le serveur complète `uuid`, `created`, `changed` si besoin et insère l'objet. Pour `updated`/`deleted`, le serveur utilise les champs `commit` / `desiredCommit` pour résoudre les conflits selon la stratégie configurée. - Le serveur renvoie un objet JSON contenant `data` (les objets modifiés après le commit fourni) et `commit` (nouveau commit si des changements ont été appliqués, sinon le dernier commit connu côté serveur). Exemple de réponse (squelette) : ``` { "data": { "clients": [ /* liste d'objets client après commit demandé */ ], "projects": [ /* ... */ ], "tasks": [ /* ... */ ], "times": [ /* ... */ ] }, "commit": "" } ``` Notes pratiques - Le champ `commit` est central pour la synchronisation incrémentale : envoyez la valeur `commit` renvoyée par le serveur comme `lastCommit` lors du prochain appel pour ne recevoir que les changements suivants. - Si vous ne souhaitez pousser aucun changement mais uniquement récupérer les nouveautés, envoyez `data` vide (ou des tableaux vides) et `lastCommit` égal au dernier commit connu du client : le serveur renverra les objets après ce commit. `/api/sync-web` ---------------- Equivalent pratique de `updateObjects`, prévu pour les appels depuis le front‑end web. Même payload et même réponse. `GET /api/hoursInPeriod` ------------------------ Signature (d'après `TApiController::getHoursInPeriodStats`): - `start` (required) — date de début (format attendu par l'app, typiquement `YYYY-MM-DD` ou une date ISO) - `end` (required) — date de fin - `group_by` (optional) — `none` | `day` | `week` | `month` | `year` (par défaut `none`) - `clients`, `projects`, `tasks` (optional) — listes CSV d'UUIDs pour filtrer (`client_uuid1,client_uuid2`) - `status` (optional) — filtre d'état des temps (ex: `active`/`deleted` selon implémentation) - `shared` (optional) — booléen pour inclure les entrées partagées - `userFilter` (optional) — CSV d'IDs utilisateurs pour limiter aux auteurs - `timezone` (optional) — timezone utilisée pour l'agrégation (ex: `UTC`) Exemple curl : ```bash curl -u "user:APP_PASSWORD" \ "https:///apps/timemanager/api/hoursInPeriod?start=2026-01-01&end=2026-01-31&group_by=day" ``` Réponse (squelette) : ``` { "total": 123.5, "grouped": { "2026-01-01": 8.0, "2026-01-02": 7.5 }, "js_date_format": "yyyy-MM-dd" } ``` `GET /api/items` et `POST /api/items` ------------------------------------ - `POST /api/items` crée un client si on lui fournit `name` et `note` (méthode `post($name,$note)` dans `TApiController`). Exemple : ```bash curl -u "user:APP_PASSWORD" -H "Content-Type: application/json" \ -d '{"name":"Nouveau client","note":"créé via API"}' \ -X POST "https:///apps/timemanager/api/items" ``` - `GET /api/items` permet de lister / rechercher des éléments exposés par l'API (usage UI). Les filtres exacts sont implémentés dans la méthode `get` du contrôleur; si vous avez un usage précis je peux extraire la signature exacte et ajouter des exemples d'appel. Exemple Python de synchronisation `updateObjects` --------------------------------------------- ```python import requests import json from requests.auth import HTTPBasicAuth url = "https:///apps/timemanager/api/updateObjects" username = "" password = "" payload = { "lastCommit": "", "data": { "clients": {"created": [{"name": "Client API", "note": "Créé via API"}], "updated": [], "deleted": []}, "projects": {"created": [], "updated": [], "deleted": []}, "tasks": {"created": [], "updated": [], "deleted": []}, "times": {"created": [], "updated": [], "deleted": []} } } resp = requests.post(url, json=payload, auth=HTTPBasicAuth(username, password)) print(resp.status_code) print(resp.text) ``` Références et exploration ------------------------- - Code source des routes : https://github.com/te-online/timemanager/blob/main/appinfo/routes.php - Contrôleur API : https://github.com/te-online/timemanager/blob/main/lib/Controller/TApiController.php - Conversion JSON → entités : https://github.com/te-online/timemanager/blob/main/lib/Db/StorageHelper.php Si vous voulez, je peux : - ajouter des exemples d'appels `curl` réels adaptés à votre instance Nextcloud (avec placeholders), - extraire la signature exacte de la méthode `get` pour `/api/items` et ajouter sa doc précise, - générer un petit script Python d'exemple qui synchronise un petit ensemble `clients/projects/tasks/times` contre votre instance.