Documentation API Manifst

Bienvenue dans la documentation de l'API REST Manifst v1. Elle est incluse à partir du plan Portefeuille, et s'évalue sur l'abonnement du compte propriétaire de la clé. Les comptes souscrits avant la grille actuelle conservent leur accès.

Collection Postman
36 requêtes prêtes à l'emploi. Renseignez baseUrl et apiKey dans les variables de collection.
Télécharger

Introduction

URL de base :

https://manifst.net/api/v1/

Toutes les réponses sont au format JSON avec la structure suivante :

// Succès
{
  "data": { ... },        // objet ou tableau
  "meta": { "total": 42 } // présent sur les listes
}

// Erreur
{
  "error": {
    "code": "INSUFFICIENT_SCOPE",
    "message": "This API key does not have the required scope: 'projects:write'."
  }
}

Authentification

Toutes les requêtes doivent inclure votre clé API dans le header Authorization :

Authorization: Bearer mfst_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Ne jamais exposer votre clé API côté client (JS frontend, application mobile). Utilisez-la uniquement côté serveur.

Générer une clé

Rendez-vous dans Paramètres → Clés API de votre dashboard Manifst. Les clés sont affichées une seule fois à la création.

Exemple de requête

curl https://manifst.net/api/v1/projects \
  -H "Authorization: Bearer mfst_live_xxxxx"

Rate limiting

FenêtreLimite
Par heure1 000 requêtes
Par mois10 000 requêtes

Chaque réponse inclut ces headers :

X-RateLimit-Limit-Hour: 1000
X-RateLimit-Remaining-Hour: 847
X-RateLimit-Limit-Month: 10000
X-RateLimit-Remaining-Month: 9231
X-RateLimit-Reset-Hour: 1711234567

En cas de dépassement, l'API retourne HTTP 429 avec le header Retry-After (secondes avant le prochain reset).

Pagination & rafraîchissement incrémental

Les listes volumineuses — /tickets et /time-entries — acceptent une pagination optionnelle et un filtre incrémental. Sans ces paramètres, la réponse reste identique aux versions précédentes (rétro-compatible).

ParamètreDescription
pageNuméro de page (défaut 1). Active la pagination.
per_pageTaille de page (défaut 100, max 500). Active la pagination.
updated_sinceNe renvoie que les éléments modifiés depuis cette date (YYYY-MM-DD ou datetime). Idéal pour un refresh incrémental Power BI.

Le bloc meta renvoie toujours le total réel avant pagination :

GET /api/v1/tickets?project=abc-123&page=2&per_page=50&updated_since=2026-07-01

{
  "data": [ ... ],
  "meta": { "total": 320, "count": 50, "page": 2, "per_page": 50 }
}

Codes d'erreur

CodeHTTPDescription
MISSING_API_KEY401Header Authorization absent
INVALID_API_KEY401Clé introuvable
REVOKED_API_KEY401Clé révoquée
EXPIRED_API_KEY401Clé expirée
PLAN_REQUIRED403Plan Portefeuille requis
ACCOUNT_INACTIVE403Compte inactif
IP_NOT_ALLOWED403IP non autorisée (whitelist)
INSUFFICIENT_SCOPE403Scope manquant sur la clé
RATE_LIMIT_EXCEEDED429Quota dépassé
NOT_FOUND404Ressource introuvable
FORBIDDEN403Accès interdit à cette ressource
VALIDATION_ERROR422Paramètre manquant ou invalide
METHOD_NOT_ALLOWED405Méthode HTTP non supportée

Scopes

Chaque clé API dispose d'un ensemble de scopes qui définissent ses permissions. Les scopes disponibles :

ScopeDescription
projects:readLire les projets et leurs membres
projects:writeCréer, modifier, supprimer des projets
super-epics:readLire les super-épics
super-epics:writeCréer, modifier, supprimer les super-épics
epics:readLire les épics
epics:writeCréer, modifier, supprimer les épics
sprints:readLire les sprints
sprints:writeCréer et modifier les sprints
tickets:readLire les tickets
tickets:writeCréer, modifier, supprimer les tickets
comments:readLire les commentaires d'un ticket
comments:writeCréer, modifier, supprimer des commentaires
team:readLire les membres d'un projet
time:readLire les entrées de temps
time:writeEnregistrer des entrées de temps
statuses:readLire les statuts d'un projet
finance:readLire les indicateurs finance / EVM (projet & portefeuille)
roadmap:readLire les dépendances et jalons de roadmap

Projets

GET /api/v1/projects Lister les projets

Scope requis : projects:read

curl /api/v1/projects -H "Authorization: Bearer mfst_live_xxx"

// Réponse 200
{
  "data": [
    {
      "uuid": "abc-123",
      "name": "Mon projet",
      "description": "Description",
      "color": "#6366f1",
      "default_dod": ["Code review faite", "Tests passants"],
      "contingency_pct": 10.0,
      "budget": 350000.00,
      "user_role": "owner",
      "member_count": 5,
      "created_at": "2026-01-15 10:00:00",
      "updated_at": "2026-03-01 14:22:00"
    }
  ],
  "meta": { "total": 1 }
}
GET /api/v1/projects/{uuid} Détail d'un projet

Scope requis : projects:read

curl /api/v1/projects/abc-123 -H "Authorization: Bearer mfst_live_xxx"
GET /api/v1/projects/{uuid}/members Membres d'un projet

Scope requis : team:read

POST /api/v1/projects Créer un projet

Scope requis : projects:write

La création initialise automatiquement les 6 statuts par défaut (Backlog, À faire, En cours, En revue, Terminé, Bloqué) et les 2 types de tickets par défaut (Story, Bug).

Body

{
  "name": "Mon projet",                     // requis, 1–80 caractères
  "description": "...",                     // optionnel
  "color": "#6366f1",                       // optionnel, hex #rrggbb
  "default_dod": ["Tests OK", "Code review"], // optionnel — Definition of Done (tableau)
  "contingency_pct": 10.00,                 // optionnel — aléas finance, 0–100 % (défaut: 10)
  "budget": 350000.00                       // optionnel — BAC / budget à terminaison (≥ 0, null pour effacer)
}

Réponse 201

{
  "data": {
    "uuid": "...",
    "name": "Mon projet",
    "description": null,
    "color": "#6366f1",
    "default_dod": null,
    "contingency_pct": 10.0,
    "budget": 350000.00,
    "user_role": "owner",
    "created_at": "2026-03-24 20:00:00",
    "updated_at": "2026-03-24 20:00:00"
  }
}
PUT /api/v1/projects/{uuid} Modifier un projet

Scope requis : projects:write — owner uniquement

Body

{
  "name": "Nouveau nom",                  // optionnel
  "description": "...",                   // optionnel
  "color": "#f59e0b",                     // optionnel
  "default_dod": ["item 1", "item 2"],     // optionnel — null ou [] pour vider
  "contingency_pct": 15.00,                // optionnel — 0–100 %
  "budget": 420000.00                      // optionnel — BAC (≥ 0, null pour effacer)
}

Réponse 200

{
  "data": {
    "uuid": "...",
    "name": "Nouveau nom",
    "description": null,
    "color": "#f59e0b",
    "default_dod": ["item 1", "item 2"],
    "contingency_pct": 15.0,
    "budget": 420000.00,
    "user_role": "owner",
    "created_at": "2026-03-24 20:00:00",
    "updated_at": "2026-03-24 20:00:00"
  }
}
DELETE /api/v1/projects/{uuid} Supprimer un projet

Scope requis : projects:write — owner uniquement

// Réponse 200
{ "data": { "deleted": true } }

Super-épics

GET /api/v1/super-epics?project={uuid} Lister les super-épics

Scope requis : super-epics:read

GET /api/v1/super-epics/{uuid} Détail

Scope requis : super-epics:read

POST /api/v1/super-epics Créer

Scope requis : super-epics:write

Body

{
  "project_uuid": "abc-123",
  "title": "Titre",
  "description": "...",  // optionnel
  "status": "backlog",   // optionnel — backlog | in_progress | done (défaut: backlog)
  "tags": ["tag-uuid-1"] // optionnel — array d'UUID de tags
}

Réponse 201

{
  "data": {
    "uuid": "...",
    "project_id": 1,
    "title": "Titre",
    "description": null,
    "status": "backlog",
    "created_at": "2026-03-24 20:00:00",
    "updated_at": "2026-03-24 20:00:00",
    "tags": [{ "uuid": "tag-uuid", "name": "bug" }]
  }
}
PUT /api/v1/super-epics/{uuid} Modifier

Scope requis : super-epics:write

Body

{
  "title": "Nouveau titre",  // optionnel
  "description": "...",      // optionnel
  "status": "in_progress",   // optionnel — backlog | in_progress | done
  "tags": ["tag-uuid-1"]     // optionnel — remplace l'ensemble des tags
}

Réponse 200

{
  "data": {
    "uuid": "...",
    "project_id": 1,
    "title": "Nouveau titre",
    "description": null,
    "status": "in_progress",
    "created_at": "2026-03-24 20:00:00",
    "updated_at": "2026-03-24 20:00:00",
    "tags": [{ "uuid": "tag-uuid", "name": "bug" }]
  }
}
DELETE /api/v1/super-epics/{uuid} Supprimer

Scope requis : super-epics:write — les épics liés sont détachés, pas supprimés.

Épics

GET /api/v1/epics?project={uuid} Lister les épics

Scope requis : epics:read

GET /api/v1/epics/{uuid} Détail

Scope requis : epics:read

POST /api/v1/epics Créer

Scope requis : epics:write

Body

{
  "project_uuid": "abc-123",
  "title": "Titre",
  "description": "...",            // optionnel
  "super_epic_uuid": "se-uuid",    // optionnel
  "status": "backlog",             // optionnel — backlog | todo | in_progress | in_review | done | blocked (défaut: backlog)
  "tags": ["tag-uuid-1"]           // optionnel — array d'UUID de tags
}

Réponse 201

{
  "data": {
    "uuid": "...",
    "project_id": 1,
    "super_epic_id": null,
    "super_epic_uuid": null,
    "title": "Titre",
    "description": null,
    "status": "backlog",
    "created_at": "2026-03-24 20:00:00",
    "updated_at": "2026-03-24 20:00:00",
    "tags": [{ "uuid": "tag-uuid", "name": "bug" }]
  }
}
PUT /api/v1/epics/{uuid} Modifier

Scope requis : epics:write

Body

{
  "title": "...",           // optionnel
  "description": "...",     // optionnel
  "super_epic_uuid": null,  // optionnel — uuid ou null pour détacher
  "status": "done",         // optionnel — backlog | todo | in_progress | in_review | done | blocked
  "tags": ["tag-uuid-1"]    // optionnel — remplace l'ensemble des tags
}

Réponse 200

{
  "data": {
    "uuid": "...",
    "project_id": 1,
    "super_epic_id": null,
    "super_epic_uuid": null,
    "title": "...",
    "description": null,
    "status": "done",
    "created_at": "2026-03-24 20:00:00",
    "updated_at": "2026-03-24 20:00:00",
    "tags": [{ "uuid": "tag-uuid", "name": "bug" }]
  }
}
DELETE /api/v1/epics/{uuid} Supprimer

Scope requis : epics:write — les tickets liés sont détachées.

Sprints

GET /api/v1/sprints?project={uuid} Lister les sprints

Scope requis : sprints:read

GET /api/v1/sprints/{uuid} Détail

Scope requis : sprints:read

POST /api/v1/sprints Créer

Scope requis : sprints:write

Body

{
  "project_uuid": "abc-123",
  "title": "Sprint 1",
  "goal": "...",               // optionnel
  "status": "planning",        // optionnel — planning | active | completed (défaut: planning)
  "start_date": "2026-04-01",  // optionnel
  "end_date": "2026-04-14",    // optionnel
  "dod": ["item 1", "item 2"]   // optionnel — Definition of Done du sprint (tableau)
}

Réponse 201

{
  "data": {
    "uuid": "...",
    "project_id": 1,
    "title": "Sprint 1",
    "goal": null,
    "status": "planning",
    "start_date": "2026-04-01",
    "end_date": "2026-04-14",
    "dod": null,
    "created_at": "2026-03-24 20:00:00"
  }
}
PUT /api/v1/sprints/{uuid} Modifier

Scope requis : sprints:write

Body

{
  "title": "Sprint 1",         // optionnel
  "status": "active",          // optionnel — planning | active | completed
  "goal": "...",               // optionnel
  "start_date": "2026-04-01",  // optionnel
  "end_date": "2026-04-14",    // optionnel
  "dod": ["item 1"]            // optionnel — null ou [] pour vider
}

Réponse 200

{
  "data": {
    "uuid": "...",
    "project_id": 1,
    "title": "Sprint 1",
    "goal": null,
    "status": "active",
    "start_date": "2026-04-01",
    "end_date": "2026-04-14",
    "dod": ["item 1"],
    "created_at": "2026-03-24 20:00:00"
  }
}

Tickets

GET /api/v1/tickets?project={uuid} Lister les stories

Scope requis : tickets:read

Filtres optionnels : ?sprint={uuid} et ?epic={uuid}

GET /api/v1/tickets/{uuid} Détail (avec AC, dépendances et sous-tâches)

Scope requis : tickets:read

{
  "data": {
    "uuid": "...", "title": "...", "description": "...",
    "priority": "haute", "status": "todo", "story_points": 5,
    "epic_id": 1, "sprint_id": 2, "assignee": "Alice Martin",
    "acceptance_criteria": ["Critère 1", "Critère 2"],
    "dependencies": [{ "uuid": "...", "title": "Autre story" }],
    "tags": [{ "uuid": "tag-uuid", "name": "bug" }],
    "subtasks": [
      { "uuid": "...", "title": "Tâche technique", "status": "todo",
        "sort_order": 1, "assignee_id": 3, "assignee_name": "Alice Martin",
        "created_at": "2026-03-25 10:00:00", "updated_at": "2026-03-25 10:00:00" }
    ],
    "subtasks_total": 1,
    "subtasks_done": 0
  }
}
POST /api/v1/tickets Créer

Scope requis : tickets:write

Body

{
  "project_uuid": "abc-123",
  "title": "En tant qu'utilisateur…",
  "description": "...",
  "priority": "haute",         // critique | haute | normale | faible
  "status": "backlog",         // backlog | todo | in_progress | in_review | done | blocked
  "story_points": 5,           // optionnel
  "epic_uuid": "epic-uuid",    // optionnel
  "sprint_uuid": "sprint-uuid",// optionnel
  "assignee_id": 3,            // optionnel
  "acceptance_criteria": ["Critère 1"], // optionnel
  "dependencies": ["us-uuid-1"],        // optionnel
  "tags": ["tag-uuid-1"]                // optionnel — array d'UUID de tags
}

Réponse 201

{
  "data": {
    "uuid": "...",
    "project_id": 1,
    "epic_id": null,
    "sprint_id": null,
    "assignee_id": null,
    "assignee": null,
    "title": "En tant qu'utilisateur…",
    "description": null,
    "priority": "haute",
    "status": "backlog",
    "story_points": 5,
    "created_at": "2026-03-24 20:00:00",
    "updated_at": "2026-03-24 20:00:00",
    "acceptance_criteria": ["Critère 1"],
    "dependencies": [],
    "tags": [{ "uuid": "tag-uuid", "name": "bug" }]
  }
}
PUT /api/v1/tickets/{uuid} Modifier

Scope requis : tickets:write

Body

{
  "title": "...",               // optionnel
  "description": "...",         // optionnel
  "priority": "haute",          // optionnel — critique | haute | normale | faible
  "status": "in_progress",      // optionnel — backlog | todo | in_progress | in_review | done | blocked
  "story_points": 8,            // optionnel
  "epic_uuid": "epic-uuid",     // optionnel — uuid ou null pour détacher
  "sprint_uuid": "sprint-uuid", // optionnel — uuid ou null pour détacher
  "assignee_id": 3,             // optionnel — id ou null
  "acceptance_criteria": ["Critère 1"], // optionnel — remplace les critères existants
  "dependencies": ["us-uuid-1"],        // optionnel — remplace les dépendances existantes
  "tags": ["tag-uuid-1"]                // optionnel — remplace l'ensemble des tags
}

Réponse 200

{
  "data": {
    "uuid": "...",
    "project_id": 1,
    "epic_id": null,
    "sprint_id": null,
    "assignee_id": null,
    "assignee": null,
    "title": "...",
    "description": null,
    "priority": "haute",
    "status": "in_progress",
    "story_points": 8,
    "created_at": "2026-03-24 20:00:00",
    "updated_at": "2026-03-24 20:00:00",
    "acceptance_criteria": ["Critère 1"],
    "dependencies": [],
    "tags": [{ "uuid": "tag-uuid", "name": "bug" }]
  }
}
DELETE /api/v1/tickets/{uuid} Supprimer

Scope requis : tickets:write

Sous-tâches

Les sous-tâches ont des statuts fixes (todo, in_progress, done), indépendants des statuts personnalisés du projet. Elles représentent une liste de contrôle technique attaché à un ticket.

GET /api/v1/subtasks?ticket_uuid={uuid} Lister les sous-tâches d'un ticket

Scope requis : tickets:read

{
  "data": [
    {
      "uuid": "...",
      "title": "Tâche technique",
      "status": "todo",           // todo | in_progress | done
      "sort_order": 1,
      "assignee_id": 3,
      "assignee_name": "Alice Martin",
      "created_at": "2026-03-25 10:00:00",
      "updated_at": "2026-03-25 10:00:00"
    }
  ],
  "meta": { "total": 1 }
}
POST /api/v1/subtasks Créer une sous-tâche

Scope requis : tickets:write

Body

{
  "ticket_uuid": "us-uuid",        // requis
  "title": "Tâche technique",  // requis
  "status": "todo",            // optionnel — todo | in_progress | done (défaut: todo)
  "assignee_id": 3             // optionnel
}

Réponse 201

{
  "data": {
    "uuid": "...", "title": "Tâche technique", "status": "todo",
    "sort_order": 1, "assignee_id": null, "assignee_name": null,
    "created_at": "...", "updated_at": "..."
  }
}
PUT /api/v1/subtasks/{uuid} Modifier

Scope requis : tickets:write

Body

{
  "title": "...",          // optionnel
  "status": "in_progress", // optionnel — todo | in_progress | done
  "assignee_id": 3,        // optionnel — id ou null pour désassigner
  "sort_order": 2          // optionnel
}

Réponse 200

{
  "data": {
    "uuid": "...", "title": "...", "status": "in_progress",
    "sort_order": 2, "assignee_id": 3, "assignee_name": "Alice Martin",
    "created_at": "...", "updated_at": "..."
  }
}
DELETE /api/v1/subtasks/{uuid} Supprimer

Scope requis : tickets:write

Commentaires

Les commentaires sont attachés à un ticket. Seul l'auteur (ou un admin) peut modifier ou supprimer ses propres commentaires. Le contenu est du HTML sanitisé (scripts et handlers JS retirés).

GET /api/v1/comments?ticket_uuid={uuid} Lister les commentaires d'un ticket

Scope requis : comments:read

ParamètreTypeDescription
usstringUUID du ticket — requis

Réponse 200

{
  "data": [
    {
      "uuid": "...",
      "author_id": 3,
      "author_name": "Alice Martin",
      "author_initials": "AM",
      "content": "<p>Texte du commentaire</p>",
      "mentions": [4, 7],
      "ticket_uuid": "...",
      "created_at": "2026-04-02 10:00:00",
      "updated_at": "2026-04-02 10:00:00"
    }
  ],
  "meta": { "total": 1 }
}
GET /api/v1/comments/{uuid} Détail d'un commentaire

Scope requis : comments:read

POST /api/v1/comments Créer un commentaire

Scope requis : comments:write

Body

{
  "ticket_uuid":  "...",                     // requis — UUID du ticket
  "content":  "<p>Mon commentaire</p>",  // requis — HTML sanitisé
  "mentions": [4, 7]                     // optionnel — IDs utilisateurs mentionnés
}

Réponse 201

{
  "data": {
    "uuid": "...",
    "author_id": 3,
    "author_name": "Alice Martin",
    "author_initials": "AM",
    "content": "<p>Mon commentaire</p>",
    "mentions": [4],
    "ticket_uuid": "...",
    "created_at": "2026-04-02 10:00:00",
    "updated_at": "2026-04-02 10:00:00"
  }
}
PUT /api/v1/comments/{uuid} Modifier un commentaire

Scope requis : comments:write — auteur ou admin uniquement.

Body

{
  "content":  "<p>Contenu modifié</p>",  // optionnel
  "mentions": [4, 7]                       // optionnel — remplace la liste complète
}
DELETE /api/v1/comments/{uuid} Supprimer un commentaire

Scope requis : comments:write — auteur ou admin uniquement.

{ "data": { "deleted": true } }

Équipe

GET /api/v1/team?project={uuid} Membres du projet

Scope requis : team:read

{
  "data": [
    {
      "uuid": "...", "firstname": "Alice", "lastname": "Martin",
      "email": "alice@example.com", "scrum_role": "dev",
      "project_role": "member", "status": "active",
      "tjm": 550.00, "service": "Delivery"
    }
  ],
  "meta": { "total": 4 }
}

tjm = taux journalier moyen (coût/jour) du membre sur ce projet, base des indicateurs finance ; null si non renseigné.

Entrées de temps

GET /api/v1/time-entries?project={uuid} Lister les temps

Scope requis : time:read

Filtre optionnel : ?story={uuid} pour une story spécifique.

POST /api/v1/time-entries Enregistrer du temps

Scope requis : time:write

Body

{
  "ticket_uuid": "story-uuid",      // requis
  "duration_minutes": 90,       // requis
  "logged_at": "2026-03-24",    // requis, format YYYY-MM-DD
  "comment": "Revue de code"    // optionnel
}

Réponse 201

{
  "data": {
    "uuid": "...",
    "ticket_id": 12,
    "user_id": 3,
    "user_name": "Alice Martin",
    "ticket_uuid": "...",
    "ticket_title": "En tant qu'utilisateur…",
    "duration_minutes": 90,
    "comment": "Revue de code",
    "logged_at": "2026-03-24 00:00:00",
    "created_at": "2026-03-24 20:00:00"
  }
}

Statuts

GET /api/v1/statuses?project={uuid} Lister les statuts d'un projet

Scope requis : statuses:read

Retourne tous les statuts du projet (par défaut et personnalisés), triés par sort_order.

Réponse 200

[
  {
    "key":        "backlog",
    "label":      "Backlog",
    "color":      "#64748b",
    "bg_color":   "#f1f5f9",
    "sort_order": 1,
    "is_done":    false,
    "is_default": true
  },
  {
    "key":        "in_validation",
    "label":      "En validation",
    "color":      "#7c3aed",
    "bg_color":   "#f5f3ff",
    "sort_order": 7,
    "is_done":    false,
    "is_default": false
  }
]

Dépendances

Liens finish-to-start entre items de roadmap (épic ou super-épic). Chaque nœud est exposé par son UUID (joignable avec /epics et /super-epics) pour reconstruire le graphe et, côté consommateur, en dériver le chemin critique.

GET /api/v1/dependencies?project={uuid} Lister les dépendances

Scope requis : roadmap:read

{
  "data": [
    {
      "uuid": "dep-uuid",
      "type": "FS",               // finish-to-start
      "pred_type": "epic",        // epic | super_epic
      "pred_uuid": "epic-uuid-1",
      "succ_type": "epic",
      "succ_uuid": "epic-uuid-2"
    }
  ],
  "meta": { "total": 1 }
}

Jalons

GET /api/v1/milestones?project={uuid} Lister les jalons datés

Scope requis : roadmap:read

{
  "data": [
    { "uuid": "...", "name": "Go-live", "date": "2026-09-30", "color": "#e11d48" }
  ],
  "meta": { "total": 1 }
}

Finance / EVM

Indicateurs de gestion par la valeur acquise (Earned Value Management) d'un projet, calculés côté serveur à partir des story points, des temps enregistrés (× TJM) et du BAC déclaré (projects.budget).

Les indicateurs dépendant du budget (bac, pv, ev, cpi, cv, sv, eac, etc, vac, tcpi) valent null tant qu'aucun BAC n'est déclaré sur le projet. Les métriques d'avancement et de coût (ac, engaged_charge, spi, progress_pct, planned_pct) restent calculées.
GET /api/v1/finance?project={uuid} Indicateurs EVM du projet

Scope requis : finance:read

{
  "data": {
    "project_uuid": "abc-123",
    "bac": 350000.00,          // budget à terminaison (déclaré)
    "base_budget": 315000.00,  // BAC − réserve d'aléa
    "reserve": 35000.00,       // réserve d'aléa (incluse dans le BAC)
    "contingency_pct": 10.00,
    "pv": 326341.95,           // valeur planifiée = % SP planifié à date × BAC
    "ev": 257455.27,           // valeur acquise   = % SP réalisé × BAC
    "ac": 186573.75,           // coût actuel      = Σ (temps ÷ 480) × TJM
    "engaged_charge": 137253.75, // coût réel des épics non terminées
    "cpi": 1.38,               // EV ÷ AC   (> 1 = sous le budget)
    "spi": 0.79,               // % réalisé ÷ % planifié (> 1 = en avance)
    "tcpi": 0.57,              // (BAC − EV) ÷ (BAC − AC)
    "eac": 253639.45,          // coût final estimé = BAC ÷ CPI
    "etc": 67065.70,           // reste à terminaison = EAC − AC
    "vac": 96360.55,           // écart à terminaison = BAC − EAC
    "cv": 70881.52,            // écart de coût  = EV − AC
    "sv": -68886.68,           // écart de délai = (% réalisé − % planifié) × BAC
    "total_sp": 503,
    "done_sp": 370,
    "planned_sp": 469.10,
    "progress_pct": 73.56,     // % SP réalisés
    "planned_pct": 93.24       // % SP planifiés à date
  }
}

Portefeuille

Consolidation EVM sur tous les projets accessibles au porteur de la clé — une seule requête là où il fallait boucler projet par projet. Les indices consolidés sont calculés sur la somme des valeurs (EV, PV, AC), pas sur une moyenne des ratios.

GET /api/v1/portfolio/finance Roll-up EVM multi-projets

Scope requis : finance:read

Filtre optionnel : ?projects=uuid1,uuid2 pour cibler une équipe / un programme.

{
  "data": {
    "totals": {
      "projects": 12, "with_bac": 4, "without_bac": 8,
      "bac": 1250000.00, "pv": 910000.00, "ev": 742000.00, "ac": 690000.00,
      "engaged_charge": 305000.00,
      "cpi": 1.08, "spi": 0.82,
      "eac": 1157407.41, "vac": 92592.59,
      "cv": 52000.00, "sv": -168000.00,
      "ac_all": 812000.00,       // AC sur TOUS les projets (BAC ou non)
      "engaged_all": 410000.00   // charge engagée sur tous les projets
    },
    "projects": [
      { "project_uuid": "abc-123", "project_name": "CMA-CGM", "bac": 350000.00, "ev": 257455.27, "ac": 186573.75, "cpi": 1.38, "spi": 0.79, "vac": 96360.55, "engaged_charge": 137253.75, "...": "..." }
    ]
  },
  "meta": { "total": 12 }
}

Documentation Manifst API v1 · Retour au site