{
  "openapi": "3.1.0",
  "info": {
    "title": "Legal Fleet API",
    "version": "1.0.0",
    "description": "API REST du CRM juridique Legal Fleet. Gestion des clients, dossiers, echeances, factures, time-tracking, veille juridique et GED. Versioning: URL path (/api/v1/) et header X-API-Version. Deprecation policy: les endpoints deprecies recoivent un header HTTP Sunset 6 mois avant suppression.",
    "x-api-version": "1.0.0",
    "x-deprecation-policy": "Sunset header provided 6 months in advance",
    "contact": {
      "name": "Legal Fleet API Support",
      "url": "https://legal-fleet.vercel.app/contact",
      "email": "support@legal-fleet.fr"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://legal-fleet.vercel.app/privacy"
    }
  },
  "servers": [
    {
      "url": "https://legal-fleet.vercel.app/api/v1",
      "description": "Production v1"
    },
    {
      "url": "https://legal-fleet.vercel.app",
      "description": "Production Root"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Jeton JWT emis par Supabase Auth. Header requis: Authorization: Bearer <token>"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "example": "UNAUTHORIZED"
              },
              "message": {
                "type": "string",
                "example": "Token manquant ou invalide."
              },
              "docs": {
                "type": "string",
                "format": "uri",
                "example": "https://legal-fleet.vercel.app/developers#auth"
              }
            }
          }
        }
      },
      "HealthResponse": {
        "type": "object",
        "required": [
          "status",
          "version",
          "timestamp",
          "uptime_s"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok"
            ],
            "example": "ok"
          },
          "version": {
            "type": "string",
            "example": "1.0.0"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "uptime_s": {
            "type": "number",
            "example": 120
          }
        }
      },
      "Client": {
        "type": "object",
        "required": [
          "id",
          "first_name",
          "last_name",
          "status",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "first_name": {
            "type": "string",
            "example": "Jean"
          },
          "last_name": {
            "type": "string",
            "example": "Dupont"
          },
          "company": {
            "type": "string",
            "nullable": true,
            "example": "Acme SAS"
          },
          "email": {
            "type": "string",
            "format": "email",
            "nullable": true
          },
          "phone": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "actif",
              "inactif",
              "prospect"
            ],
            "example": "actif"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ClientInput": {
        "type": "object",
        "required": [
          "first_name",
          "last_name"
        ],
        "properties": {
          "first_name": {
            "type": "string",
            "example": "Jean"
          },
          "last_name": {
            "type": "string",
            "example": "Dupont"
          },
          "company": {
            "type": "string",
            "nullable": true,
            "example": "Acme SAS"
          },
          "email": {
            "type": "string",
            "format": "email",
            "nullable": true
          },
          "phone": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "actif",
              "inactif",
              "prospect"
            ],
            "default": "actif"
          }
        }
      },
      "Dossier": {
        "type": "object",
        "required": [
          "id",
          "titre",
          "statut",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "client_id": {
            "type": "string",
            "format": "uuid"
          },
          "titre": {
            "type": "string",
            "example": "Contentieux commercial"
          },
          "reference": {
            "type": "string",
            "nullable": true,
            "example": "DOS-2025-001"
          },
          "statut": {
            "type": "string",
            "enum": [
              "en_cours",
              "cloture",
              "archive"
            ],
            "example": "en_cours"
          },
          "matiere": {
            "type": "string",
            "nullable": true,
            "example": "Droit des affaires"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "DossierInput": {
        "type": "object",
        "required": [
          "client_id",
          "titre"
        ],
        "properties": {
          "client_id": {
            "type": "string",
            "format": "uuid"
          },
          "titre": {
            "type": "string",
            "example": "Contentieux commercial"
          },
          "reference": {
            "type": "string",
            "nullable": true,
            "example": "DOS-2025-001"
          },
          "statut": {
            "type": "string",
            "enum": [
              "en_cours",
              "cloture",
              "archive"
            ],
            "default": "en_cours"
          },
          "matiere": {
            "type": "string",
            "nullable": true,
            "example": "Droit des affaires"
          }
        }
      },
      "Echeance": {
        "type": "object",
        "required": [
          "id",
          "titre",
          "date_echeance",
          "statut"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "dossier_id": {
            "type": "string",
            "format": "uuid"
          },
          "titre": {
            "type": "string",
            "example": "Conclusions récapitulatives"
          },
          "date_echeance": {
            "type": "string",
            "format": "date",
            "example": "2025-09-15"
          },
          "statut": {
            "type": "string",
            "enum": [
              "a_venir",
              "respectee",
              "depassee"
            ],
            "example": "a_venir"
          }
        }
      },
      "Facture": {
        "type": "object",
        "required": [
          "id",
          "reference",
          "montant_ht",
          "montant_ttc",
          "statut"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "client_id": {
            "type": "string",
            "format": "uuid"
          },
          "reference": {
            "type": "string",
            "example": "FAC-2025-001"
          },
          "montant_ht": {
            "type": "number",
            "example": 1500
          },
          "montant_ttc": {
            "type": "number",
            "example": 1800
          },
          "statut": {
            "type": "string",
            "enum": [
              "brouillon",
              "emise",
              "payee",
              "annulee"
            ],
            "example": "emise"
          },
          "date_emission": {
            "type": "string",
            "format": "date"
          }
        }
      },
      "Task": {
        "type": "object",
        "required": [
          "id",
          "titre",
          "statut"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "dossier_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "titre": {
            "type": "string",
            "example": "Rediger acte introductif"
          },
          "statut": {
            "type": "string",
            "enum": [
              "a_faire",
              "en_cours",
              "termine"
            ],
            "example": "a_faire"
          },
          "priorite": {
            "type": "string",
            "enum": [
              "basse",
              "moyenne",
              "haute"
            ],
            "example": "haute"
          }
        }
      },
      "TimeEntry": {
        "type": "object",
        "required": [
          "id",
          "duration_minutes",
          "date"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "dossier_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "duration_minutes": {
            "type": "integer",
            "example": 45
          },
          "description": {
            "type": "string",
            "nullable": true,
            "example": "Rendez-vous client"
          },
          "date": {
            "type": "string",
            "format": "date"
          }
        }
      },
      "VeilleArticle": {
        "type": "object",
        "required": [
          "id",
          "titre",
          "resume",
          "source",
          "date_publication"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "titre": {
            "type": "string",
            "example": "Reforme de la procedure civile 2025"
          },
          "resume": {
            "type": "string",
            "example": "Analyse detaillee des nouvelles regles applicables."
          },
          "source": {
            "type": "string",
            "example": "Legifrance"
          },
          "matiere": {
            "type": "string",
            "example": "Procedure civile"
          },
          "date_publication": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "SearchResult": {
        "type": "object",
        "required": [
          "type",
          "id",
          "title"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "client",
              "dossier",
              "document",
              "note"
            ]
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "title": {
            "type": "string",
            "example": "Dossier Dupont"
          },
          "snippet": {
            "type": "string",
            "nullable": true
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Paramètres de requête invalides.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Token manquant ou invalide.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Accès refusé à cette ressource.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Ressource introuvable.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Trop de requêtes — seuil de rate-limit atteint.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "InternalError": {
        "description": "Erreur interne du serveur.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  },
  "paths": {
    "/api/health": {
      "get": {
        "operationId": "getHealth",
        "summary": "Verification de la disponibilite du service Legal Fleet",
        "description": "Endpoint public (non authentifie) retournant le statut operationnel de Legal Fleet, la version de l API et les metriques de base.",
        "tags": [
          "health"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Service operationnel.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/clients": {
      "get": {
        "operationId": "listClients",
        "summary": "Liste les clients du cabinet Legal Fleet",
        "description": "Retourne la liste paginee des clients appartenant au workspace authentifie.",
        "tags": [
          "clients"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "actif",
                "inactif",
                "prospect"
              ]
            },
            "description": "Filtrer par statut"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 20,
              "maximum": 100
            },
            "description": "Nombre maximal de clients"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Decalage de pagination"
          }
        ],
        "responses": {
          "200": {
            "description": "Liste paginee des clients.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Client"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createClient",
        "summary": "Cree un nouveau client dans Legal Fleet",
        "description": "Cree un client (personne physique ou morale) dans le workspace authentifie.",
        "tags": [
          "clients"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClientInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Client cree avec succes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Client"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/clients/{id}": {
      "get": {
        "operationId": "getClient",
        "summary": "Recupere un client par identifiant unique",
        "description": "Retourne les details complets d un client du workspace.",
        "tags": [
          "clients"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID du client"
          }
        ],
        "responses": {
          "200": {
            "description": "Details du client.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Client"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "updateClient",
        "summary": "Met a jour les informations d un client",
        "description": "Met a jour partiellement les champs d un client existant.",
        "tags": [
          "clients"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID du client"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClientInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Client mis a jour.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Client"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteClient",
        "summary": "Supprime un client du cabinet",
        "description": "Supprime definitivement un client et archive ses dossiers.",
        "tags": [
          "clients"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID du client"
          }
        ],
        "responses": {
          "204": {
            "description": "Client supprime avec succes."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/dossiers": {
      "get": {
        "operationId": "listDossiers",
        "summary": "Liste les dossiers juridiques du cabinet",
        "description": "Retourne la liste des dossiers juridiques du workspace, avec filtre par statut et client.",
        "tags": [
          "dossiers"
        ],
        "parameters": [
          {
            "name": "client_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filtrer par client"
          },
          {
            "name": "statut",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "en_cours",
                "cloture",
                "archive"
              ]
            },
            "description": "Filtrer par statut"
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des dossiers juridiques.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Dossier"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createDossier",
        "summary": "Cree un nouveau dossier juridique",
        "description": "Ouvre un nouveau dossier juridique associe a un client.",
        "tags": [
          "dossiers"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DossierInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Dossier cree avec succes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Dossier"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/dossiers/{id}": {
      "get": {
        "operationId": "getDossier",
        "summary": "Recupere un dossier juridique par ID",
        "description": "Retourne les details d un dossier avec ses echeances.",
        "tags": [
          "dossiers"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID du dossier"
          }
        ],
        "responses": {
          "200": {
            "description": "Details du dossier juridique.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Dossier"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/echeances": {
      "get": {
        "operationId": "listEcheances",
        "summary": "Liste les echeances et delais de procedure",
        "description": "Retourne les echeances procedurales du cabinet, filtrables par dossier ou date.",
        "tags": [
          "echeances"
        ],
        "parameters": [
          {
            "name": "dossier_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filtrer par dossier"
          },
          {
            "name": "date",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Filtrer par date d echeance"
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des echeances.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Echeance"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/factures": {
      "get": {
        "operationId": "listFactures",
        "summary": "Liste les factures et honoraires du cabinet",
        "description": "Retourne les factures emises du workspace Legal Fleet.",
        "tags": [
          "factures"
        ],
        "responses": {
          "200": {
            "description": "Liste des factures.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Facture"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/tasks": {
      "get": {
        "operationId": "listTasks",
        "summary": "Liste les taches de travail du cabinet",
        "description": "Retourne les taches et rappels assignes aux collaborateurs.",
        "tags": [
          "tasks"
        ],
        "responses": {
          "200": {
            "description": "Liste des taches.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Task"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/time-entries": {
      "get": {
        "operationId": "listTimeEntries",
        "summary": "Liste les entrees de time-tracking",
        "description": "Retourne les heures passees sur les dossiers pour la facturation.",
        "tags": [
          "time-entries"
        ],
        "responses": {
          "200": {
            "description": "Entrees de temps.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TimeEntry"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/veille": {
      "get": {
        "operationId": "listVeille",
        "summary": "Recupere les articles de veille juridique IA",
        "description": "Retourne les articles de veille juridique generes par IA pour le cabinet.",
        "tags": [
          "veille"
        ],
        "responses": {
          "200": {
            "description": "Articles de veille juridique.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/VeilleArticle"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/search": {
      "get": {
        "operationId": "searchGlobal",
        "summary": "Recherche globale full-text dans Legal Fleet",
        "description": "Effectue une recherche textuelle parmi les clients, dossiers, documents et notes.",
        "tags": [
          "search"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Terme de recherche"
          }
        ],
        "responses": {
          "200": {
            "description": "Resultats de recherche unifies.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SearchResult"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    }
  }
}