{
  "openapi": "3.0.0",
  "info": {
    "title": "MA Utility — Public API",
    "version": "1.0.0",
    "description": "API publique REST de MA Utility. Authentification par cle API.\n\nGenerer une cle dans Settings -> API Keys, puis utiliser le header `X-API-Key` ou `Authorization: Bearer ma_live_<...>`.\n\nChaque cle est portee par un scope (read:conversations, write:leads, etc.) et un rate limit per minute.",
    "contact": {
      "name": "MA Utility Support",
      "url": "https://mautility.com",
      "email": "support@mautility.com"
    }
  },
  "servers": [
    {
      "url": "https://api.mautility.com",
      "description": "Production"
    },
    {
      "url": "http://localhost:3001",
      "description": "Local dev"
    }
  ],
  "tags": [
    { "name": "Conversations", "description": "Conversations multi-canal (WhatsApp, Live Chat, Telegram, etc.)" },
    { "name": "Leads", "description": "Leads (contacts/prospects)" },
    { "name": "Agents", "description": "Agents IA configurables" },
    { "name": "Analytics", "description": "Statistiques + funnel" }
  ],
  "security": [
    { "apiKey": [] },
    { "bearerAuth": [] }
  ],
  "paths": {
    "/api/v2/public/conversations": {
      "get": {
        "tags": ["Conversations"],
        "summary": "Liste les conversations",
        "parameters": [
          { "$ref": "#/components/parameters/Limit" },
          { "$ref": "#/components/parameters/Offset" },
          {
            "name": "status",
            "in": "query",
            "schema": { "type": "string", "enum": ["open", "snoozed", "resolved"] }
          },
          {
            "name": "pipelineId",
            "in": "query",
            "schema": { "type": "string", "format": "uuid" }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste paginee",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Envelope" },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": { "$ref": "#/components/schemas/Conversation" }
                        },
                        "meta": { "$ref": "#/components/schemas/PaginationMeta" }
                      }
                    }
                  ]
                },
                "example": {
                  "success": true,
                  "data": [
                    {
                      "id": "5f54f336-aaaa-bbbb-cccc-dddddddddddd",
                      "status": "open",
                      "lastMessageAt": "2026-05-21T10:30:00Z"
                    }
                  ],
                  "meta": { "total": 1, "limit": 25, "offset": 0 }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/api/v2/public/conversations/{id}": {
      "get": {
        "tags": ["Conversations"],
        "summary": "Detail d'une conversation",
        "parameters": [
          { "$ref": "#/components/parameters/IdPath" },
          {
            "name": "messagesLimit",
            "in": "query",
            "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }
          }
        ],
        "responses": {
          "200": {
            "description": "Conversation + messages",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Envelope" },
                    {
                      "type": "object",
                      "properties": { "data": { "$ref": "#/components/schemas/ConversationDetail" } }
                    }
                  ]
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/api/v2/public/conversations/{id}/messages": {
      "post": {
        "tags": ["Conversations"],
        "summary": "Envoyer un message dans une conversation",
        "parameters": [{ "$ref": "#/components/parameters/IdPath" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["content"],
                "properties": {
                  "content": { "type": "string", "maxLength": 4096 }
                }
              },
              "example": { "content": "Merci, je reviens vers vous tres vite." }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Message cree",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Envelope" },
                    {
                      "type": "object",
                      "properties": { "data": { "$ref": "#/components/schemas/Message" } }
                    }
                  ]
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/api/v2/public/leads": {
      "get": {
        "tags": ["Leads"],
        "summary": "Liste les leads",
        "parameters": [
          { "$ref": "#/components/parameters/Limit" },
          { "$ref": "#/components/parameters/Offset" },
          { "name": "status", "in": "query", "schema": { "type": "string" } },
          { "name": "source", "in": "query", "schema": { "type": "string" } },
          { "name": "pipelineId", "in": "query", "schema": { "type": "string", "format": "uuid" } },
          { "name": "search", "in": "query", "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "Liste paginee",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Envelope" },
                    {
                      "type": "object",
                      "properties": {
                        "data": { "type": "array", "items": { "$ref": "#/components/schemas/Lead" } },
                        "meta": { "$ref": "#/components/schemas/PaginationMeta" }
                      }
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Leads"],
        "summary": "Creer un lead",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/LeadCreate" },
              "example": {
                "phone": "+33612345678",
                "displayName": "Jane Doe",
                "email": "jane@example.com",
                "source": "inbound_webhook"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Lead cree",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Envelope" },
                    {
                      "type": "object",
                      "properties": { "data": { "$ref": "#/components/schemas/Lead" } }
                    }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "409": { "$ref": "#/components/responses/Conflict" }
        }
      }
    },
    "/api/v2/public/leads/{id}": {
      "get": {
        "tags": ["Leads"],
        "summary": "Detail d'un lead",
        "parameters": [{ "$ref": "#/components/parameters/IdPath" }],
        "responses": {
          "200": {
            "description": "Lead",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Envelope" },
                    {
                      "type": "object",
                      "properties": { "data": { "$ref": "#/components/schemas/Lead" } }
                    }
                  ]
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      },
      "patch": {
        "tags": ["Leads"],
        "summary": "Mettre a jour un lead",
        "parameters": [{ "$ref": "#/components/parameters/IdPath" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/LeadUpdate" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Lead mis a jour",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Envelope" },
                    {
                      "type": "object",
                      "properties": { "data": { "$ref": "#/components/schemas/Lead" } }
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/public/agents": {
      "get": {
        "tags": ["Agents"],
        "summary": "Liste des agents IA",
        "responses": {
          "200": {
            "description": "Liste",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Envelope" },
                    {
                      "type": "object",
                      "properties": {
                        "data": { "type": "array", "items": { "$ref": "#/components/schemas/Agent" } }
                      }
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/public/agents/{id}/invoke": {
      "post": {
        "tags": ["Agents"],
        "summary": "Invoque un agent en sandbox",
        "parameters": [{ "$ref": "#/components/parameters/IdPath" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["userMessage"],
                "properties": { "userMessage": { "type": "string", "minLength": 1, "maxLength": 4000 } }
              },
              "example": { "userMessage": "Bonjour, j'aimerais reserver pour 2 personnes ce soir." }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reponse generee",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Envelope" },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "text": { "type": "string" },
                            "tokensIn": { "type": "integer" },
                            "tokensOut": { "type": "integer" },
                            "latencyMs": { "type": "integer" }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/public/analytics/funnel": {
      "get": {
        "tags": ["Analytics"],
        "summary": "Funnel de conversion",
        "parameters": [
          { "name": "from", "in": "query", "schema": { "type": "string", "format": "date-time" } },
          { "name": "to", "in": "query", "schema": { "type": "string", "format": "date-time" } }
        ],
        "responses": {
          "200": {
            "description": "Funnel",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Envelope" },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "newLeads": { "type": "integer" },
                            "activeLeads": { "type": "integer" },
                            "qualified": { "type": "integer" },
                            "converted": { "type": "integer" },
                            "conversionRate": { "type": "number", "format": "float" },
                            "range": {
                              "type": "object",
                              "properties": {
                                "from": { "type": "string", "format": "date-time" },
                                "to": { "type": "string", "format": "date-time" }
                              }
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "API key au format `ma_live_<...>`. A creer dans Settings -> API Keys."
      },
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "ApiKey",
        "description": "Alternative au header X-API-Key : `Authorization: Bearer ma_live_<...>`."
      }
    },
    "parameters": {
      "Limit": {
        "name": "limit",
        "in": "query",
        "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 25 }
      },
      "Offset": {
        "name": "offset",
        "in": "query",
        "schema": { "type": "integer", "minimum": 0, "default": 0 }
      },
      "IdPath": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": { "type": "string", "format": "uuid" }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Cle d'API manquante ou invalide",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" },
            "examples": {
              "missing": { "value": { "success": false, "error": "API key required", "code": "API_KEY_REQUIRED" } },
              "invalid": { "value": { "success": false, "error": "API key invalide", "code": "API_KEY_INVALID" } }
            }
          }
        }
      },
      "Forbidden": {
        "description": "Scope manquant",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" },
            "example": { "success": false, "error": "Scope manquant : read:conversations", "code": "SCOPE_REQUIRED" }
          }
        }
      },
      "NotFound": {
        "description": "Ressource introuvable",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" }
          }
        }
      },
      "BadRequest": {
        "description": "Parametres invalides",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" }
          }
        }
      },
      "Conflict": {
        "description": "Conflit (deja existant)",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" }
          }
        }
      },
      "RateLimited": {
        "description": "Rate limit depasse",
        "headers": {
          "X-RateLimit-Limit": { "schema": { "type": "integer" } },
          "X-RateLimit-Remaining": { "schema": { "type": "integer" } },
          "Retry-After": { "schema": { "type": "integer" } }
        },
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" },
            "example": { "success": false, "error": "Rate limit depasse", "code": "RATE_LIMIT_EXCEEDED" }
          }
        }
      }
    },
    "schemas": {
      "Envelope": {
        "type": "object",
        "required": ["success"],
        "properties": {
          "success": { "type": "boolean" }
        }
      },
      "PaginationMeta": {
        "type": "object",
        "properties": {
          "total": { "type": "integer" },
          "limit": { "type": "integer" },
          "offset": { "type": "integer" }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "success": { "type": "boolean", "example": false },
          "error": { "type": "string" },
          "code": { "type": "string" }
        }
      },
      "Conversation": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "pipelineId": { "type": "string", "format": "uuid" },
          "leadId": { "type": "string", "format": "uuid", "nullable": true },
          "channel": { "type": "string" },
          "status": { "type": "string", "enum": ["open", "snoozed", "resolved"] },
          "priority": { "type": "string", "enum": ["low", "medium", "high", "urgent"] },
          "lastMessageAt": { "type": "string", "format": "date-time", "nullable": true },
          "createdAt": { "type": "string", "format": "date-time" }
        }
      },
      "ConversationDetail": {
        "allOf": [
          { "$ref": "#/components/schemas/Conversation" },
          {
            "type": "object",
            "properties": {
              "messages": { "type": "array", "items": { "$ref": "#/components/schemas/Message" } }
            }
          }
        ]
      },
      "Message": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "conversationId": { "type": "string", "format": "uuid" },
          "senderType": { "type": "string", "enum": ["lead", "ai", "human"] },
          "direction": { "type": "string", "enum": ["inbound", "outbound"] },
          "messageType": { "type": "string" },
          "content": { "type": "string", "nullable": true },
          "createdAt": { "type": "string", "format": "date-time" }
        }
      },
      "Lead": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "pipelineId": { "type": "string", "format": "uuid" },
          "phone": { "type": "string", "nullable": true },
          "displayName": { "type": "string", "nullable": true },
          "email": { "type": "string", "nullable": true },
          "source": { "type": "string" },
          "status": { "type": "string", "enum": ["new", "active", "qualified", "converted", "lost"] },
          "createdAt": { "type": "string", "format": "date-time" }
        }
      },
      "LeadCreate": {
        "type": "object",
        "required": ["phone"],
        "properties": {
          "phone": { "type": "string", "description": "Format E.164 ou normalisable" },
          "displayName": { "type": "string", "nullable": true },
          "email": { "type": "string", "nullable": true },
          "source": { "type": "string" },
          "pipelineId": { "type": "string", "format": "uuid", "description": "Pipeline cible. Defaut : premier pipeline du compte." },
          "notes": { "type": "string", "nullable": true }
        }
      },
      "LeadUpdate": {
        "type": "object",
        "properties": {
          "displayName": { "type": "string", "nullable": true },
          "email": { "type": "string", "nullable": true },
          "notes": { "type": "string", "nullable": true },
          "status": { "type": "string", "enum": ["new", "active", "qualified", "converted", "lost"] }
        }
      },
      "Agent": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "name": { "type": "string" },
          "description": { "type": "string", "nullable": true },
          "llmProvider": { "type": "string" },
          "llmModel": { "type": "string", "nullable": true },
          "updatedAt": { "type": "string", "format": "date-time" }
        }
      }
    }
  }
}
