{
  "openapi": "3.1.0",
  "info": {
    "title": "LearnFloo API",
    "version": "1",
    "description": "External API of LearnFloo (community, courses, live webinars). 190 operations generated from the MCP catalogue; the same names are the MCP tools of https://api.learnfloo.com/mcp. Reference: https://api.learnfloo.com/docs",
    "contact": {
      "name": "LearnFloo",
      "url": "https://www.learnfloo.com"
    }
  },
  "externalDocs": {
    "description": "API reference",
    "url": "https://api.learnfloo.com/docs"
  },
  "servers": [
    {
      "url": "https://api.learnfloo.com/api/v1"
    }
  ],
  "tags": [
    {
      "name": "Espace"
    },
    {
      "name": "Membres et gamification"
    },
    {
      "name": "Lives"
    },
    {
      "name": "Scènes et régie"
    },
    {
      "name": "Sondages et quiz"
    },
    {
      "name": "Support"
    },
    {
      "name": "Groupes"
    },
    {
      "name": "Cours"
    },
    {
      "name": "Fil de la communauté"
    },
    {
      "name": "Calendrier"
    },
    {
      "name": "Vidéos du studio"
    },
    {
      "name": "Médiathèque"
    },
    {
      "name": "Webhooks"
    },
    {
      "name": "E-mails"
    },
    {
      "name": "Guide LearnFloo"
    }
  ],
  "paths": {
    "/space": {
      "get": {
        "operationId": "get_space",
        "summary": "L'espace de la clé",
        "description": "The space behind the API key: name, slug, visibility, price, member and course counts, group vocabulary, URL. Call it first to know where you are.",
        "tags": [
          "Espace"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "update_space",
        "summary": "Modifier la présentation de l'espace",
        "description": "Changes the presentation and brand of the space: name, description, welcome message, directory category, owner activity, logo and cover (https URLs, e.g. stored with POST /attachments), colors (hex), fonts, membership on request (joinApproval, joinQuestions) and the owner's ad trackers on the public pages (metaPixelId, ga4Id, loaded after the visitor's consent). Send only the fields to change; null clears one. Visibility and price stay in the app (they change the billing).",
        "tags": [
          "Espace"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name, 80 chars max"
                  },
                  "description": {
                    "description": "Short description shown on the space card and about page, 500 chars max",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Short description shown on the space card and about page, 500 chars max"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "welcomeMessage": {
                    "description": "Welcome message shown to new members, 2000 chars max",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Welcome message shown to new members, 2000 chars max"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "category": {
                    "type": "string",
                    "description": "Directory category",
                    "enum": [
                      "business",
                      "money",
                      "tech",
                      "creative",
                      "education",
                      "health",
                      "sport",
                      "lifestyle",
                      "other"
                    ]
                  },
                  "activity": {
                    "type": "string",
                    "description": "Owner's activity (coach or trainer, school, content creator, software company, company / HR, agency, other)",
                    "enum": [
                      "coach",
                      "school",
                      "creator",
                      "software",
                      "hr",
                      "agency",
                      "other"
                    ]
                  },
                  "metaPixelId": {
                    "description": "Meta pixel ID (digits), null clears",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Meta pixel ID (digits), null clears"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "ga4Id": {
                    "description": "Google Analytics 4 measurement ID (G-XXXXXXX), null clears",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Google Analytics 4 measurement ID (G-XXXXXXX), null clears"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "logo": {
                    "description": "Logo, https image URL",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Logo, https image URL"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "coverImage": {
                    "description": "Cover image, https URL",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Cover image, https URL"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "colorPrimary": {
                    "description": "Primary color, hex (#6d28d9)",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Primary color, hex (#6d28d9)"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "colorSecondary": {
                    "description": "Secondary color, hex",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Secondary color, hex"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "colorAccent": {
                    "description": "Accent color, hex",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Accent color, hex"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "liveColor": {
                    "description": "Main color of the live rooms, hex",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Main color of the live rooms, hex"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "liveBgColor": {
                    "description": "Background color of the live rooms, hex",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Background color of the live rooms, hex"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "liveShowLogo": {
                    "type": "boolean",
                    "description": "Logo shown in the live rooms"
                  },
                  "appFont": {
                    "description": "Font of the app for the members",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Font of the app for the members",
                        "enum": [
                          "inter",
                          "poppins",
                          "montserrat",
                          "dm-sans",
                          "nunito",
                          "space-grotesk",
                          "raleway",
                          "oswald",
                          "playfair",
                          "lora"
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "liveFont": {
                    "description": "Font of the live rooms and scenes",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Font of the live rooms and scenes",
                        "enum": [
                          "inter",
                          "poppins",
                          "montserrat",
                          "dm-sans",
                          "nunito",
                          "space-grotesk",
                          "raleway",
                          "oswald",
                          "playfair",
                          "lora"
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "joinApproval": {
                    "type": "boolean",
                    "description": "Membership on request: newcomers answer joinQuestions and the team approves them (list_join_requests)"
                  },
                  "joinQuestions": {
                    "type": "array",
                    "description": "Up to 3 questions asked to people requesting to join, 200 chars each",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/join-requests": {
      "get": {
        "operationId": "list_join_requests",
        "summary": "Demandes d'adhésion",
        "description": "Join requests of a space on request (joinApproval), with the answers to the questions. status: pending (default), approved or declined.",
        "tags": [
          "Membres et gamification"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Default pending",
              "enum": [
                "pending",
                "approved",
                "declined"
              ]
            },
            "description": "Default pending"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/join-requests/{id}/approve": {
      "post": {
        "operationId": "approve_join_request",
        "summary": "Accepter une demande d'adhésion",
        "description": "Approves a join request: member at once in a free space (member.joined), allowed to pay in a paid space. The person is notified.",
        "tags": [
          "Membres et gamification"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/join-requests/{id}/decline": {
      "post": {
        "operationId": "decline_join_request",
        "summary": "Refuser une demande d'adhésion",
        "description": "Declines a join request. The person is notified and cannot send a new request.",
        "tags": [
          "Membres et gamification"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/retention": {
      "get": {
        "operationId": "get_retention",
        "summary": "Fidélisation : décrochage et départs",
        "description": "Members drifting away (regular members whose activity of the last 14 days dropped well below their own rhythm, checked every night) and the reasons members gave when leaving or cancelling over the last `days` days (avoidable vs natural).",
        "tags": [
          "Membres et gamification"
        ],
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "Window of the exit reasons, default 90, max 365"
            },
            "description": "Window of the exit reasons, default 90, max 365"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/space/usage": {
      "get": {
        "operationId": "get_space_usage",
        "summary": "Consommation et facturation",
        "description": "Usage of the space since the last invoice (webinar hours, interactive and spectator hours, plays, stored minutes), account state (billing active, live allowed, cap) and the rate limit of the key.",
        "tags": [
          "Espace"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/space/audience": {
      "get": {
        "operationId": "get_space_audience",
        "summary": "Statistiques d'audience",
        "description": "Audience of the space's public pages (about page, public courses, custom domain, invitation pages) over the last `days` days: visitors, visits, page views, bounce rate, average visit time, daily series, referring sites, channels, pages, countries and conversions (free joins, join requests, checkouts, paid memberships, event registrations, paid seats). Pro and Entreprise tiers also get UTM sources / mediums / campaigns and the visit → join (or checkout → paid) funnel; `utm` and `funnel` are null otherwise. `configured: false` when statistics are not enabled on the platform. Cookieless; members' content is never tracked.",
        "tags": [
          "Espace"
        ],
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "Window in days, default 30, max 365"
            },
            "description": "Window in days, default 30, max 365"
          },
          {
            "name": "tz",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "IANA time zone of the daily series, default Europe/Paris"
            },
            "description": "IANA time zone of the daily series, default Europe/Paris"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/space/permissions": {
      "get": {
        "operationId": "get_space_permissions",
        "summary": "Droits des membres",
        "description": "Who may send voice messages, video messages and files in the posts and comments, who may create lives, and who may attach rich notes of « Ma liste » (rich text, @mentions, files, voice, video) to the space, with the maximum length of voice and video messages. Owner and admins always may.",
        "tags": [
          "Espace"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "update_space_permissions",
        "summary": "Modifier les droits des membres",
        "description": "Changes the member rights of the space. Send only the rights to change. Voice and video are costly (storage, encoding) and lives are billed: restrict them to some levels or groups when the owner asks.",
        "tags": [
          "Espace"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "voice": {
                    "type": "object",
                    "description": "Rule: who = everyone | custom | staff | admins; custom = members from minLevel and/or in groups (plus the staff)",
                    "properties": {
                      "who": {
                        "type": "string",
                        "description": "Who may",
                        "enum": [
                          "everyone",
                          "custom",
                          "staff",
                          "admins"
                        ]
                      },
                      "minLevel": {
                        "type": "number",
                        "description": "custom: from this level"
                      },
                      "groups": {
                        "type": "array",
                        "description": "custom: group ids or slugs",
                        "items": {
                          "type": "string"
                        }
                      }
                    },
                    "required": [
                      "who"
                    ]
                  },
                  "video": {
                    "type": "object",
                    "description": "Rule: who = everyone | custom | staff | admins; custom = members from minLevel and/or in groups (plus the staff)",
                    "properties": {
                      "who": {
                        "type": "string",
                        "description": "Who may",
                        "enum": [
                          "everyone",
                          "custom",
                          "staff",
                          "admins"
                        ]
                      },
                      "minLevel": {
                        "type": "number",
                        "description": "custom: from this level"
                      },
                      "groups": {
                        "type": "array",
                        "description": "custom: group ids or slugs",
                        "items": {
                          "type": "string"
                        }
                      }
                    },
                    "required": [
                      "who"
                    ]
                  },
                  "files": {
                    "type": "object",
                    "description": "Rule: who = everyone | custom | staff | admins; custom = members from minLevel and/or in groups (plus the staff)",
                    "properties": {
                      "who": {
                        "type": "string",
                        "description": "Who may",
                        "enum": [
                          "everyone",
                          "custom",
                          "staff",
                          "admins"
                        ]
                      },
                      "minLevel": {
                        "type": "number",
                        "description": "custom: from this level"
                      },
                      "groups": {
                        "type": "array",
                        "description": "custom: group ids or slugs",
                        "items": {
                          "type": "string"
                        }
                      }
                    },
                    "required": [
                      "who"
                    ]
                  },
                  "createLive": {
                    "type": "object",
                    "description": "Rule: who = everyone | custom | staff | admins; custom = members from minLevel and/or in groups (plus the staff)",
                    "properties": {
                      "who": {
                        "type": "string",
                        "description": "Who may",
                        "enum": [
                          "everyone",
                          "custom",
                          "staff",
                          "admins"
                        ]
                      },
                      "minLevel": {
                        "type": "number",
                        "description": "custom: from this level"
                      },
                      "groups": {
                        "type": "array",
                        "description": "custom: group ids or slugs",
                        "items": {
                          "type": "string"
                        }
                      }
                    },
                    "required": [
                      "who"
                    ]
                  },
                  "richNotes": {
                    "type": "object",
                    "description": "Rule: who = everyone | custom | staff | admins; custom = members from minLevel and/or in groups (plus the staff)",
                    "properties": {
                      "who": {
                        "type": "string",
                        "description": "Who may",
                        "enum": [
                          "everyone",
                          "custom",
                          "staff",
                          "admins"
                        ]
                      },
                      "minLevel": {
                        "type": "number",
                        "description": "custom: from this level"
                      },
                      "groups": {
                        "type": "array",
                        "description": "custom: group ids or slugs",
                        "items": {
                          "type": "string"
                        }
                      }
                    },
                    "required": [
                      "who"
                    ]
                  },
                  "voiceMaxSec": {
                    "type": "number",
                    "description": "Longest voice message in seconds (15-600)"
                  },
                  "videoMaxSec": {
                    "type": "number",
                    "description": "Longest video message in seconds (15-600)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/users": {
      "get": {
        "operationId": "list_users",
        "summary": "Lister les membres",
        "description": "Members of the space, paginated (200 max per page), with role, status, XP and level.",
        "tags": [
          "Membres et gamification"
        ],
        "parameters": [
          {
            "name": "role",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Filter by role",
              "enum": [
                "member",
                "contributor",
                "teacher",
                "moderator",
                "admin",
                "owner"
              ]
            },
            "description": "Filter by role"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Filter by status",
              "enum": [
                "active",
                "suspended",
                "expired"
              ]
            },
            "description": "Filter by status"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "Page size"
            },
            "description": "Page size"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Cursor of the next page (nextCursor of the previous call)"
            },
            "description": "Cursor of the next page (nextCursor of the previous call)"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "create_user",
        "summary": "Créer un membre (externe)",
        "description": "Creates (or updates, idempotent on externalId) a user of your platform and adds them as member of the space.",
        "tags": [
          "Membres et gamification"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "externalId": {
                    "type": "string",
                    "description": "Your stable id of the user"
                  },
                  "name": {
                    "type": "string",
                    "description": "Display name"
                  },
                  "role": {
                    "type": "string",
                    "description": "Role in the space, default member",
                    "enum": [
                      "member",
                      "contributor",
                      "teacher",
                      "moderator",
                      "admin"
                    ]
                  },
                  "member": {
                    "type": "boolean",
                    "description": "false creates the account without joining the space"
                  }
                },
                "required": [
                  "externalId",
                  "name"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/users/{id}": {
      "get": {
        "operationId": "get_user",
        "summary": "Fiche d’un membre",
        "description": "One user with membership (role, status, XP, level) and stats (lessons completed, lives joined, posts, badges).",
        "tags": [
          "Membres et gamification"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
            },
            "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "update_user",
        "summary": "Modifier un membre",
        "description": "Changes the name (users created by your platform only), the role or the status of a member. The owner cannot be changed.",
        "tags": [
          "Membres et gamification"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "New name"
                  },
                  "role": {
                    "type": "string",
                    "description": "New role",
                    "enum": [
                      "member",
                      "contributor",
                      "teacher",
                      "moderator",
                      "admin"
                    ]
                  },
                  "status": {
                    "type": "string",
                    "description": "New status",
                    "enum": [
                      "active",
                      "suspended"
                    ]
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
            },
            "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "remove_user",
        "summary": "Retirer un membre",
        "description": "Removes the member from the space (account and history kept).",
        "tags": [
          "Membres et gamification"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
            },
            "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/users/{id}/entry": {
      "post": {
        "operationId": "create_user_entry_url",
        "summary": "URL de connexion (SSO)",
        "description": "Single-use, 15-minute sign-in URL that opens the space (feed, courses, calendar…) for a user of your platform (ext:… only; created when name is given). Ask for it at click time.",
        "tags": [
          "Membres et gamification"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Creates the user if unknown"
                  },
                  "redirect": {
                    "type": "string",
                    "description": "home (default), posts, courses, calendar, live, leaderboard, tickets, challenges, or a path of the space"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "\"ext:<externalId>\""
            },
            "description": "\"ext:<externalId>\""
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/users/{id}/progress": {
      "get": {
        "operationId": "get_user_progress",
        "summary": "Progression d’un membre",
        "description": "Progress of a user in every course of the space (lessons completed, percentage).",
        "tags": [
          "Membres et gamification"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
            },
            "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/users/{id}/xp": {
      "get": {
        "operationId": "get_user_xp",
        "summary": "XP d’un membre",
        "description": "Total XP, level and latest XP events of a user in the space.",
        "tags": [
          "Membres et gamification"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
            },
            "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "Events returned, 1000 max"
            },
            "description": "Events returned, 1000 max"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "award_xp",
        "summary": "Attribuer des XP",
        "description": "Gives (or takes, negative amount) XP to a user from your platform: quiz passed, homework handed in… Level recalculated.",
        "tags": [
          "Membres et gamification"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "amount": {
                    "type": "number",
                    "description": "-1000 to 1000"
                  },
                  "reason": {
                    "type": "string",
                    "description": "Shown as source api:<reason>, 60 chars"
                  },
                  "refId": {
                    "type": "string",
                    "description": "Your reference"
                  }
                },
                "required": [
                  "amount"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
            },
            "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/users/{id}/badges": {
      "get": {
        "operationId": "get_user_badges",
        "summary": "Badges d’un membre",
        "description": "Badges awarded to a user.",
        "tags": [
          "Membres et gamification"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
            },
            "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/leaderboard": {
      "get": {
        "operationId": "get_leaderboard",
        "summary": "Classement",
        "description": "Members ranked by XP (500 max), optionally within one group.",
        "tags": [
          "Membres et gamification"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "Page size"
            },
            "description": "Page size"
          },
          {
            "name": "group",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Group id or slug"
            },
            "description": "Group id or slug"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/badges": {
      "get": {
        "operationId": "list_badges",
        "summary": "Catalogue des badges",
        "description": "Badges of the space with their criteria and XP reward.",
        "tags": [
          "Membres et gamification"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/challenges": {
      "get": {
        "operationId": "list_challenges",
        "summary": "Défis",
        "description": "Challenges of the space (objective, dates, status, participants).",
        "tags": [
          "Membres et gamification"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/challenges/{id}": {
      "get": {
        "operationId": "get_challenge",
        "summary": "Détail d’un défi",
        "description": "One challenge with its participants and their progress.",
        "tags": [
          "Membres et gamification"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions": {
      "get": {
        "operationId": "list_live_sessions",
        "summary": "Lister les lives",
        "description": "Live sessions of the space, newest first (200 max), with status, dates, replay and counters.",
        "tags": [
          "Lives"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Filter by status",
              "enum": [
                "scheduled",
                "live",
                "ended",
                "cancelled"
              ]
            },
            "description": "Filter by status"
          },
          {
            "name": "group",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Only the content addressed to this group (id or slug)"
            },
            "description": "Only the content addressed to this group (id or slug)"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "create_live_session",
        "summary": "Programmer un live",
        "description": "Schedules a live (webinar or conference) in the space. Returns the session and hostUrl, the page where the host starts it.",
        "tags": [
          "Lives"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "description": "Title"
                  },
                  "description": {
                    "type": "string",
                    "description": "Description"
                  },
                  "mode": {
                    "type": "string",
                    "description": "broadcast: only host and speakers publish (default); conference: everyone publishes",
                    "enum": [
                      "broadcast",
                      "conference"
                    ]
                  },
                  "scheduledAt": {
                    "type": "string",
                    "description": "ISO 8601 date"
                  },
                  "durationMin": {
                    "type": "number",
                    "description": "Planned duration, default 60"
                  },
                  "maxParticipants": {
                    "type": "number",
                    "description": "2 to 1000, default 100"
                  },
                  "recordingEnabled": {
                    "type": "boolean",
                    "description": "Automatic recording, default true"
                  },
                  "chat": {
                    "type": "string",
                    "description": "Chat panel at arrival: closed (default), open, or off (disabled)",
                    "enum": [
                      "closed",
                      "open",
                      "off"
                    ]
                  },
                  "hostEmail": {
                    "type": "string",
                    "description": "LearnFloo account of the host (owner, admin, moderator or teacher); default the creator of the key"
                  },
                  "groups": {
                    "type": "array",
                    "description": "Audience: group ids or slugs; empty = the whole space",
                    "items": {
                      "type": "string"
                    }
                  },
                  "replay": {
                    "type": "string",
                    "description": "Who watches the replay (host and staff always do): all (default, whoever can open the live), attendees (joined it), groups (replayGroups), level (replayMinLevel and above), none",
                    "enum": [
                      "all",
                      "attendees",
                      "groups",
                      "level",
                      "none"
                    ]
                  },
                  "replayGroups": {
                    "type": "array",
                    "description": "Replay restricted to these group ids or slugs (replay = groups)",
                    "items": {
                      "type": "string"
                    }
                  },
                  "replayMinLevel": {
                    "type": "number",
                    "description": "Minimum member level, 2 to 10 (replay = level)"
                  },
                  "replayChat": {
                    "type": "boolean",
                    "description": "Show the live chat and questions next to the replay, default true"
                  },
                  "replayPublish": {
                    "type": "string",
                    "description": "auto (default): replay visible as soon as it is ready; review: held back until published (update_live_session replayPublished: true)",
                    "enum": [
                      "auto",
                      "review"
                    ]
                  }
                },
                "required": [
                  "title",
                  "scheduledAt"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}": {
      "get": {
        "operationId": "get_live_session",
        "summary": "Détail d’un live",
        "description": "One live session: status, schedule, participants now, recording and replay, chat mode, conversions, active scene.",
        "tags": [
          "Lives"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "update_live_session",
        "summary": "Modifier un live",
        "description": "Changes a live. Before it starts: everything (date, duration, format, capacity, recording, chat, audience, replay rule). Once started: title, description, audience, capacity, chat, replay rule. Once ended: title, description, audience, replay rule, replay chat and publishing.",
        "tags": [
          "Lives"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "description": "Title"
                  },
                  "description": {
                    "type": "string",
                    "description": "Description"
                  },
                  "mode": {
                    "type": "string",
                    "description": "Format, before the live",
                    "enum": [
                      "broadcast",
                      "conference"
                    ]
                  },
                  "scheduledAt": {
                    "type": "string",
                    "description": "ISO 8601 date"
                  },
                  "durationMin": {
                    "type": "number",
                    "description": "Minutes"
                  },
                  "maxParticipants": {
                    "type": "number",
                    "description": "2 to 1000"
                  },
                  "recordingEnabled": {
                    "type": "boolean",
                    "description": "Automatic recording"
                  },
                  "chat": {
                    "type": "string",
                    "description": "Chat mode",
                    "enum": [
                      "closed",
                      "open",
                      "off"
                    ]
                  },
                  "groups": {
                    "type": "array",
                    "description": "Audience: group ids or slugs; empty = the whole space",
                    "items": {
                      "type": "string"
                    }
                  },
                  "replay": {
                    "type": "string",
                    "description": "Who watches the replay (host and staff always do): all (default, whoever can open the live), attendees (joined it), groups (replayGroups), level (replayMinLevel and above), none",
                    "enum": [
                      "all",
                      "attendees",
                      "groups",
                      "level",
                      "none"
                    ]
                  },
                  "replayGroups": {
                    "type": "array",
                    "description": "Replay restricted to these group ids or slugs (replay = groups)",
                    "items": {
                      "type": "string"
                    }
                  },
                  "replayMinLevel": {
                    "type": "number",
                    "description": "Minimum member level, 2 to 10 (replay = level)"
                  },
                  "replayChat": {
                    "type": "boolean",
                    "description": "Show the live chat and questions next to the replay"
                  },
                  "replayPublish": {
                    "type": "string",
                    "description": "auto: replay visible as soon as it is ready; review: held back until published (switching an already visible replay to review hides it)",
                    "enum": [
                      "auto",
                      "review"
                    ]
                  },
                  "replayPublished": {
                    "type": "boolean",
                    "description": "true publishes a replay held back for review; false hides it from members again (switches to review)"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "cancel_live_session",
        "summary": "Annuler un live",
        "description": "Cancels a scheduled live (calendar event removed). A running or ended live cannot be cancelled.",
        "tags": [
          "Lives"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/permanent": {
      "delete": {
        "operationId": "delete_live_session",
        "summary": "Supprimer définitivement un live",
        "description": "Permanently deletes an ended or cancelled live with its calendar event, chat, polls, invites and participants (cancel a scheduled live first). The replay video is kept in the videos unless deleteReplay is true. The time already on air stays billed.",
        "tags": [
          "Lives"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "deleteReplay",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Also delete the replay video (default false)"
            },
            "description": "Also delete the replay video (default false)"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/entry": {
      "post": {
        "operationId": "create_live_entry_url",
        "summary": "URL d’entrée d’un apprenant",
        "description": "Personal, single-use, 15-minute URL that signs a user of your platform into a live (viewer or speaker). Ask for it at click time.",
        "tags": [
          "Lives"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sessionId": {
                    "type": "string",
                    "description": "LearnFloo id"
                  },
                  "user": {
                    "type": "object",
                    "description": "User of your platform: { externalId, name }",
                    "properties": {
                      "externalId": {
                        "type": "string",
                        "description": "Your stable id of the user, 200 chars max"
                      },
                      "name": {
                        "type": "string",
                        "description": "Display name, 60 chars max"
                      }
                    },
                    "required": [
                      "externalId"
                    ]
                  },
                  "role": {
                    "type": "string",
                    "description": "viewer (default) or speaker (mic and camera from the start)",
                    "enum": [
                      "viewer",
                      "speaker"
                    ]
                  }
                },
                "required": [
                  "sessionId",
                  "user"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/attendance": {
      "get": {
        "operationId": "get_live_attendance",
        "summary": "Présences d’un live",
        "description": "Attendance report: summary (attended, peak, average watch time, spectator and interactive hours) and per participant watch time and percentage. Costs 5 rate-limit tokens.",
        "tags": [
          "Lives"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/leads": {
      "get": {
        "operationId": "get_live_leads",
        "summary": "Prospects d’un live",
        "description": "Lead scoring of the registrants of a live, best first: score 0-100, grade (customer, hot, warm, cold, absent), e-mail, UTM origin, watch time, messages, votes, clicks, conversion, and whether they clicked the offer or a button without buying (clicked_not_converted: the people to follow up). Costs 5 rate-limit tokens.",
        "tags": [
          "Lives"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "filter",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Only these prospects, default all",
              "enum": [
                "all",
                "hot",
                "warm",
                "cold",
                "customer",
                "absent",
                "clicked_not_converted"
              ]
            },
            "description": "Only these prospects, default all"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/participants": {
      "get": {
        "operationId": "get_live_participants",
        "summary": "Participants d’un live",
        "description": "Instant state of the people registered on a live: connected, spectator, hand raised, role.",
        "tags": [
          "Lives"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/chat": {
      "get": {
        "operationId": "get_live_chat",
        "summary": "Chat d’un live",
        "description": "Chat messages of a live, oldest first (2000 max), kept after the live.",
        "tags": [
          "Lives"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "Default 500, 2000 max"
            },
            "description": "Default 500, 2000 max"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/replay": {
      "get": {
        "operationId": "get_live_replay",
        "summary": "Replay d’un live",
        "description": "The replay of a live: MP4, HLS and embed URLs, thumbnail, duration, linked lesson, views.",
        "tags": [
          "Lives"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/conversions": {
      "post": {
        "operationId": "report_live_conversion",
        "summary": "Signaler une inscription",
        "description": "Reports a sign-up or purchase made during a live: announced in the chat and on the scene, counted in the report, webhook live.conversion.",
        "tags": [
          "Lives"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "externalId": {
                    "type": "string",
                    "description": "Your id of the buyer"
                  },
                  "userId": {
                    "type": "string",
                    "description": "Or the LearnFloo user id"
                  },
                  "email": {
                    "type": "string",
                    "description": "Or the e-mail of the LearnFloo account"
                  },
                  "name": {
                    "type": "string",
                    "description": "First name shown in the announcement"
                  },
                  "label": {
                    "type": "string",
                    "description": "Product"
                  },
                  "amountCents": {
                    "type": "number",
                    "description": "Amount in the smallest unit"
                  },
                  "currency": {
                    "type": "string",
                    "description": "Currency",
                    "enum": [
                      "eur",
                      "usd"
                    ]
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/invites": {
      "get": {
        "operationId": "list_live_invites",
        "summary": "Liens d’invitation",
        "description": "Shareable invitation links of a live (speaker, viewer, assistant, moderator).",
        "tags": [
          "Lives"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "create_live_invite",
        "summary": "Créer un lien d’invitation",
        "description": "Creates a reusable invitation link for people without an account on your platform (external speaker, control room assistant, chat moderator).",
        "tags": [
          "Lives"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "role": {
                    "type": "string",
                    "description": "Role given by the link, default viewer",
                    "enum": [
                      "viewer",
                      "speaker",
                      "assistant",
                      "moderator"
                    ]
                  },
                  "label": {
                    "type": "string",
                    "description": "Label"
                  },
                  "expiresInHours": {
                    "type": "number",
                    "description": "Expiry"
                  },
                  "maxUses": {
                    "type": "number",
                    "description": "Max uses"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/invites/{inviteId}": {
      "delete": {
        "operationId": "revoke_live_invite",
        "summary": "Révoquer un lien d’invitation",
        "description": "Revokes an invitation link.",
        "tags": [
          "Lives"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "inviteId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Invite id"
            },
            "description": "Invite id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/participants/{userId}/role": {
      "put": {
        "operationId": "set_participant_role",
        "summary": "Rôle d’un participant",
        "description": "Gives or takes the floor, or names a control-room assistant or a moderator, for a participant already registered on the live. Applied immediately.",
        "tags": [
          "Lives"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "role": {
                    "type": "string",
                    "description": "New role",
                    "enum": [
                      "speaker",
                      "viewer",
                      "assistant",
                      "moderator"
                    ]
                  }
                },
                "required": [
                  "role"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
            },
            "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/viewers": {
      "put": {
        "operationId": "set_extra_viewers",
        "summary": "Spectateurs affichés en plus",
        "description": "Adds viewers to the counter shown by the viewers widget of the scenes (never counted in attendance or billing). 0 removes it.",
        "tags": [
          "Lives"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "extra": {
                    "type": "number",
                    "description": "Viewers added to the real count"
                  }
                },
                "required": [
                  "extra"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/chat/stage": {
      "put": {
        "operationId": "stage_chat_message",
        "summary": "Message du chat à l’antenne",
        "description": "Shows a chat message on the scene (message slot, else bottom left); null removes it.",
        "tags": [
          "Lives"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "messageId": {
                    "description": "Chat message id, null to remove",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Chat message id, null to remove"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "messageId"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/scenes": {
      "get": {
        "operationId": "get_live_scenes",
        "summary": "Régie d’un live",
        "description": "The whole control room of a live: scenes with slots and overlays, active scene, auto-advance state, media state (PDF page, video playing), temporary bands.",
        "tags": [
          "Scènes et régie"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "create_scene",
        "summary": "Créer une scène",
        "description": "Creates a scene in a live, from its fields or from a template of the space ({ template: \"name\" }). activate: true puts it on air right away. Works before and during the live.",
        "tags": [
          "Scènes et régie"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name shown in the control room"
                  },
                  "layout": {
                    "type": "string",
                    "description": "Layout of the slots",
                    "enum": [
                      "solo",
                      "grid",
                      "spotlight",
                      "sidebyside",
                      "pip",
                      "cinema",
                      "free"
                    ]
                  },
                  "slots": {
                    "type": "array",
                    "description": "Slots: { kind: host | guest | screen | media | embed, guestIndex?, userId?, mediaId?, url?, mediaKind?, fit?, loop?, muted?, title?, autoplay?, once?, startSec?, durationSec?, volume?, mediaSec? (video file length in seconds, measured by the editor), x?, y?, w?, h?, shape?: rect | rounded | square | squircle | circle | portrait, filter?: none | bw | noir | sepia | vintage | warm | cool | vivid | faded | bright | contrast, bgMode?: none | blur | image (camera background on the person's device), bgBlur? 1-20, bgImage? (https or preset:ocean|forest|sunset|slate) } (volume / muted also set a camera's sound on the air)",
                    "items": {
                      "type": "object",
                      "description": "Slot"
                    }
                  },
                  "overlays": {
                    "type": "array",
                    "description": "Stickers, bands and widgets: { id?, type: band | sticker | poll | message | viewers, text?, label?, emoji?, imageUrl?, bg?, color?, fontSize?, bold?, scroll?, speed?, align?, visible?, opacity?, x?, y?, w?, h?, … }",
                    "items": {
                      "type": "object",
                      "description": "Overlay"
                    }
                  },
                  "background": {
                    "type": "string",
                    "description": "CSS color of the background"
                  },
                  "backgroundImageUrl": {
                    "description": "https image, null to remove",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "https image, null to remove"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "showLogo": {
                    "type": "boolean",
                    "description": "Space logo in the corner"
                  },
                  "framed": {
                    "description": "Framed: a margin around the slots lets the background show (fixed layouts); null to remove",
                    "anyOf": [
                      {
                        "type": "boolean",
                        "description": "Framed: a margin around the slots lets the background show (fixed layouts); null to remove"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "transition": {
                    "type": "string",
                    "description": "Transition when the scene goes on air",
                    "enum": [
                      "cut",
                      "fade",
                      "black",
                      "slide-left",
                      "slide-right",
                      "slide-up",
                      "slide-down",
                      "zoom",
                      "wipe",
                      "blur"
                    ]
                  },
                  "transitionMs": {
                    "type": "number",
                    "description": "Transition duration, 100 to 3000 ms"
                  },
                  "audios": {
                    "type": "array",
                    "description": "Sounds of the scene, several allowed (6 max), each { mediaId } of a library audio file or { url }, autoplay?, once?, loop?, volume?, startSec?, durationSec?, mediaSec? (file length in seconds); replaces the list, [] removes every sound",
                    "items": {
                      "type": "object",
                      "description": "Sound"
                    }
                  },
                  "audio": {
                    "description": "Older single-sound field, same shape as an audios item (sets the list to this one sound); null removes every sound",
                    "anyOf": [
                      {
                        "type": "object",
                        "description": "Older single-sound field, same shape as an audios item (sets the list to this one sound); null removes every sound"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "durationSec": {
                    "description": "Auto-advance: seconds on screen, 1 to 86400, stretched to the end of the autoplaying, not looped videos and sounds of known length",
                    "anyOf": [
                      {
                        "type": "number",
                        "description": "Auto-advance: seconds on screen, 1 to 86400, stretched to the end of the autoplaying, not looped videos and sounds of known length"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "nextSceneId": {
                    "description": "Auto-advance: next scene id (default: the next in the list)",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Auto-advance: next scene id (default: the next in the list)"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "jingle": {
                    "description": "Jingle: plays its duration (or the length of its videos and sounds), then the scene it interrupted resumes where it was, even without auto-advance; reached by auto-advance it goes on to the next scene; null to remove",
                    "anyOf": [
                      {
                        "type": "boolean",
                        "description": "Jingle: plays its duration (or the length of its videos and sounds), then the scene it interrupted resumes where it was, even without auto-advance; reached by auto-advance it goes on to the next scene; null to remove"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "locked": {
                    "type": "boolean",
                    "description": "Locked scenes refuse changes until unlocked"
                  },
                  "template": {
                    "type": "string",
                    "description": "Name or id of a scene template of the space"
                  },
                  "activate": {
                    "type": "boolean",
                    "description": "Put on air right away"
                  },
                  "afterId": {
                    "type": "string",
                    "description": "Insert after this scene"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Stable id, 1 to 40 chars (letters, digits, -, _); generated when absent"
            },
            "description": "Stable id, 1 to 40 chars (letters, digits, -, _); generated when absent"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/scenes/{sceneId}": {
      "get": {
        "operationId": "get_live_scene",
        "summary": "Détail d’une scène",
        "description": "One scene of a live.",
        "tags": [
          "Scènes et régie"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "sceneId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Scene id"
            },
            "description": "Scene id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "update_scene",
        "summary": "Modifier une scène",
        "description": "Changes the given fields of a scene; slots and overlays, when present, replace the whole lists (use the overlay and slot tools to touch one element). Visible immediately if on air.",
        "tags": [
          "Scènes et régie"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name shown in the control room"
                  },
                  "layout": {
                    "type": "string",
                    "description": "Layout of the slots",
                    "enum": [
                      "solo",
                      "grid",
                      "spotlight",
                      "sidebyside",
                      "pip",
                      "cinema",
                      "free"
                    ]
                  },
                  "slots": {
                    "type": "array",
                    "description": "Slots: { kind: host | guest | screen | media | embed, guestIndex?, userId?, mediaId?, url?, mediaKind?, fit?, loop?, muted?, title?, autoplay?, once?, startSec?, durationSec?, volume?, mediaSec? (video file length in seconds, measured by the editor), x?, y?, w?, h?, shape?: rect | rounded | square | squircle | circle | portrait, filter?: none | bw | noir | sepia | vintage | warm | cool | vivid | faded | bright | contrast, bgMode?: none | blur | image (camera background on the person's device), bgBlur? 1-20, bgImage? (https or preset:ocean|forest|sunset|slate) } (volume / muted also set a camera's sound on the air)",
                    "items": {
                      "type": "object",
                      "description": "Slot"
                    }
                  },
                  "overlays": {
                    "type": "array",
                    "description": "Stickers, bands and widgets: { id?, type: band | sticker | poll | message | viewers, text?, label?, emoji?, imageUrl?, bg?, color?, fontSize?, bold?, scroll?, speed?, align?, visible?, opacity?, x?, y?, w?, h?, … }",
                    "items": {
                      "type": "object",
                      "description": "Overlay"
                    }
                  },
                  "background": {
                    "type": "string",
                    "description": "CSS color of the background"
                  },
                  "backgroundImageUrl": {
                    "description": "https image, null to remove",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "https image, null to remove"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "showLogo": {
                    "type": "boolean",
                    "description": "Space logo in the corner"
                  },
                  "framed": {
                    "description": "Framed: a margin around the slots lets the background show (fixed layouts); null to remove",
                    "anyOf": [
                      {
                        "type": "boolean",
                        "description": "Framed: a margin around the slots lets the background show (fixed layouts); null to remove"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "transition": {
                    "type": "string",
                    "description": "Transition when the scene goes on air",
                    "enum": [
                      "cut",
                      "fade",
                      "black",
                      "slide-left",
                      "slide-right",
                      "slide-up",
                      "slide-down",
                      "zoom",
                      "wipe",
                      "blur"
                    ]
                  },
                  "transitionMs": {
                    "type": "number",
                    "description": "Transition duration, 100 to 3000 ms"
                  },
                  "audios": {
                    "type": "array",
                    "description": "Sounds of the scene, several allowed (6 max), each { mediaId } of a library audio file or { url }, autoplay?, once?, loop?, volume?, startSec?, durationSec?, mediaSec? (file length in seconds); replaces the list, [] removes every sound",
                    "items": {
                      "type": "object",
                      "description": "Sound"
                    }
                  },
                  "audio": {
                    "description": "Older single-sound field, same shape as an audios item (sets the list to this one sound); null removes every sound",
                    "anyOf": [
                      {
                        "type": "object",
                        "description": "Older single-sound field, same shape as an audios item (sets the list to this one sound); null removes every sound"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "durationSec": {
                    "description": "Auto-advance: seconds on screen, 1 to 86400, stretched to the end of the autoplaying, not looped videos and sounds of known length",
                    "anyOf": [
                      {
                        "type": "number",
                        "description": "Auto-advance: seconds on screen, 1 to 86400, stretched to the end of the autoplaying, not looped videos and sounds of known length"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "nextSceneId": {
                    "description": "Auto-advance: next scene id (default: the next in the list)",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Auto-advance: next scene id (default: the next in the list)"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "jingle": {
                    "description": "Jingle: plays its duration (or the length of its videos and sounds), then the scene it interrupted resumes where it was, even without auto-advance; reached by auto-advance it goes on to the next scene; null to remove",
                    "anyOf": [
                      {
                        "type": "boolean",
                        "description": "Jingle: plays its duration (or the length of its videos and sounds), then the scene it interrupted resumes where it was, even without auto-advance; reached by auto-advance it goes on to the next scene; null to remove"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "locked": {
                    "type": "boolean",
                    "description": "Locked scenes refuse changes until unlocked"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Stable id, 1 to 40 chars (letters, digits, -, _); generated when absent"
            },
            "description": "Stable id, 1 to 40 chars (letters, digits, -, _); generated when absent"
          },
          {
            "name": "sceneId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Scene id"
            },
            "description": "Scene id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "delete_scene",
        "summary": "Supprimer une scène",
        "description": "Removes a scene (automatic layout if it was on air). Returns the control room.",
        "tags": [
          "Scènes et régie"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "sceneId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Scene id"
            },
            "description": "Scene id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/scenes/{sceneId}/activate": {
      "post": {
        "operationId": "activate_scene",
        "summary": "Mettre une scène à l’antenne",
        "description": "Puts a scene on air for everyone (room, audience stream, recording, external broadcasts). Its videos restart from the beginning.",
        "tags": [
          "Scènes et régie"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "sceneId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Scene id"
            },
            "description": "Scene id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/scenes/active": {
      "put": {
        "operationId": "set_active_scene",
        "summary": "Scène active (ou automatique)",
        "description": "Sets the scene on air by id; null returns to the automatic layout (cameras in a grid, screen share large).",
        "tags": [
          "Scènes et régie"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sceneId": {
                    "description": "Scene id, null for the automatic layout",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Scene id, null for the automatic layout"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "sceneId"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/scenes/order": {
      "put": {
        "operationId": "reorder_scenes",
        "summary": "Réordonner les scènes",
        "description": "Sets the order of the scenes of a live.",
        "tags": [
          "Scènes et régie"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sceneIds": {
                    "type": "array",
                    "description": "Scene ids in the wanted order",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "required": [
                  "sceneIds"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/scenes/auto": {
      "put": {
        "operationId": "set_auto_advance",
        "summary": "Enchaînement automatique",
        "description": "Turns the automatic scene sequence on or off (each scene with durationSec gives way to nextSceneId or the next one), with or without loop.",
        "tags": [
          "Scènes et régie"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean",
                    "description": "On or off"
                  },
                  "loop": {
                    "type": "boolean",
                    "description": "Restart from the first scene at the end"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/bands": {
      "post": {
        "operationId": "show_band",
        "summary": "Bandeau éphémère",
        "description": "Shows a band at the top of every screen for a few seconds, whatever the scene (break, announcement).",
        "tags": [
          "Scènes et régie"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text": {
                    "type": "string",
                    "description": "Text"
                  },
                  "bg": {
                    "type": "string",
                    "description": "Background color, hex"
                  },
                  "color": {
                    "type": "string",
                    "description": "Text color, hex"
                  },
                  "seconds": {
                    "type": "number",
                    "description": "2 to 60, default 8"
                  }
                },
                "required": [
                  "text"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/media/{mediaId}": {
      "put": {
        "operationId": "control_scene_media",
        "summary": "Piloter un PDF ou une vidéo",
        "description": "Turns the page of a PDF, or plays, pauses and seeks a video or the scene sound present in a scene, synchronised for everyone.",
        "tags": [
          "Scènes et régie"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "page": {
                    "type": "number",
                    "description": "Page of a PDF"
                  },
                  "playing": {
                    "type": "boolean",
                    "description": "Play or pause"
                  },
                  "position": {
                    "type": "number",
                    "description": "Position in seconds"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "mediaId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Media id used in a scene"
            },
            "description": "Media id used in a scene"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/scenes/{sceneId}/overlays": {
      "post": {
        "operationId": "add_overlay",
        "summary": "Ajouter un sticker ou un bandeau",
        "description": "Adds a sticker, a band or a widget (poll, message, viewers) to a scene. Give it a stable id to update it later.",
        "tags": [
          "Scènes et régie"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Overlay fields (type band | sticker | poll | message | viewers, id?, text, label, emoji, imageUrl, bg, color, fontSize, bold, scroll, speed, align, visible, opacity, x, y, w, h…)"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "sceneId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Scene id"
            },
            "description": "Scene id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/scenes/{sceneId}/overlays/{overlayId}": {
      "patch": {
        "operationId": "update_overlay",
        "summary": "Modifier un sticker ou un bandeau",
        "description": "Changes the given fields of one overlay of a scene ({ text }, { visible: false }, { x, y }…). Visible immediately if on air.",
        "tags": [
          "Scènes et régie"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Fields to change"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "sceneId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Scene id"
            },
            "description": "Scene id"
          },
          {
            "name": "overlayId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Overlay id"
            },
            "description": "Overlay id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "delete_overlay",
        "summary": "Retirer un sticker ou un bandeau",
        "description": "Removes an overlay from a scene.",
        "tags": [
          "Scènes et régie"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "sceneId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Scene id"
            },
            "description": "Scene id"
          },
          {
            "name": "overlayId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Overlay id"
            },
            "description": "Overlay id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/overlays/{overlayId}": {
      "patch": {
        "operationId": "update_overlay_everywhere",
        "summary": "Modifier un bandeau dans toutes les scènes",
        "description": "Changes the overlay carrying this id in every scene of the live: a common band (seats left, price, next step) updated in one call.",
        "tags": [
          "Scènes et régie"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Fields to change"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "overlayId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Overlay id shared by the scenes"
            },
            "description": "Overlay id shared by the scenes"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/scenes/{sceneId}/slots": {
      "post": {
        "operationId": "add_slot",
        "summary": "Ajouter un emplacement",
        "description": "Adds a slot (host, guest, screen, media, embed) to a scene; position 0 = main.",
        "tags": [
          "Scènes et régie"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Slot fields (kind, guestIndex, userId, mediaId, url, mediaKind, fit, loop, muted, title, autoplay, once, startSec, durationSec, volume, x, y, w, h, position; cameras: shape, filter, bgMode, bgBlur, bgImage)"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "sceneId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Scene id"
            },
            "description": "Scene id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/scenes/{sceneId}/slots/{slotId}": {
      "patch": {
        "operationId": "update_slot",
        "summary": "Modifier un emplacement",
        "description": "Changes a slot of a scene (other media, guest, fit, geometry in free layout, position).",
        "tags": [
          "Scènes et régie"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Fields to change"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "sceneId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Scene id"
            },
            "description": "Scene id"
          },
          {
            "name": "slotId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Slot id"
            },
            "description": "Slot id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "delete_slot",
        "summary": "Retirer un emplacement",
        "description": "Removes a slot from a scene.",
        "tags": [
          "Scènes et régie"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "sceneId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Scene id"
            },
            "description": "Scene id"
          },
          {
            "name": "slotId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Slot id"
            },
            "description": "Slot id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/scene-templates": {
      "get": {
        "operationId": "list_scene_templates",
        "summary": "Modèles de scènes",
        "description": "Scene templates of the space, reusable in every live.",
        "tags": [
          "Scènes et régie"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "create_scene_template",
        "summary": "Enregistrer un modèle de scène",
        "description": "Saves a scene template from fields ({ name, scene }) or from an existing scene ({ name, sessionId, sceneId }). Same name = replaced.",
        "tags": [
          "Scènes et régie"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Template name"
                  },
                  "scene": {
                    "type": "object",
                    "description": "Scene fields"
                  },
                  "sessionId": {
                    "type": "string",
                    "description": "Live id of an existing scene"
                  },
                  "sceneId": {
                    "type": "string",
                    "description": "Scene id to save"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/scene-templates/{id}": {
      "delete": {
        "operationId": "delete_scene_template",
        "summary": "Supprimer un modèle de scène",
        "description": "Deletes a scene template (id or name).",
        "tags": [
          "Scènes et régie"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Template id or name"
            },
            "description": "Template id or name"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/polls": {
      "get": {
        "operationId": "list_live_polls",
        "summary": "Sondages d’un live",
        "description": "Polls and quizzes of a live with their counts, kept after the live.",
        "tags": [
          "Sondages et quiz"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Filter by status",
              "enum": [
                "draft",
                "open",
                "closed"
              ]
            },
            "description": "Filter by status"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "create_poll",
        "summary": "Préparer un sondage ou un quiz",
        "description": "Creates a poll (opinion) or a quiz (with correct answers) in a live, as a draft, or opened right away with open: true during the live. 2 to 6 options.",
        "tags": [
          "Sondages et quiz"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "description": "Default poll",
                    "enum": [
                      "poll",
                      "quiz"
                    ]
                  },
                  "question": {
                    "type": "string",
                    "description": "Question"
                  },
                  "options": {
                    "type": "array",
                    "description": "2 to 6 answers",
                    "items": {
                      "type": "string"
                    }
                  },
                  "correct": {
                    "type": "array",
                    "description": "Quiz: 0-based indexes of the correct answers",
                    "items": {
                      "type": "integer"
                    }
                  },
                  "allowMultiple": {
                    "type": "boolean",
                    "description": "Several answers allowed"
                  },
                  "phase": {
                    "type": "string",
                    "description": "When it runs: by hand during the live (default), open in the waiting room before the start, or opened on the closing screen when the live ends",
                    "enum": [
                      "live",
                      "waiting",
                      "closing"
                    ]
                  },
                  "open": {
                    "type": "boolean",
                    "description": "Open right away (running live only)"
                  }
                },
                "required": [
                  "question",
                  "options"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/polls/{pollId}": {
      "get": {
        "operationId": "get_live_poll",
        "summary": "Détail d’un sondage",
        "description": "One poll or quiz with its results.",
        "tags": [
          "Sondages et quiz"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "pollId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Poll id"
            },
            "description": "Poll id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "update_poll",
        "summary": "Modifier un sondage (brouillon)",
        "description": "Changes a draft poll (same fields as creation).",
        "tags": [
          "Sondages et quiz"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "description": "Kind",
                    "enum": [
                      "poll",
                      "quiz"
                    ]
                  },
                  "question": {
                    "type": "string",
                    "description": "Question"
                  },
                  "options": {
                    "type": "array",
                    "description": "Answers",
                    "items": {
                      "type": "string"
                    }
                  },
                  "correct": {
                    "type": "array",
                    "description": "Correct indexes",
                    "items": {
                      "type": "integer"
                    }
                  },
                  "allowMultiple": {
                    "type": "boolean",
                    "description": "Several answers allowed"
                  },
                  "phase": {
                    "type": "string",
                    "description": "When it runs",
                    "enum": [
                      "live",
                      "waiting",
                      "closing"
                    ]
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "pollId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Poll id"
            },
            "description": "Poll id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "delete_poll",
        "summary": "Supprimer un sondage",
        "description": "Deletes a poll and its votes, whatever its status.",
        "tags": [
          "Sondages et quiz"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "pollId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Poll id"
            },
            "description": "Poll id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/polls/{pollId}/open": {
      "post": {
        "operationId": "open_poll",
        "summary": "Lancer un sondage",
        "description": "Opens the vote to the participants (one poll open at a time, running live only).",
        "tags": [
          "Sondages et quiz"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "announceInChat": {
                    "type": "boolean",
                    "description": "System message in the chat, default true"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "pollId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Poll id"
            },
            "description": "Poll id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/polls/{pollId}/close": {
      "post": {
        "operationId": "close_poll",
        "summary": "Fermer un sondage",
        "description": "Closes the vote; results shown unless showResults is false.",
        "tags": [
          "Sondages et quiz"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "showResults": {
                    "type": "boolean",
                    "description": "Default true"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "pollId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Poll id"
            },
            "description": "Poll id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/polls/{pollId}/results": {
      "put": {
        "operationId": "show_poll_results",
        "summary": "Afficher ou cacher les résultats",
        "description": "Shows or hides the counts to the participants (and the correct answer of a quiz).",
        "tags": [
          "Sondages et quiz"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "shown": {
                    "type": "boolean",
                    "description": "Shown or hidden"
                  }
                },
                "required": [
                  "shown"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "pollId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Poll id"
            },
            "description": "Poll id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/polls/{pollId}/stage": {
      "put": {
        "operationId": "stage_poll",
        "summary": "Sondage à l’antenne",
        "description": "Shows the poll in the scene (poll slot, else bottom right) in the room, the broadcast and the recording; false removes it.",
        "tags": [
          "Sondages et quiz"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "shown": {
                    "type": "boolean",
                    "description": "On air or not"
                  }
                },
                "required": [
                  "shown"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "pollId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Poll id"
            },
            "description": "Poll id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/live/sessions/{id}/polls/{pollId}/band": {
      "post": {
        "operationId": "show_poll_band",
        "summary": "Bandeau des résultats",
        "description": "Shows a 12-second band on the scene with the leading answers (or the right answer and the success rate of a quiz).",
        "tags": [
          "Sondages et quiz"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "pollId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Poll id"
            },
            "description": "Poll id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/support/tickets": {
      "get": {
        "operationId": "list_support_tickets",
        "summary": "Lister les tickets",
        "description": "Tickets of one external user (externalId) or of the whole space (scope: \"space\", team dashboard), newest first.",
        "tags": [
          "Support"
        ],
        "parameters": [
          {
            "name": "externalId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Your id of the user (their tickets)"
            },
            "description": "Your id of the user (their tickets)"
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "All the tickets of the space",
              "enum": [
                "space"
              ]
            },
            "description": "All the tickets of the space"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Filter, default all",
              "enum": [
                "active",
                "open",
                "pending",
                "resolved",
                "closed",
                "all"
              ]
            },
            "description": "Filter, default all"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "500 max"
            },
            "description": "500 max"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "create_support_ticket",
        "summary": "Ouvrir un ticket",
        "description": "Opens a support ticket on behalf of a user of your platform. The team of the space is notified.",
        "tags": [
          "Support"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "user": {
                    "type": "object",
                    "description": "User of your platform: { externalId, name }",
                    "properties": {
                      "externalId": {
                        "type": "string",
                        "description": "Your stable id of the user, 200 chars max"
                      },
                      "name": {
                        "type": "string",
                        "description": "Display name, 60 chars max"
                      }
                    },
                    "required": [
                      "externalId"
                    ]
                  },
                  "subject": {
                    "type": "string",
                    "description": "Subject, 200 chars"
                  },
                  "content": {
                    "type": "string",
                    "description": "Plain text (blank line = new paragraph), or HTML when format is \"html\""
                  },
                  "format": {
                    "type": "string",
                    "description": "Format of content, default text",
                    "enum": [
                      "text",
                      "html"
                    ]
                  },
                  "priority": {
                    "type": "string",
                    "description": "Default normal",
                    "enum": [
                      "low",
                      "normal",
                      "high",
                      "urgent"
                    ]
                  },
                  "category": {
                    "type": "string",
                    "description": "Free category"
                  },
                  "attachments": {
                    "type": "array",
                    "description": "Attachments previously stored via POST /api/v1/attachments (kind, url, name, mimeType, sizeBytes)",
                    "items": {
                      "type": "object",
                      "description": "Attachment",
                      "properties": {
                        "kind": {
                          "type": "string",
                          "description": "Kind",
                          "enum": [
                            "image",
                            "file",
                            "audio",
                            "video"
                          ]
                        },
                        "url": {
                          "type": "string",
                          "description": "URL"
                        },
                        "name": {
                          "type": "string",
                          "description": "File name"
                        },
                        "mimeType": {
                          "type": "string",
                          "description": "MIME type"
                        },
                        "sizeBytes": {
                          "type": "number",
                          "description": "Size"
                        }
                      }
                    }
                  }
                },
                "required": [
                  "user",
                  "subject",
                  "content"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/support/tickets/{id}": {
      "get": {
        "operationId": "get_support_ticket",
        "summary": "Détail d’un ticket",
        "description": "A ticket with its messages (never the internal notes). Give externalId of the user, or scope: \"space\" for the team.",
        "tags": [
          "Support"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "externalId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Your id of the user"
            },
            "description": "Your id of the user"
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Team access to any ticket",
              "enum": [
                "space"
              ]
            },
            "description": "Team access to any ticket"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/support/tickets/{id}/messages": {
      "post": {
        "operationId": "reply_support_ticket",
        "summary": "Répondre à un ticket",
        "description": "Adds a message to a ticket, as the user ({ user }) or as the team ({ staff: {} } or { staff: { email } }): a staff reply puts the ticket in pending.",
        "tags": [
          "Support"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "user": {
                    "type": "object",
                    "description": "User of your platform: { externalId, name }",
                    "properties": {
                      "externalId": {
                        "type": "string",
                        "description": "Your stable id of the user, 200 chars max"
                      },
                      "name": {
                        "type": "string",
                        "description": "Display name, 60 chars max"
                      }
                    },
                    "required": [
                      "externalId"
                    ]
                  },
                  "staff": {
                    "type": "object",
                    "description": "Team reply: {} for the key creator, { email } for another team member",
                    "properties": {
                      "email": {
                        "type": "string",
                        "description": "E-mail"
                      }
                    }
                  },
                  "content": {
                    "type": "string",
                    "description": "Plain text (blank line = new paragraph), or HTML when format is \"html\""
                  },
                  "format": {
                    "type": "string",
                    "description": "Format of content, default text",
                    "enum": [
                      "text",
                      "html"
                    ]
                  },
                  "attachments": {
                    "type": "array",
                    "description": "Attachments previously stored via POST /api/v1/attachments (kind, url, name, mimeType, sizeBytes)",
                    "items": {
                      "type": "object",
                      "description": "Attachment",
                      "properties": {
                        "kind": {
                          "type": "string",
                          "description": "Kind",
                          "enum": [
                            "image",
                            "file",
                            "audio",
                            "video"
                          ]
                        },
                        "url": {
                          "type": "string",
                          "description": "URL"
                        },
                        "name": {
                          "type": "string",
                          "description": "File name"
                        },
                        "mimeType": {
                          "type": "string",
                          "description": "MIME type"
                        },
                        "sizeBytes": {
                          "type": "number",
                          "description": "Size"
                        }
                      }
                    }
                  }
                },
                "required": [
                  "content"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/support/tickets/{id}/status": {
      "post": {
        "operationId": "set_support_ticket_status",
        "summary": "Statut d’un ticket",
        "description": "Changes the status of a ticket: as the user (resolved or open), or as the team (any status, plus priority, assigneeEmail and the follow-up of the work). As the team, status alone is not required: sending only a follow-up field is enough.",
        "tags": [
          "Support"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "user": {
                    "type": "object",
                    "description": "As the user",
                    "properties": {
                      "externalId": {
                        "type": "string",
                        "description": "Your id of the user"
                      }
                    }
                  },
                  "staff": {
                    "type": "object",
                    "description": "As the team",
                    "properties": {
                      "email": {
                        "type": "string",
                        "description": "E-mail"
                      }
                    }
                  },
                  "status": {
                    "type": "string",
                    "description": "New status",
                    "enum": [
                      "open",
                      "pending",
                      "resolved",
                      "closed"
                    ]
                  },
                  "priority": {
                    "type": "string",
                    "description": "Team only",
                    "enum": [
                      "low",
                      "normal",
                      "high",
                      "urgent"
                    ]
                  },
                  "assigneeEmail": {
                    "description": "Team only, null to unassign",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Team only, null to unassign"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "takenAt": {
                    "description": "Team only. Taken in hand, ISO 8601 date and time, null to clear",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Team only. Taken in hand, ISO 8601 date and time, null to clear"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "dueAt": {
                    "description": "Team only. Estimated delivery, ISO 8601 date and time, null to clear",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Team only. Estimated delivery, ISO 8601 date and time, null to clear"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "deliveredAt": {
                    "description": "Team only. Actual delivery, ISO 8601 date and time, null to clear",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Team only. Actual delivery, ISO 8601 date and time, null to clear"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "estimateMinutes": {
                    "description": "Team only. Estimated time in minutes, null to clear",
                    "anyOf": [
                      {
                        "type": "number",
                        "description": "Team only. Estimated time in minutes, null to clear"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "spentMinutes": {
                    "description": "Team only. Time spent in minutes, null to clear",
                    "anyOf": [
                      {
                        "type": "number",
                        "description": "Team only. Time spent in minutes, null to clear"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/groups": {
      "get": {
        "operationId": "list_groups",
        "summary": "Lister les groupes",
        "description": "Groups of the space (classes, teams, cohorts… see groupLabels of get_space) with member counts and automatic rules.",
        "tags": [
          "Groupes"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "create_group",
        "summary": "Créer un groupe",
        "description": "Creates a group, manual or automatic (rule: level_min, streak_days, challenge_joined, challenge_completed, badge, course_completed).",
        "tags": [
          "Groupes"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name"
                  },
                  "slug": {
                    "type": "string",
                    "description": "Slug, derived from the name when absent"
                  },
                  "description": {
                    "type": "string",
                    "description": "Description"
                  },
                  "color": {
                    "type": "string",
                    "description": "#rrggbb"
                  },
                  "rule": {
                    "type": "object",
                    "description": "Automatic rule: { kind, level?, days?, challenge?, badge?, course? }"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/groups/{id}": {
      "get": {
        "operationId": "get_group",
        "summary": "Détail d’un groupe",
        "description": "One group (id or slug) with its members and their group role (leader or member).",
        "tags": [
          "Groupes"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Group id or slug"
            },
            "description": "Group id or slug"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "update_group",
        "summary": "Modifier un groupe",
        "description": "Changes name, slug, description, color or rule (null = manual group) of a group.",
        "tags": [
          "Groupes"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name"
                  },
                  "slug": {
                    "type": "string",
                    "description": "Slug"
                  },
                  "description": {
                    "description": "Description",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Description"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "color": {
                    "description": "#rrggbb",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "#rrggbb"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "rule": {
                    "description": "Rule, null for a manual group",
                    "anyOf": [
                      {
                        "type": "object",
                        "description": "Rule, null for a manual group"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Group id or slug"
            },
            "description": "Group id or slug"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "delete_group",
        "summary": "Supprimer un groupe",
        "description": "Deletes a group; the content addressed only to it becomes visible to the whole space.",
        "tags": [
          "Groupes"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Group id or slug"
            },
            "description": "Group id or slug"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/groups/{id}/members": {
      "post": {
        "operationId": "add_group_members",
        "summary": "Ajouter des membres à un groupe",
        "description": "Adds members of the space to a group (500 per call, idempotent), as member or leader.",
        "tags": [
          "Groupes"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "users": {
                    "type": "array",
                    "description": "User ids or ext:<externalId>",
                    "items": {
                      "type": "string"
                    }
                  },
                  "role": {
                    "type": "string",
                    "description": "Default member",
                    "enum": [
                      "member",
                      "leader"
                    ]
                  }
                },
                "required": [
                  "users"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Group id or slug"
            },
            "description": "Group id or slug"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/groups/{id}/members/{userId}": {
      "delete": {
        "operationId": "remove_group_member",
        "summary": "Retirer un membre d’un groupe",
        "description": "Removes one member from a group.",
        "tags": [
          "Groupes"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Group id or slug"
            },
            "description": "Group id or slug"
          },
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
            },
            "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/users/{id}/groups": {
      "get": {
        "operationId": "get_user_groups",
        "summary": "Groupes d’un membre",
        "description": "Groups of a user in the space, with their group role.",
        "tags": [
          "Groupes"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
            },
            "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "set_user_groups",
        "summary": "Remplacer les groupes d’un membre",
        "description": "Replaces the whole list of groups of a user (sync of classes from your platform).",
        "tags": [
          "Groupes"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "groups": {
                    "type": "array",
                    "description": "Group ids or slugs",
                    "items": {
                      "type": "string"
                    }
                  },
                  "role": {
                    "type": "string",
                    "description": "Default member",
                    "enum": [
                      "member",
                      "leader"
                    ]
                  }
                },
                "required": [
                  "groups"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
            },
            "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/groups/{id}/leaderboard": {
      "get": {
        "operationId": "get_group_leaderboard",
        "summary": "Classement d’un groupe",
        "description": "Members of a group ranked by XP.",
        "tags": [
          "Groupes"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Group id or slug"
            },
            "description": "Group id or slug"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "Page size"
            },
            "description": "Page size"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/groups/{id}/stats": {
      "get": {
        "operationId": "get_group_stats",
        "summary": "Suivi d’un groupe",
        "description": "Follow-up of every member of a group: course progress, lessons completed, posts, lives attended, XP over 30 days, last activity, plus a summary. Costs 5 rate-limit tokens.",
        "tags": [
          "Groupes"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Group id or slug"
            },
            "description": "Group id or slug"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/groups/{id}/documents": {
      "get": {
        "operationId": "list_group_documents",
        "summary": "Documents d’un groupe",
        "description": "Shared documents of a group, newest first.",
        "tags": [
          "Groupes"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Group id or slug"
            },
            "description": "Group id or slug"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "add_group_document",
        "summary": "Ajouter un document à un groupe",
        "description": "Adds a document (file stored via POST /api/v1/attachments, or any https link) to a group.",
        "tags": [
          "Groupes"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "description": "Title"
                  },
                  "url": {
                    "type": "string",
                    "description": "https URL"
                  },
                  "kind": {
                    "type": "string",
                    "description": "Kind, \"link\" for an external link"
                  },
                  "mimeType": {
                    "type": "string",
                    "description": "MIME type"
                  },
                  "sizeBytes": {
                    "type": "number",
                    "description": "Size"
                  }
                },
                "required": [
                  "title",
                  "url"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Group id or slug"
            },
            "description": "Group id or slug"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/groups/{id}/documents/{docId}": {
      "delete": {
        "operationId": "delete_group_document",
        "summary": "Supprimer un document d’un groupe",
        "description": "Deletes a document of a group.",
        "tags": [
          "Groupes"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Group id or slug"
            },
            "description": "Group id or slug"
          },
          {
            "name": "docId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Document id"
            },
            "description": "Document id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/courses": {
      "get": {
        "operationId": "list_courses",
        "summary": "Lister les cours",
        "description": "Published courses of the space (includeUnpublished for drafts too), with lesson counts and audience.",
        "tags": [
          "Cours"
        ],
        "parameters": [
          {
            "name": "includeUnpublished",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Drafts too"
            },
            "description": "Drafts too"
          },
          {
            "name": "group",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Only the content addressed to this group (id or slug)"
            },
            "description": "Only the content addressed to this group (id or slug)"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "create_course",
        "summary": "Créer un cours",
        "description": "Creates a course (draft by default). The author, when given, must be owner, admin or teacher.",
        "tags": [
          "Cours"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "description": "Title"
                  },
                  "slug": {
                    "type": "string",
                    "description": "Slug"
                  },
                  "description": {
                    "type": "string",
                    "description": "Description"
                  },
                  "coverImage": {
                    "type": "string",
                    "description": "https image"
                  },
                  "published": {
                    "type": "boolean",
                    "description": "Default false"
                  },
                  "groups": {
                    "type": "array",
                    "description": "Audience: group ids or slugs; empty = the whole space",
                    "items": {
                      "type": "string"
                    }
                  },
                  "author": {
                    "type": "object",
                    "description": "Who does it: { email } of a LearnFloo member, or { externalId, name } of a user of your platform (created and added as member on first use). Default: the creator of the API key",
                    "properties": {
                      "email": {
                        "type": "string",
                        "description": "E-mail of a LearnFloo member"
                      },
                      "externalId": {
                        "type": "string",
                        "description": "Your id of the user"
                      },
                      "name": {
                        "type": "string",
                        "description": "Display name"
                      }
                    }
                  }
                },
                "required": [
                  "title"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/courses/order": {
      "put": {
        "operationId": "reorder_courses",
        "summary": "Réordonner les cours",
        "description": "Sets the order of the courses page (also used by list_courses and the public site): the listed courses (ids or slugs) come first in that order, the others follow.",
        "tags": [
          "Cours"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "courseIds": {
                    "type": "array",
                    "description": "Course ids or slugs in the wanted order",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "required": [
                  "courseIds"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/courses/{id}": {
      "get": {
        "operationId": "get_course",
        "summary": "Structure d’un cours",
        "description": "A course (id or slug) with its modules and lessons; withContent adds the HTML of the lessons.",
        "tags": [
          "Cours"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Course id or slug"
            },
            "description": "Course id or slug"
          },
          {
            "name": "withContent",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Include the lesson content"
            },
            "description": "Include the lesson content"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "update_course",
        "summary": "Modifier un cours",
        "description": "Changes title, description, cover, published state or audience of a course.",
        "tags": [
          "Cours"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "description": "Title"
                  },
                  "description": {
                    "type": "string",
                    "description": "Description"
                  },
                  "coverImage": {
                    "type": "string",
                    "description": "https image"
                  },
                  "published": {
                    "type": "boolean",
                    "description": "Published"
                  },
                  "groups": {
                    "type": "array",
                    "description": "Audience: group ids or slugs; empty = the whole space",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Course id or slug"
            },
            "description": "Course id or slug"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "delete_course",
        "summary": "Supprimer un cours",
        "description": "Deletes a course with its modules, lessons and progress.",
        "tags": [
          "Cours"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Course id or slug"
            },
            "description": "Course id or slug"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/courses/{id}/modules": {
      "post": {
        "operationId": "create_module",
        "summary": "Créer un module",
        "description": "Adds a module (section) to a course.",
        "tags": [
          "Cours"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "description": "Title"
                  },
                  "description": {
                    "type": "string",
                    "description": "Description"
                  }
                },
                "required": [
                  "title"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Course id or slug"
            },
            "description": "Course id or slug"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/courses/{id}/lessons": {
      "post": {
        "operationId": "create_lesson",
        "summary": "Créer une leçon",
        "description": "Adds a lesson to a course, with rich content and an optional video (MP4, HLS, YouTube, Vimeo, or playbackUrl of a studio video).",
        "tags": [
          "Cours"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "description": "Title"
                  },
                  "content": {
                    "type": "string",
                    "description": "Plain text (blank line = new paragraph), or HTML when format is \"html\""
                  },
                  "format": {
                    "type": "string",
                    "description": "Format of content, default text",
                    "enum": [
                      "text",
                      "html"
                    ]
                  },
                  "moduleId": {
                    "type": "string",
                    "description": "Module id"
                  },
                  "videoUrl": {
                    "type": "string",
                    "description": "Video URL"
                  },
                  "videoDurationSec": {
                    "type": "number",
                    "description": "Video duration"
                  }
                },
                "required": [
                  "title",
                  "content"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Course id or slug"
            },
            "description": "Course id or slug"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/lessons/{id}": {
      "get": {
        "operationId": "get_lesson",
        "summary": "Détail d’une leçon",
        "description": "One lesson with its content.",
        "tags": [
          "Cours"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "update_lesson",
        "summary": "Modifier une leçon",
        "description": "Changes title, content, module, video or order of a lesson.",
        "tags": [
          "Cours"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "description": "Title"
                  },
                  "content": {
                    "type": "string",
                    "description": "Plain text (blank line = new paragraph), or HTML when format is \"html\""
                  },
                  "format": {
                    "type": "string",
                    "description": "Format of content, default text",
                    "enum": [
                      "text",
                      "html"
                    ]
                  },
                  "moduleId": {
                    "description": "Module id, null for none",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Module id, null for none"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "videoUrl": {
                    "description": "Video URL, null to remove",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Video URL, null to remove"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "videoDurationSec": {
                    "description": "Duration",
                    "anyOf": [
                      {
                        "type": "number",
                        "description": "Duration"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "order": {
                    "type": "number",
                    "description": "Position"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "delete_lesson",
        "summary": "Supprimer une leçon",
        "description": "Deletes a lesson.",
        "tags": [
          "Cours"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/courses/{id}/progress": {
      "get": {
        "operationId": "get_course_progress",
        "summary": "Progression dans un cours",
        "description": "Every learner who started the course (most advanced first), or the lesson-by-lesson detail of one learner (externalId or userId). Costs 5 rate-limit tokens.",
        "tags": [
          "Cours"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Course id or slug"
            },
            "description": "Course id or slug"
          },
          {
            "name": "externalId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Your id of one learner"
            },
            "description": "Your id of one learner"
          },
          {
            "name": "userId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Or the LearnFloo user id"
            },
            "description": "Or the LearnFloo user id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/lessons/{id}/complete": {
      "post": {
        "operationId": "complete_lesson",
        "summary": "Valider une leçon",
        "description": "Marks a lesson as completed for a learner, as if validated in LearnFloo (XP, quests, badges, webhook). Idempotent.",
        "tags": [
          "Cours"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "user": {
                    "type": "object",
                    "description": "User of your platform: { externalId, name }",
                    "properties": {
                      "externalId": {
                        "type": "string",
                        "description": "Your stable id of the user, 200 chars max"
                      },
                      "name": {
                        "type": "string",
                        "description": "Display name, 60 chars max"
                      }
                    },
                    "required": [
                      "externalId"
                    ]
                  },
                  "userId": {
                    "type": "string",
                    "description": "Or the LearnFloo user id"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/posts": {
      "get": {
        "operationId": "list_posts",
        "summary": "Lister les publications",
        "description": "Feed of the space, newest first, paginated; categories general, announcements, question, wins, resource.",
        "tags": [
          "Fil de la communauté"
        ],
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Filter by category",
              "enum": [
                "general",
                "announcements",
                "question",
                "wins",
                "resource"
              ]
            },
            "description": "Filter by category"
          },
          {
            "name": "group",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Only the content addressed to this group (id or slug)"
            },
            "description": "Only the content addressed to this group (id or slug)"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "Page size"
            },
            "description": "Page size"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Cursor of the next page (nextCursor of the previous call)"
            },
            "description": "Cursor of the next page (nextCursor of the previous call)"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "create_post",
        "summary": "Publier dans le fil",
        "description": "Creates a post in the feed (mentions, XP and notifications as in the app). pinned is for moderators.",
        "tags": [
          "Fil de la communauté"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "description": "Title (the question when the post carries a poll)"
                  },
                  "category": {
                    "type": "string",
                    "description": "Default general",
                    "enum": [
                      "general",
                      "announcements",
                      "question",
                      "wins",
                      "resource"
                    ]
                  },
                  "content": {
                    "type": "string",
                    "description": "Plain text (blank line = new paragraph), or HTML when format is \"html\""
                  },
                  "format": {
                    "type": "string",
                    "description": "Format of content, default text",
                    "enum": [
                      "text",
                      "html"
                    ]
                  },
                  "attachments": {
                    "type": "array",
                    "description": "Attachments previously stored via POST /api/v1/attachments (kind, url, name, mimeType, sizeBytes)",
                    "items": {
                      "type": "object",
                      "description": "Attachment",
                      "properties": {
                        "kind": {
                          "type": "string",
                          "description": "Kind",
                          "enum": [
                            "image",
                            "file",
                            "audio",
                            "video"
                          ]
                        },
                        "url": {
                          "type": "string",
                          "description": "URL"
                        },
                        "name": {
                          "type": "string",
                          "description": "File name"
                        },
                        "mimeType": {
                          "type": "string",
                          "description": "MIME type"
                        },
                        "sizeBytes": {
                          "type": "number",
                          "description": "Size"
                        }
                      }
                    }
                  },
                  "pinned": {
                    "type": "boolean",
                    "description": "Pin the post"
                  },
                  "groups": {
                    "type": "array",
                    "description": "Audience: group ids or slugs; empty = the whole space",
                    "items": {
                      "type": "string"
                    }
                  },
                  "poll": {
                    "type": "object",
                    "description": "Poll carried by the post, its question is the title",
                    "properties": {
                      "options": {
                        "type": "array",
                        "description": "2 to 6 choices, 100 chars each",
                        "items": {
                          "type": "string"
                        }
                      },
                      "allowMultiple": {
                        "type": "boolean",
                        "description": "Several choices allowed"
                      },
                      "resultsBeforeVote": {
                        "type": "boolean",
                        "description": "Counts visible before voting (default true)"
                      },
                      "closesAt": {
                        "type": "string",
                        "description": "End of the vote, ISO 8601 (default: open until closed)"
                      }
                    },
                    "required": [
                      "options"
                    ]
                  },
                  "author": {
                    "type": "object",
                    "description": "Who does it: { email } of a LearnFloo member, or { externalId, name } of a user of your platform (created and added as member on first use). Default: the creator of the API key",
                    "properties": {
                      "email": {
                        "type": "string",
                        "description": "E-mail of a LearnFloo member"
                      },
                      "externalId": {
                        "type": "string",
                        "description": "Your id of the user"
                      },
                      "name": {
                        "type": "string",
                        "description": "Display name"
                      }
                    }
                  }
                },
                "required": [
                  "content"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/posts/{id}": {
      "get": {
        "operationId": "get_post",
        "summary": "Détail d’une publication",
        "description": "A post with its comments (oldest first, parentId for replies).",
        "tags": [
          "Fil de la communauté"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "update_post",
        "summary": "Modifier une publication",
        "description": "Changes title, category, content, pinned state or audience of a post.",
        "tags": [
          "Fil de la communauté"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "description": "Title",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Title"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "category": {
                    "type": "string",
                    "description": "Category",
                    "enum": [
                      "general",
                      "announcements",
                      "question",
                      "wins",
                      "resource"
                    ]
                  },
                  "content": {
                    "type": "string",
                    "description": "Plain text (blank line = new paragraph), or HTML when format is \"html\""
                  },
                  "format": {
                    "type": "string",
                    "description": "Format of content, default text",
                    "enum": [
                      "text",
                      "html"
                    ]
                  },
                  "pinned": {
                    "type": "boolean",
                    "description": "Pinned"
                  },
                  "groups": {
                    "type": "array",
                    "description": "Audience: group ids or slugs; empty = the whole space",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "delete_post",
        "summary": "Supprimer une publication",
        "description": "Deletes a post with its comments and reactions.",
        "tags": [
          "Fil de la communauté"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/posts/{id}/poll/votes": {
      "post": {
        "operationId": "vote_poll",
        "summary": "Voter à un sondage du fil",
        "description": "Votes on a post's poll as a member (author, else the key's creator); optionIds [] withdraws the vote. Returns the counts.",
        "tags": [
          "Fil de la communauté"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "optionIds": {
                    "type": "array",
                    "description": "Ids of the chosen options (a, b, c…)",
                    "items": {
                      "type": "string"
                    }
                  },
                  "author": {
                    "type": "object",
                    "description": "Who does it: { email } of a LearnFloo member, or { externalId, name } of a user of your platform (created and added as member on first use). Default: the creator of the API key",
                    "properties": {
                      "email": {
                        "type": "string",
                        "description": "E-mail of a LearnFloo member"
                      },
                      "externalId": {
                        "type": "string",
                        "description": "Your id of the user"
                      },
                      "name": {
                        "type": "string",
                        "description": "Display name"
                      }
                    }
                  }
                },
                "required": [
                  "optionIds"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/posts/{id}/comments": {
      "post": {
        "operationId": "create_comment",
        "summary": "Commenter une publication",
        "description": "Adds a comment (or a reply with parentCommentId) to a post.",
        "tags": [
          "Fil de la communauté"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "content": {
                    "type": "string",
                    "description": "Plain text (blank line = new paragraph), or HTML when format is \"html\""
                  },
                  "format": {
                    "type": "string",
                    "description": "Format of content, default text",
                    "enum": [
                      "text",
                      "html"
                    ]
                  },
                  "parentCommentId": {
                    "type": "string",
                    "description": "Reply to this comment"
                  },
                  "attachments": {
                    "type": "array",
                    "description": "Attachments previously stored via POST /api/v1/attachments (kind, url, name, mimeType, sizeBytes)",
                    "items": {
                      "type": "object",
                      "description": "Attachment",
                      "properties": {
                        "kind": {
                          "type": "string",
                          "description": "Kind",
                          "enum": [
                            "image",
                            "file",
                            "audio",
                            "video"
                          ]
                        },
                        "url": {
                          "type": "string",
                          "description": "URL"
                        },
                        "name": {
                          "type": "string",
                          "description": "File name"
                        },
                        "mimeType": {
                          "type": "string",
                          "description": "MIME type"
                        },
                        "sizeBytes": {
                          "type": "number",
                          "description": "Size"
                        }
                      }
                    }
                  },
                  "author": {
                    "type": "object",
                    "description": "Who does it: { email } of a LearnFloo member, or { externalId, name } of a user of your platform (created and added as member on first use). Default: the creator of the API key",
                    "properties": {
                      "email": {
                        "type": "string",
                        "description": "E-mail of a LearnFloo member"
                      },
                      "externalId": {
                        "type": "string",
                        "description": "Your id of the user"
                      },
                      "name": {
                        "type": "string",
                        "description": "Display name"
                      }
                    }
                  }
                },
                "required": [
                  "content"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/comments/{id}": {
      "delete": {
        "operationId": "delete_comment",
        "summary": "Supprimer un commentaire",
        "description": "Deletes a comment and its replies.",
        "tags": [
          "Fil de la communauté"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/events": {
      "get": {
        "operationId": "list_events",
        "summary": "Lister les événements",
        "description": "Calendar events by start date (scheduled lives included with liveSessionId).",
        "tags": [
          "Calendrier"
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "ISO date"
            },
            "description": "ISO date"
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "ISO date"
            },
            "description": "ISO date"
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Filter by type",
              "enum": [
                "event",
                "workshop",
                "masterclass",
                "deadline",
                "qa",
                "live"
              ]
            },
            "description": "Filter by type"
          },
          {
            "name": "group",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Only the content addressed to this group (id or slug)"
            },
            "description": "Only the content addressed to this group (id or slug)"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "create_event",
        "summary": "Créer un événement",
        "description": "Creates a calendar event (lives are created with create_live_session): online, in person (address) or hybrid, with optional registration, seats, waiting list and a price paid on the space owner's Stripe account.",
        "tags": [
          "Calendrier"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "description": "Default event; broadcast = a studio video played for everyone at startsAt, like a live (endsAt computed from the video)",
                    "enum": [
                      "event",
                      "workshop",
                      "masterclass",
                      "deadline",
                      "qa",
                      "broadcast"
                    ]
                  },
                  "title": {
                    "type": "string",
                    "description": "Title"
                  },
                  "description": {
                    "type": "string",
                    "description": "Description"
                  },
                  "startsAt": {
                    "type": "string",
                    "description": "ISO date"
                  },
                  "endsAt": {
                    "type": "string",
                    "description": "ISO date"
                  },
                  "venue": {
                    "description": "Where it happens",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Where it happens",
                        "enum": [
                          "online",
                          "in_person",
                          "hybrid"
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "location": {
                    "type": "string",
                    "description": "Online link or room"
                  },
                  "address": {
                    "description": "Street address (in person or hybrid)",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Street address (in person or hybrid)"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "registration": {
                    "type": "boolean",
                    "description": "Members register (always on with a capacity or a price)"
                  },
                  "capacity": {
                    "description": "Seats, null for unlimited",
                    "anyOf": [
                      {
                        "type": "number",
                        "description": "Seats, null for unlimited",
                        "minimum": 1
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "waitlist": {
                    "type": "boolean",
                    "description": "Waiting list when full (default true)"
                  },
                  "priceCents": {
                    "description": "Price of a seat in cents of the space currency (min 50), null or 0 for free; needs the space Stripe account",
                    "anyOf": [
                      {
                        "type": "number",
                        "description": "Price of a seat in cents of the space currency (min 50), null or 0 for free; needs the space Stripe account",
                        "minimum": 0
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "broadcastVideoId": {
                    "type": "string",
                    "description": "Broadcast: id of a ready studio video of the space (list_videos)"
                  },
                  "broadcastPublic": {
                    "type": "boolean",
                    "description": "Broadcast: open to anyone with the link, account or not (then no registration nor price)"
                  },
                  "broadcastReplay": {
                    "type": "boolean",
                    "description": "Broadcast: watchable on demand after the end (default true)"
                  },
                  "groups": {
                    "type": "array",
                    "description": "Audience: group ids or slugs; empty = the whole space",
                    "items": {
                      "type": "string"
                    }
                  },
                  "author": {
                    "type": "object",
                    "description": "Who does it: { email } of a LearnFloo member, or { externalId, name } of a user of your platform (created and added as member on first use). Default: the creator of the API key",
                    "properties": {
                      "email": {
                        "type": "string",
                        "description": "E-mail of a LearnFloo member"
                      },
                      "externalId": {
                        "type": "string",
                        "description": "Your id of the user"
                      },
                      "name": {
                        "type": "string",
                        "description": "Display name"
                      }
                    }
                  }
                },
                "required": [
                  "title",
                  "startsAt"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/events/{id}": {
      "get": {
        "operationId": "get_event",
        "summary": "Détail d’un événement",
        "description": "One calendar event.",
        "tags": [
          "Calendrier"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "update_event",
        "summary": "Modifier un événement",
        "description": "Changes an event (an event linked to a live is changed with update_live_session).",
        "tags": [
          "Calendrier"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "description": "Type",
                    "enum": [
                      "event",
                      "workshop",
                      "masterclass",
                      "deadline",
                      "qa",
                      "broadcast"
                    ]
                  },
                  "title": {
                    "type": "string",
                    "description": "Title"
                  },
                  "description": {
                    "type": "string",
                    "description": "Description"
                  },
                  "startsAt": {
                    "type": "string",
                    "description": "ISO date"
                  },
                  "endsAt": {
                    "description": "ISO date, null to clear",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "ISO date, null to clear"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "venue": {
                    "description": "Where it happens",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Where it happens",
                        "enum": [
                          "online",
                          "in_person",
                          "hybrid"
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "location": {
                    "type": "string",
                    "description": "Online link or room"
                  },
                  "address": {
                    "description": "Street address (in person or hybrid)",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Street address (in person or hybrid)"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "registration": {
                    "type": "boolean",
                    "description": "Members register (always on with a capacity or a price)"
                  },
                  "capacity": {
                    "description": "Seats, null for unlimited",
                    "anyOf": [
                      {
                        "type": "number",
                        "description": "Seats, null for unlimited",
                        "minimum": 1
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "waitlist": {
                    "type": "boolean",
                    "description": "Waiting list when full (default true)"
                  },
                  "priceCents": {
                    "description": "Price of a seat in cents of the space currency (min 50), null or 0 for free; needs the space Stripe account",
                    "anyOf": [
                      {
                        "type": "number",
                        "description": "Price of a seat in cents of the space currency (min 50), null or 0 for free; needs the space Stripe account",
                        "minimum": 0
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "broadcastVideoId": {
                    "type": "string",
                    "description": "Broadcast: id of a ready studio video of the space (list_videos)"
                  },
                  "broadcastPublic": {
                    "type": "boolean",
                    "description": "Broadcast: open to anyone with the link, account or not (then no registration nor price)"
                  },
                  "broadcastReplay": {
                    "type": "boolean",
                    "description": "Broadcast: watchable on demand after the end (default true)"
                  },
                  "groups": {
                    "type": "array",
                    "description": "Audience: group ids or slugs; empty = the whole space",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "delete_event",
        "summary": "Supprimer un événement",
        "description": "Deletes a calendar event.",
        "tags": [
          "Calendrier"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/events/{id}/registrations": {
      "get": {
        "operationId": "list_event_registrations",
        "summary": "Inscrits à un événement",
        "description": "People registered to an event (registered, paying, waitlisted, oldest first) with payment and check-in.",
        "tags": [
          "Calendrier"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Only this status",
              "enum": [
                "registered",
                "pending_payment",
                "waitlisted",
                "cancelled",
                "refunded"
              ]
            },
            "description": "Only this status"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/events/{id}/registrations/{registrationId}": {
      "patch": {
        "operationId": "check_in_event_registration",
        "summary": "Pointer une présence",
        "description": "Marks a registered person present at an event (checkedIn false to undo).",
        "tags": [
          "Calendrier"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "checkedIn": {
                    "type": "boolean",
                    "description": "Present"
                  }
                },
                "required": [
                  "checkedIn"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "registrationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Registration id"
            },
            "description": "Registration id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/videos": {
      "get": {
        "operationId": "list_videos",
        "summary": "Lister les vidéos",
        "description": "Studio recordings and imported live replays, newest first, paginated.",
        "tags": [
          "Vidéos du studio"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Filter by status",
              "enum": [
                "uploading",
                "processing",
                "ready",
                "failed"
              ]
            },
            "description": "Filter by status"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "Page size"
            },
            "description": "Page size"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Cursor of the next page (nextCursor of the previous call)"
            },
            "description": "Cursor of the next page (nextCursor of the previous call)"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/videos/{id}": {
      "get": {
        "operationId": "get_video",
        "summary": "Détail d’une vidéo",
        "description": "One video with its playback URLs (ready videos only), duration, thumbnail, linked lesson or live.",
        "tags": [
          "Vidéos du studio"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "update_video",
        "summary": "Renommer une vidéo",
        "description": "Changes the title or description of a video.",
        "tags": [
          "Vidéos du studio"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "description": "Title"
                  },
                  "description": {
                    "type": "string",
                    "description": "Description"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "delete_video",
        "summary": "Supprimer une vidéo",
        "description": "Deletes a studio video or a live replay, with its files. A deleted replay leaves its live without replay.",
        "tags": [
          "Vidéos du studio"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/videos/{id}/subtitles": {
      "post": {
        "operationId": "generate_subtitles",
        "summary": "Générer les sous-titres d’une vidéo",
        "description": "Generates subtitles for a ready video with Gladia, in the spoken language (detected), added as a caption track. Billed per hour of video (max 2 h 15). Poll get_subtitles for the result.",
        "tags": [
          "Vidéos du studio"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "get": {
        "operationId": "get_subtitles",
        "summary": "État des sous-titres d’une vidéo",
        "description": "State of the latest subtitle job of a video: none, queued, transcribing, done (language, seconds billed) or failed (error).",
        "tags": [
          "Vidéos du studio"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/videos/{id}/publish-kit": {
      "post": {
        "operationId": "generate_publish_kit",
        "summary": "Préparer la publication YouTube d’une vidéo",
        "description": "Writes a YouTube publication kit for a ready video from its transcript: 5 titles with their angle, a description with timed chapters, a tagged link to the space and hashtags, 3 short extracts (30-60 s) and an announcement for the feed and e-mail. Billed as a publication kit (3 per month included). Poll get_publish_kit for the result.",
        "tags": [
          "Vidéos du studio"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "language": {
                    "type": "string",
                    "description": "Language of the kit (default fr)",
                    "enum": [
                      "fr",
                      "en",
                      "es"
                    ]
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "get": {
        "operationId": "get_publish_kit",
        "summary": "Kit de publication YouTube d’une vidéo",
        "description": "The latest YouTube publication kit of a video: status (running, ready, failed), titles, description ready to paste, chapters, shorts, announcement.",
        "tags": [
          "Vidéos du studio"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/channels": {
      "get": {
        "operationId": "list_channels",
        "summary": "Lister les chaînes",
        "description": "Channels of the space: studio videos played in a loop like a TV channel, the same image for everyone. With their programme, what is on air now and the page address.",
        "tags": [
          "Vidéos du studio"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "create_channel",
        "summary": "Créer une chaîne",
        "description": "Creates a channel that plays studio videos in a loop for everyone at the same moment. Each programme a viewer starts counts as one video play.",
        "tags": [
          "Vidéos du studio"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "description": "Name of the channel"
                  },
                  "slug": {
                    "type": "string",
                    "description": "Address: /<space>/chaine/<slug>; derived from the title when absent"
                  },
                  "description": {
                    "description": "Description, null to clear",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Description, null to clear"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "enabled": {
                    "type": "boolean",
                    "description": "On air (needs at least one video). Off: only staff see it"
                  },
                  "public": {
                    "type": "boolean",
                    "description": "Open to everyone, account or not (default true); false = active members of the space only"
                  },
                  "videos": {
                    "type": "array",
                    "description": "Programme: ids of ready studio videos (list_videos), in order; replaces the programme and starts the loop again from the first one",
                    "items": {
                      "type": "string"
                    }
                  },
                  "position": {
                    "type": "number",
                    "description": "Place in the space's list of channels, 1 = first (also served at /<space>/chaine)"
                  }
                },
                "required": [
                  "title"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/channels/{id}": {
      "get": {
        "operationId": "get_channel",
        "summary": "Voir une chaîne",
        "description": "A channel with its programme, what is on air now (onAir) and the next programmes with their start times (upNext).",
        "tags": [
          "Vidéos du studio"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Channel id or slug"
            },
            "description": "Channel id or slug"
          },
          {
            "name": "next",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "Number of upcoming programmes to list (default 10, max 50)"
            },
            "description": "Number of upcoming programmes to list (default 10, max 50)"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "update_channel",
        "summary": "Modifier une chaîne",
        "description": "Updates the given fields of a channel: name, address, access, on air or off, programme (videos, which restarts the loop), position in the list.",
        "tags": [
          "Vidéos du studio"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "description": "Name of the channel"
                  },
                  "slug": {
                    "type": "string",
                    "description": "Address: /<space>/chaine/<slug>; derived from the title when absent"
                  },
                  "description": {
                    "description": "Description, null to clear",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Description, null to clear"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "enabled": {
                    "type": "boolean",
                    "description": "On air (needs at least one video). Off: only staff see it"
                  },
                  "public": {
                    "type": "boolean",
                    "description": "Open to everyone, account or not (default true); false = active members of the space only"
                  },
                  "videos": {
                    "type": "array",
                    "description": "Programme: ids of ready studio videos (list_videos), in order; replaces the programme and starts the loop again from the first one",
                    "items": {
                      "type": "string"
                    }
                  },
                  "position": {
                    "type": "number",
                    "description": "Place in the space's list of channels, 1 = first (also served at /<space>/chaine)"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Channel id or slug"
            },
            "description": "Channel id or slug"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "delete_channel",
        "summary": "Supprimer une chaîne",
        "description": "Deletes a channel; its address stops working. The videos stay in the studio.",
        "tags": [
          "Vidéos du studio"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Channel id or slug"
            },
            "description": "Channel id or slug"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/media": {
      "get": {
        "operationId": "list_media",
        "summary": "Lister la médiathèque",
        "description": "Images, PDF, videos, embeds, stickers and sounds of the space used in scenes and the studio.",
        "tags": [
          "Médiathèque"
        ],
        "parameters": [
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Filter by kind",
              "enum": [
                "image",
                "pdf",
                "video",
                "embed",
                "sticker",
                "audio"
              ]
            },
            "description": "Filter by kind"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "Page size"
            },
            "description": "Page size"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Cursor of the next page (nextCursor of the previous call)"
            },
            "description": "Cursor of the next page (nextCursor of the previous call)"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "add_media",
        "summary": "Ajouter un média par URL",
        "description": "Adds an item to the media library from an https URL (image, pdf, video, embed of YouTube/Vimeo/Loom, sticker, audio), optionally in a folder (created when needed).",
        "tags": [
          "Médiathèque"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "description": "Kind",
                    "enum": [
                      "image",
                      "pdf",
                      "video",
                      "embed",
                      "sticker",
                      "audio"
                    ]
                  },
                  "url": {
                    "type": "string",
                    "description": "https URL"
                  },
                  "title": {
                    "type": "string",
                    "description": "Title"
                  },
                  "folder": {
                    "type": "string",
                    "description": "Folder id or name"
                  }
                },
                "required": [
                  "kind",
                  "url"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/media/folders": {
      "get": {
        "operationId": "list_media_folders",
        "summary": "Dossiers de la médiathèque",
        "description": "Folders of the media library.",
        "tags": [
          "Médiathèque"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "create_media_folder",
        "summary": "Créer un dossier",
        "description": "Creates a folder in the media library.",
        "tags": [
          "Médiathèque"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/media/{id}": {
      "get": {
        "operationId": "get_media",
        "summary": "Détail d’un média",
        "description": "One item of the media library.",
        "tags": [
          "Médiathèque"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "update_media",
        "summary": "Modifier un média",
        "description": "Changes the title or the folder (null for the root) of a media item.",
        "tags": [
          "Médiathèque"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "description": "Title"
                  },
                  "folder": {
                    "description": "Folder id or name, null for the root",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Folder id or name, null for the root"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "delete_media",
        "summary": "Supprimer un média",
        "description": "Deletes a media item (and its file when hosted by LearnFloo).",
        "tags": [
          "Médiathèque"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/media/folders/{id}": {
      "delete": {
        "operationId": "delete_media_folder",
        "summary": "Supprimer un dossier",
        "description": "Deletes a folder of the media library. Its media go back to the root, or are deleted too when deleteMedia is true.",
        "tags": [
          "Médiathèque"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Folder id or name"
            },
            "description": "Folder id or name"
          },
          {
            "name": "deleteMedia",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Also delete the media of the folder (default false)"
            },
            "description": "Also delete the media of the folder (default false)"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/webhooks/events": {
      "get": {
        "operationId": "list_webhook_events",
        "summary": "Événements de webhook",
        "description": "Catalogue of the webhook events: name, family, meaning and a sample data payload.",
        "tags": [
          "Webhooks"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/webhooks": {
      "get": {
        "operationId": "list_webhooks",
        "summary": "Lister les webhooks",
        "description": "Outgoing webhooks of the space with their events and delivery state.",
        "tags": [
          "Webhooks"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "create_webhook",
        "summary": "Créer un webhook",
        "description": "Subscribes an https URL to events ([\"*\"] for all), optionally limited to some courses or groups. The signing secret (and its Standard Webhooks form standardSecret) is returned once.",
        "tags": [
          "Webhooks"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "https URL"
                  },
                  "events": {
                    "type": "array",
                    "description": "Event names (see list_webhook_events), or [\"*\"]",
                    "items": {
                      "type": "string"
                    }
                  },
                  "filters": {
                    "type": "object",
                    "description": "Only for events carrying a course or groups: keep those of these courses / groups (other events pass). null removes the filters.",
                    "properties": {
                      "courseIds": {
                        "type": "array",
                        "description": "Course ids",
                        "items": {
                          "type": "string"
                        }
                      },
                      "groupIds": {
                        "type": "array",
                        "description": "Group ids",
                        "items": {
                          "type": "string"
                        }
                      }
                    }
                  },
                  "secret": {
                    "type": "string",
                    "description": "16 to 128 chars, generated when absent"
                  },
                  "description": {
                    "type": "string",
                    "description": "Description"
                  }
                },
                "required": [
                  "url",
                  "events"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/webhooks/{id}": {
      "get": {
        "operationId": "get_webhook",
        "summary": "Détail d’un webhook",
        "description": "One webhook.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "update_webhook",
        "summary": "Modifier un webhook",
        "description": "Changes url, events, filters, description or active state (active: true leaves the pause and resets the failure count).",
        "tags": [
          "Webhooks"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "https URL"
                  },
                  "events": {
                    "type": "array",
                    "description": "Event names",
                    "items": {
                      "type": "string"
                    }
                  },
                  "filters": {
                    "type": "object",
                    "description": "Only for events carrying a course or groups: keep those of these courses / groups (other events pass). null removes the filters.",
                    "properties": {
                      "courseIds": {
                        "type": "array",
                        "description": "Course ids",
                        "items": {
                          "type": "string"
                        }
                      },
                      "groupIds": {
                        "type": "array",
                        "description": "Group ids",
                        "items": {
                          "type": "string"
                        }
                      }
                    }
                  },
                  "description": {
                    "type": "string",
                    "description": "Description"
                  },
                  "active": {
                    "type": "boolean",
                    "description": "Active"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "delete_webhook",
        "summary": "Supprimer un webhook",
        "description": "Deletes a webhook.",
        "tags": [
          "Webhooks"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/webhooks/{id}/test": {
      "post": {
        "operationId": "test_webhook",
        "summary": "Tester un webhook",
        "description": "Sends a ping, or the sample of an event with \"test\": true, to a webhook (even paused).",
        "tags": [
          "Webhooks"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "event": {
                    "type": "string",
                    "description": "Event name whose sample is sent; ping when absent"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/webhooks/{id}/deliveries": {
      "get": {
        "operationId": "list_webhook_deliveries",
        "summary": "Journal d’un webhook",
        "description": "Delivery log of a webhook over 30 days (attempts, status, errors).",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "Page size"
            },
            "description": "Page size"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Only this status",
              "enum": [
                "pending",
                "success",
                "failed"
              ]
            },
            "description": "Only this status"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/webhooks/{id}/rotate-secret": {
      "post": {
        "operationId": "rotate_webhook_secret",
        "summary": "Changer le secret d’un webhook",
        "description": "Replaces the signing secret (returned once); the old one keeps signing for expiresInHours (default 24, 0 to 168) so the receiver can switch.",
        "tags": [
          "Webhooks"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "secret": {
                    "type": "string",
                    "description": "New secret, 16 to 128 chars, generated when absent"
                  },
                  "expiresInHours": {
                    "type": "number",
                    "description": "Hours the old secret still signs"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/webhooks/{id}/replay": {
      "post": {
        "operationId": "replay_webhook",
        "summary": "Rejouer des événements",
        "description": "Sends again the kept events (30 days) of a period to a webhook, after an outage: those it subscribes to, or the given events. At most 5000, 5 per second.",
        "tags": [
          "Webhooks"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "since": {
                    "type": "string",
                    "description": "ISO date"
                  },
                  "until": {
                    "type": "string",
                    "description": "ISO date, now when absent"
                  },
                  "events": {
                    "type": "array",
                    "description": "Only these events",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "required": [
                  "since"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/webhooks/{id}/deliveries/{deliveryId}/redeliver": {
      "post": {
        "operationId": "redeliver_webhook",
        "summary": "Renvoyer un envoi",
        "description": "Sends one delivery of the log again (same event id).",
        "tags": [
          "Webhooks"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          },
          {
            "name": "deliveryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Delivery id from list_webhook_deliveries"
            },
            "description": "Delivery id from list_webhook_deliveries"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/emails/campaigns": {
      "get": {
        "operationId": "list_email_campaigns",
        "summary": "Lister les campagnes e-mail",
        "description": "Campaigns of the space (drafts, scheduled, sent, failed) with their statistics: sent, delivered, opened, clicked, bounced, spam, unsubscribed. kind \"digest\" lists the automatic digests sent.",
        "tags": [
          "E-mails"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Only this status",
              "enum": [
                "draft",
                "scheduled",
                "sending",
                "sent",
                "cancelled",
                "failed"
              ]
            },
            "description": "Only this status"
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Only this kind",
              "enum": [
                "campaign",
                "digest"
              ]
            },
            "description": "Only this kind"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "create_email_campaign",
        "summary": "Créer une campagne e-mail",
        "description": "Creates a campaign as a draft (or from a reusable text). Show the content to the user and get their agreement before sending: pass send \"now\" or an ISO date to send it in the same call, or call send_email_campaign later.",
        "tags": [
          "E-mails"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "subject": {
                    "type": "string",
                    "description": "Subject, 200 chars; {{prenom}} and {{espace}} allowed"
                  },
                  "previewText": {
                    "type": "string",
                    "description": "Preview text shown by mail clients, 200 chars"
                  },
                  "body": {
                    "type": "string",
                    "description": "Body: plain text (blank line = new paragraph) or HTML when format is \"html\"; {{prenom}} and {{espace}} are replaced for each reader"
                  },
                  "format": {
                    "type": "string",
                    "description": "Format of body, default text",
                    "enum": [
                      "text",
                      "html"
                    ]
                  },
                  "segmentId": {
                    "type": "string",
                    "description": "Audience: a segment id; absent = every member"
                  },
                  "templateId": {
                    "type": "string",
                    "description": "Start from this reusable text (subject, preview and body when not given)"
                  },
                  "send": {
                    "type": "string",
                    "description": "\"now\", or an ISO date to schedule; absent = stays a draft"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/emails/campaigns/{id}": {
      "get": {
        "operationId": "get_email_campaign",
        "summary": "Lire une campagne",
        "description": "One campaign with its content, audience and statistics.",
        "tags": [
          "E-mails"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "update_email_campaign",
        "summary": "Modifier une campagne",
        "description": "Changes a draft (subject, preview text, body, audience). Scheduled or sent campaigns cannot be modified.",
        "tags": [
          "E-mails"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "subject": {
                    "type": "string",
                    "description": "Subject"
                  },
                  "previewText": {
                    "description": "Preview text, null to remove",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Preview text, null to remove"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "body": {
                    "type": "string",
                    "description": "Body: plain text (blank line = new paragraph) or HTML when format is \"html\"; {{prenom}} and {{espace}} are replaced for each reader"
                  },
                  "format": {
                    "type": "string",
                    "description": "Format of body, default text",
                    "enum": [
                      "text",
                      "html"
                    ]
                  },
                  "segmentId": {
                    "description": "Segment id, null = every member",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Segment id, null = every member"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "delete_email_campaign",
        "summary": "Supprimer une campagne",
        "description": "Deletes a campaign (a scheduled one is unscheduled; a campaign being sent cannot be deleted).",
        "tags": [
          "E-mails"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/emails/campaigns/{id}/preview": {
      "get": {
        "operationId": "preview_email_campaign",
        "summary": "Aperçu d’une campagne",
        "description": "The campaign as a reader will receive it (subject, HTML and text, frame and unsubscribe footer included), rendered with the key creator’s first name.",
        "tags": [
          "E-mails"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/emails/campaigns/{id}/send": {
      "post": {
        "operationId": "send_email_campaign",
        "summary": "Envoyer ou programmer une campagne",
        "description": "Sends a draft now, or schedules it (at: ISO date at least one minute ahead). Irreversible once sending: confirm with the user first. Costs 5 rate-limit tokens.",
        "tags": [
          "E-mails"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "at": {
                    "type": "string",
                    "description": "ISO date to schedule; absent = now"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/emails/campaigns/{id}/cancel": {
      "post": {
        "operationId": "cancel_email_campaign",
        "summary": "Annuler une campagne programmée",
        "description": "A scheduled campaign goes back to draft.",
        "tags": [
          "E-mails"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/emails/campaigns/{id}/test": {
      "post": {
        "operationId": "test_email_campaign",
        "summary": "S’envoyer une campagne en test",
        "description": "Sends the campaign to the creator of the API key only, subject prefixed with [Test].",
        "tags": [
          "E-mails"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/emails/segments": {
      "get": {
        "operationId": "list_email_segments",
        "summary": "Lister les segments",
        "description": "Saved audiences of the space (filters on roles, groups, level, seniority, activity, explicit members) with their last member count.",
        "tags": [
          "E-mails"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "create_email_segment",
        "summary": "Créer un segment",
        "description": "Saves an audience for campaigns and the digest.",
        "tags": [
          "E-mails"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name, 80 chars"
                  },
                  "description": {
                    "type": "string",
                    "description": "Description, 300 chars"
                  },
                  "filters": {
                    "type": "object",
                    "description": "Who: members matching every filter given (none = every active member). users are added to the result.",
                    "properties": {
                      "roles": {
                        "type": "array",
                        "description": "Member roles: owner, admin, moderator, teacher, contributor, member",
                        "items": {
                          "type": "string"
                        }
                      },
                      "groups": {
                        "type": "array",
                        "description": "In at least one of these groups (ids or slugs)",
                        "items": {
                          "type": "string"
                        }
                      },
                      "minLevel": {
                        "type": "number",
                        "description": "Minimum level"
                      },
                      "maxLevel": {
                        "type": "number",
                        "description": "Maximum level"
                      },
                      "joinedWithinDays": {
                        "type": "number",
                        "description": "Joined the space within the last N days"
                      },
                      "activeWithinDays": {
                        "type": "number",
                        "description": "Opened the app within the last N days"
                      },
                      "users": {
                        "type": "array",
                        "description": "Explicit members (user ids or \"ext:<externalId>\")",
                        "items": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "required": [
                  "name",
                  "filters"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/emails/segments/{id}": {
      "get": {
        "operationId": "get_email_segment",
        "summary": "Lire un segment",
        "description": "A segment with its member count computed now and a sample of names. Costs 3 tokens.",
        "tags": [
          "E-mails"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "update_email_segment",
        "summary": "Modifier un segment",
        "description": "Changes the name, description or filters of a segment.",
        "tags": [
          "E-mails"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name"
                  },
                  "description": {
                    "description": "Description, null to remove",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Description, null to remove"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "filters": {
                    "type": "object",
                    "description": "Who: members matching every filter given (none = every active member). users are added to the result.",
                    "properties": {
                      "roles": {
                        "type": "array",
                        "description": "Member roles: owner, admin, moderator, teacher, contributor, member",
                        "items": {
                          "type": "string"
                        }
                      },
                      "groups": {
                        "type": "array",
                        "description": "In at least one of these groups (ids or slugs)",
                        "items": {
                          "type": "string"
                        }
                      },
                      "minLevel": {
                        "type": "number",
                        "description": "Minimum level"
                      },
                      "maxLevel": {
                        "type": "number",
                        "description": "Maximum level"
                      },
                      "joinedWithinDays": {
                        "type": "number",
                        "description": "Joined the space within the last N days"
                      },
                      "activeWithinDays": {
                        "type": "number",
                        "description": "Opened the app within the last N days"
                      },
                      "users": {
                        "type": "array",
                        "description": "Explicit members (user ids or \"ext:<externalId>\")",
                        "items": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "delete_email_segment",
        "summary": "Supprimer un segment",
        "description": "Deletes a segment (campaigns keep their history).",
        "tags": [
          "E-mails"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/emails/segments/preview": {
      "post": {
        "operationId": "preview_email_segment",
        "summary": "Compter une audience",
        "description": "How many members a set of filters reaches now, without saving anything. Use it before creating a segment or sending. Costs 3 tokens.",
        "tags": [
          "E-mails"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "filters": {
                    "type": "object",
                    "description": "Who: members matching every filter given (none = every active member). users are added to the result.",
                    "properties": {
                      "roles": {
                        "type": "array",
                        "description": "Member roles: owner, admin, moderator, teacher, contributor, member",
                        "items": {
                          "type": "string"
                        }
                      },
                      "groups": {
                        "type": "array",
                        "description": "In at least one of these groups (ids or slugs)",
                        "items": {
                          "type": "string"
                        }
                      },
                      "minLevel": {
                        "type": "number",
                        "description": "Minimum level"
                      },
                      "maxLevel": {
                        "type": "number",
                        "description": "Maximum level"
                      },
                      "joinedWithinDays": {
                        "type": "number",
                        "description": "Joined the space within the last N days"
                      },
                      "activeWithinDays": {
                        "type": "number",
                        "description": "Opened the app within the last N days"
                      },
                      "users": {
                        "type": "array",
                        "description": "Explicit members (user ids or \"ext:<externalId>\")",
                        "items": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "required": [
                  "filters"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/emails/templates": {
      "get": {
        "operationId": "list_email_templates",
        "summary": "Lister les textes réutilisables",
        "description": "Reusable campaign texts of the space (subject, preview text, body).",
        "tags": [
          "E-mails"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "create_email_template",
        "summary": "Créer un texte réutilisable",
        "description": "Saves a campaign text to start future campaigns from (templateId of create_email_campaign).",
        "tags": [
          "E-mails"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name, 80 chars"
                  },
                  "subject": {
                    "type": "string",
                    "description": "Subject"
                  },
                  "previewText": {
                    "type": "string",
                    "description": "Preview text"
                  },
                  "body": {
                    "type": "string",
                    "description": "Body: plain text (blank line = new paragraph) or HTML when format is \"html\"; {{prenom}} and {{espace}} are replaced for each reader"
                  },
                  "format": {
                    "type": "string",
                    "description": "Format of body, default text",
                    "enum": [
                      "text",
                      "html"
                    ]
                  }
                },
                "required": [
                  "name",
                  "subject",
                  "body"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/emails/templates/{id}": {
      "patch": {
        "operationId": "update_email_template",
        "summary": "Modifier un texte réutilisable",
        "description": "Changes a reusable campaign text.",
        "tags": [
          "E-mails"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name"
                  },
                  "subject": {
                    "type": "string",
                    "description": "Subject"
                  },
                  "previewText": {
                    "description": "Preview text, null to remove",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Preview text, null to remove"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "body": {
                    "type": "string",
                    "description": "Body: plain text (blank line = new paragraph) or HTML when format is \"html\"; {{prenom}} and {{espace}} are replaced for each reader"
                  },
                  "format": {
                    "type": "string",
                    "description": "Format of body, default text",
                    "enum": [
                      "text",
                      "html"
                    ]
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "delete_email_template",
        "summary": "Supprimer un texte réutilisable",
        "description": "Deletes a reusable campaign text.",
        "tags": [
          "E-mails"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "LearnFloo id"
            },
            "description": "LearnFloo id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/emails/notifications": {
      "get": {
        "operationId": "list_email_notifications",
        "summary": "Lire les e-mails automatiques",
        "description": "The wording of the automatic e-mails the space sends (kind × language, e.g. live_invitation × fr), the saved text or the platform default, with the variables each kind accepts.",
        "tags": [
          "E-mails"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/emails/notifications/{kind}/{lang}/preview": {
      "get": {
        "operationId": "preview_email_notification",
        "summary": "Aperçu d’un e-mail automatique",
        "description": "Renders an automatic e-mail with sample values and the space branding: the saved text, or the subject and body given.",
        "tags": [
          "E-mails"
        ],
        "parameters": [
          {
            "name": "kind",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Kind",
              "enum": [
                "live_invitation"
              ]
            },
            "description": "Kind"
          },
          {
            "name": "lang",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Language",
              "enum": [
                "fr",
                "en",
                "es"
              ]
            },
            "description": "Language"
          },
          {
            "name": "subject",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Subject to try"
            },
            "description": "Subject to try"
          },
          {
            "name": "body",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Body to try (HTML)"
            },
            "description": "Body to try (HTML)"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/emails/notifications/{kind}/{lang}": {
      "put": {
        "operationId": "set_email_notification",
        "summary": "Modifier un e-mail automatique",
        "description": "Saves the space’s wording of an automatic e-mail for a kind and a language ({{variables}} listed by list_email_notifications).",
        "tags": [
          "E-mails"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "subject": {
                    "type": "string",
                    "description": "Subject"
                  },
                  "body": {
                    "type": "string",
                    "description": "Body: text or HTML when format is \"html\""
                  },
                  "format": {
                    "type": "string",
                    "description": "Format of body, default text",
                    "enum": [
                      "text",
                      "html"
                    ]
                  }
                },
                "required": [
                  "subject",
                  "body"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "kind",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Kind",
              "enum": [
                "live_invitation"
              ]
            },
            "description": "Kind"
          },
          {
            "name": "lang",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Language",
              "enum": [
                "fr",
                "en",
                "es"
              ]
            },
            "description": "Language"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "reset_email_notification",
        "summary": "Rétablir le texte par défaut",
        "description": "Back to the platform’s default wording for that kind and language.",
        "tags": [
          "E-mails"
        ],
        "x-access": "write",
        "parameters": [
          {
            "name": "kind",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Kind",
              "enum": [
                "live_invitation"
              ]
            },
            "description": "Kind"
          },
          {
            "name": "lang",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Language",
              "enum": [
                "fr",
                "en",
                "es"
              ]
            },
            "description": "Language"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/emails/digest": {
      "get": {
        "operationId": "get_email_digest",
        "summary": "Lire le récapitulatif automatique",
        "description": "Settings of the automatic digest (cadence, day, hour, time zone, sections, audience) with the last and next send.",
        "tags": [
          "E-mails"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "update_email_digest",
        "summary": "Régler le récapitulatif automatique",
        "description": "Partial update of the digest settings: enable it, change the cadence (daily, weekly, monthly), day, hour, time zone, sections, number of items, subject, intro, audience.",
        "tags": [
          "E-mails"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean",
                    "description": "On or off"
                  },
                  "cadence": {
                    "type": "string",
                    "description": "Cadence",
                    "enum": [
                      "daily",
                      "weekly",
                      "monthly"
                    ]
                  },
                  "weekday": {
                    "type": "number",
                    "description": "Weekly: 0 (Sunday) to 6"
                  },
                  "dayOfMonth": {
                    "type": "number",
                    "description": "Monthly: 1 to 28"
                  },
                  "hour": {
                    "type": "number",
                    "description": "Local hour, 0 to 23"
                  },
                  "timeZone": {
                    "type": "string",
                    "description": "IANA time zone, e.g. Europe/Paris"
                  },
                  "sections": {
                    "type": "object",
                    "description": "Sections included",
                    "properties": {
                      "posts": {
                        "type": "boolean",
                        "description": "Posts"
                      },
                      "courses": {
                        "type": "boolean",
                        "description": "New courses"
                      },
                      "lessons": {
                        "type": "boolean",
                        "description": "New lessons"
                      },
                      "lives": {
                        "type": "boolean",
                        "description": "Upcoming live sessions"
                      },
                      "events": {
                        "type": "boolean",
                        "description": "Upcoming events"
                      },
                      "challenges": {
                        "type": "boolean",
                        "description": "Challenges"
                      }
                    }
                  },
                  "maxItems": {
                    "type": "number",
                    "description": "Items per section, 1 to 20"
                  },
                  "subject": {
                    "description": "Subject with {{prenom}} / {{espace}}; null = platform text",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Subject with {{prenom}} / {{espace}}; null = platform text"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "intro": {
                    "description": "Introduction; null = platform text",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Introduction; null = platform text"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "onlyIfNews": {
                    "type": "boolean",
                    "description": "Skip the send when nothing new happened"
                  },
                  "segmentId": {
                    "description": "Audience segment id, null = every member",
                    "anyOf": [
                      {
                        "type": "string",
                        "description": "Audience segment id, null = every member"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/emails/digest/preview": {
      "get": {
        "operationId": "preview_email_digest",
        "summary": "Aperçu du récapitulatif",
        "description": "The digest as it would go out now (subject, HTML, and whether it would be empty). Costs 3 tokens.",
        "tags": [
          "E-mails"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/emails/digest/send": {
      "post": {
        "operationId": "send_email_digest",
        "summary": "Envoyer le récapitulatif maintenant",
        "description": "Sends the digest now: to the key creator only (test true), or to the whole audience. Costs 5 tokens.",
        "tags": [
          "E-mails"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "test": {
                    "type": "boolean",
                    "description": "true = to the creator of the API key only"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/emails/sender": {
      "get": {
        "operationId": "get_email_sender",
        "summary": "Lire le domaine d’envoi",
        "description": "What the space’s e-mails leave from: the paid option, the domain, its DNS records (DKIM, Return-Path) and their verification, deliverability counters, suspension.",
        "tags": [
          "E-mails"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "operationId": "add_email_sender_domain",
        "summary": "Ajouter un domaine d’envoi",
        "description": "Registers the space’s sending domain (the paid option must be enabled by the owner in the app) and returns the DNS records to add.",
        "tags": [
          "E-mails"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "domain": {
                    "type": "string",
                    "description": "Domain, e.g. out.monecole.fr"
                  },
                  "fromEmail": {
                    "type": "string",
                    "description": "Sending address on that domain"
                  },
                  "fromName": {
                    "type": "string",
                    "description": "Display name"
                  },
                  "replyTo": {
                    "type": "string",
                    "description": "Reply address (default: the key creator’s)"
                  }
                },
                "required": [
                  "domain",
                  "fromEmail",
                  "fromName"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "operationId": "update_email_sender",
        "summary": "Modifier l’expéditeur",
        "description": "Changes the display name, sending address (on the domain) or reply address.",
        "tags": [
          "E-mails"
        ],
        "x-access": "write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "fromEmail": {
                    "type": "string",
                    "description": "Sending address"
                  },
                  "fromName": {
                    "type": "string",
                    "description": "Display name"
                  },
                  "replyTo": {
                    "type": "string",
                    "description": "Reply address"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "operationId": "remove_email_sender_domain",
        "summary": "Retirer le domaine d’envoi",
        "description": "Removes the sending domain: e-mails go back to leaving via LearnFloo.",
        "tags": [
          "E-mails"
        ],
        "x-access": "write",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/emails/sender/check": {
      "post": {
        "operationId": "check_email_sender_domain",
        "summary": "Vérifier les DNS du domaine",
        "description": "Asks the mail provider to look the DKIM and Return-Path records up and records the result.",
        "tags": [
          "E-mails"
        ],
        "x-access": "write",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/emails/sender/test": {
      "post": {
        "operationId": "test_email_sender",
        "summary": "Tester l’expéditeur",
        "description": "Sends the key creator a test e-mail with the space’s current sender.",
        "tags": [
          "E-mails"
        ],
        "x-access": "write",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/users/{id}/email-preferences": {
      "get": {
        "operationId": "get_email_preferences",
        "summary": "Préférences e-mail d’un membre",
        "description": "Whether a member still receives the space’s bulk e-mails (campaigns, digest).",
        "tags": [
          "E-mails"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
            },
            "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "put": {
        "operationId": "set_email_preferences",
        "summary": "Régler les préférences e-mail d’un membre",
        "description": "Subscribes or unsubscribes a member from the space’s bulk e-mails (for example to mirror an opt-out recorded in your platform).",
        "tags": [
          "E-mails"
        ],
        "x-access": "write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "subscribed": {
                    "type": "boolean",
                    "description": "true to receive, false to opt out"
                  }
                },
                "required": [
                  "subscribed"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
            },
            "description": "User id, or \"ext:<externalId>\" for a user created by your platform"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/guide": {
      "get": {
        "operationId": "get_platform_guide",
        "summary": "Guide de LearnFloo : sommaire",
        "description": "The official LearnFloo platform guide (how LearnFloo works: space, members, feed, courses, live sessions, studio, media, e-mails, billing, API), the same whatever the space. Returns its modules and lesson ids; with q, only the lessons about that topic. Use it to explain or teach LearnFloo to the user, then read a lesson with get_platform_guide_lesson.",
        "tags": [
          "Guide LearnFloo"
        ],
        "parameters": [
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Language of the guide, default fr: answer the user in theirs",
              "enum": [
                "fr",
                "en",
                "es"
              ]
            },
            "description": "Language of the guide, default fr: answer the user in theirs"
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Search the lessons (title and text), e.g. \"replay\", \"facturation\""
            },
            "description": "Search the lessons (title and text), e.g. \"replay\", \"facturation\""
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/guide/lessons/{id}": {
      "get": {
        "operationId": "get_platform_guide_lesson",
        "summary": "Guide de LearnFloo : une leçon",
        "description": "One lesson of the LearnFloo platform guide, in Markdown. id comes from get_platform_guide (\"<module>-<lesson>\", e.g. \"2-3\").",
        "tags": [
          "Guide LearnFloo"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Lesson id, e.g. \"2-3\""
            },
            "description": "Lesson id, e.g. \"2-3\""
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Language of the guide, default fr: answer the user in theirs",
              "enum": [
                "fr",
                "en",
                "es"
              ]
            },
            "description": "Language of the guide, default fr: answer the user in theirs"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "oauth2": {
        "type": "oauth2",
        "description": "Authorization of a space by its owner or an admin on the LearnFloo consent page (scope read or full).",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://api.learnfloo.com/oauth/authorize",
            "tokenUrl": "https://api.learnfloo.com/oauth/token",
            "refreshUrl": "https://api.learnfloo.com/oauth/token",
            "scopes": {
              "read": "Read-only",
              "full": "Read and write"
            }
          }
        }
      },
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key of the space (lf_live_…), Space settings → API and MCP"
      }
    },
    "responses": {
      "Error": {
        "description": "Error",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string"
                }
              },
              "required": [
                "error"
              ]
            }
          }
        }
      }
    }
  },
  "security": [
    {
      "apiKey": []
    },
    {
      "oauth2": [
        "full"
      ]
    }
  ]
}