{
  "openapi": "3.1.0",
  "info": {
    "title": "Dispolà",
    "version": "1.0.0",
    "description": "Les places dispo aujourd'hui, demain et cette semaine chez les pros du Grand Montréal, de Québec, Sherbrooke et Gatineau. Lecture seule : la demande elle-même se fait par la personne, sur le formulaire ou par texto, car c'est elle qui consent aux textos. Mode d'emploi : https://dispola.ca/llms.txt. Serveur MCP (mêmes places, pour Claude, ChatGPT ou tout client MCP) : https://dispola.ca/mcp"
  },
  "servers": [
    {
      "url": "https://dispola.ca"
    }
  ],
  "paths": {
    "/api/places": {
      "get": {
        "operationId": "listerPlaces",
        "summary": "Places libres",
        "parameters": [
          {
            "name": "city",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "montreal",
                "quebec",
                "sherbrooke",
                "gatineau",
                "rive-nord",
                "rive-sud",
                "all"
              ],
              "default": "montreal"
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "coiffure",
                "ongles",
                "cils",
                "sourcils",
                "esthetique",
                "massotherapie",
                "tatouage",
                "physiotherapie",
                "osteopathie",
                "kinesiologie",
                "therapie_sport",
                "chiropratique",
                "acupuncture"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Les places libres.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "city": {
                      "type": "string"
                    },
                    "category": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "checked_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "places": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "type",
                          "city",
                          "starts_at",
                          "ends_at",
                          "services",
                          "pro",
                          "booking_url"
                        ],
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "reseau",
                              "clinique"
                            ],
                            "description": "reseau : un.e pro du réseau Dispolà, la demande se fait sur Dispolà. clinique : une clinique dont la page de réservation en ligne est publique, la personne y réserve elle-même."
                          },
                          "city": {
                            "type": "string",
                            "enum": [
                              "montreal",
                              "quebec",
                              "sherbrooke",
                              "gatineau",
                              "rive-nord",
                              "rive-sud"
                            ]
                          },
                          "starts_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "ends_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "services": {
                            "type": "array",
                            "description": "Les services qui entrent encore dans la plage, chacun à sa première heure possible.",
                            "items": {
                              "type": "object",
                              "properties": {
                                "service": {
                                  "type": "string",
                                  "description": "Code du service, par exemple ongles.gel (liste dans /llms.txt)."
                                },
                                "category": {
                                  "type": "string",
                                  "enum": [
                                    "coiffure",
                                    "ongles",
                                    "cils",
                                    "sourcils",
                                    "esthetique",
                                    "massotherapie",
                                    "tatouage",
                                    "physiotherapie",
                                    "osteopathie",
                                    "kinesiologie",
                                    "therapie_sport",
                                    "chiropratique",
                                    "acupuncture"
                                  ]
                                },
                                "label": {
                                  "type": "object",
                                  "properties": {
                                    "fr": {
                                      "type": "string"
                                    },
                                    "en": {
                                      "type": "string"
                                    }
                                  }
                                },
                                "duration_min": {
                                  "type": "integer"
                                },
                                "starts_at": {
                                  "type": "string",
                                  "format": "date-time"
                                },
                                "price_cad": {
                                  "type": [
                                    "number",
                                    "null"
                                  ]
                                }
                              }
                            }
                          },
                          "neighborhood": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "pro": {
                            "type": "object",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "url": {
                                "type": "string",
                                "format": "uri"
                              }
                            }
                          },
                          "booking_url": {
                            "type": "string",
                            "format": "uri",
                            "description": "reseau : ajouter &service=<code> pour choisir le service."
                          },
                          "verified_at": {
                            "type": "string",
                            "description": "clinique seulement : quand la place a été vue libre."
                          }
                        }
                      }
                    },
                    "sur_demande": {
                      "type": "array",
                      "description": "Avec une catégorie : des commerces sans réservation en ligne, avec des moments estimés selon leurs heures d'ouverture, de demain à dans 4 jours. Ce ne sont pas des places : la personne ouvre request_url, coche 2 ou 3 heures et entre elle-même son cellulaire ; Dispolà appelle le commerce et lui texte l'heure confirmée. Absent s'il n'y en a aucun.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "enum": [
                              "sur_demande"
                            ]
                          },
                          "name": {
                            "type": "string"
                          },
                          "city": {
                            "type": "string"
                          },
                          "neighborhood": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "a_confirmer": {
                            "type": "boolean",
                            "enum": [
                              true
                            ]
                          },
                          "moments": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "moment": {
                                  "type": "string",
                                  "description": "Moment estimé, à confirmer par le commerce."
                                },
                                "label": {
                                  "type": "object",
                                  "properties": {
                                    "fr": {
                                      "type": "string"
                                    },
                                    "en": {
                                      "type": "string"
                                    }
                                  }
                                }
                              }
                            }
                          },
                          "request_url": {
                            "type": "string",
                            "format": "uri"
                          }
                        }
                      }
                    },
                    "waitlist": {
                      "type": "object",
                      "description": "Aucune place qui convient : la personne remplit elle-même le formulaire d'alerte texto.",
                      "properties": {
                        "request_url": {
                          "type": "string",
                          "format": "uri"
                        },
                        "plages": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "description": "AAAA-MM-JJ:jour, :am, :pm ou :soir (heure de Montréal)."
                          }
                        }
                      }
                    },
                    "texto": {
                      "type": "string",
                      "description": "Numéro où texter une demande."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "city ou category inconnue.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}