{
  "openapi": "3.1.0",
  "info": {
    "title": "JLon Beauty Bar public catalog",
    "version": "1.0.0",
    "description": "Public, read-only data about JLon Beauty Bar. No endpoint creates, changes or cancels appointments; booking is done by a person at https://www.jlonbeautybar.com/direct-booking.",
    "contact": {
      "email": "team@jlonbeautybar.com"
    }
  },
  "servers": [
    {
      "url": "https://www.jlonbeautybar.com"
    }
  ],
  "paths": {
    "/services.json": {
      "get": {
        "operationId": "getServiceCatalog",
        "summary": "Service catalog with published prices, durations and booking deep links",
        "responses": {
          "200": {
            "description": "The service catalog",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "name",
                    "url",
                    "updated",
                    "currency",
                    "booking",
                    "groups",
                    "services"
                  ],
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "updated": {
                      "type": "string",
                      "format": "date"
                    },
                    "currency": {
                      "type": "string"
                    },
                    "notes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "booking": {
                      "type": "object",
                      "properties": {
                        "url": {
                          "type": "string",
                          "format": "uri"
                        },
                        "deepLink": {
                          "type": "string"
                        }
                      }
                    },
                    "groups": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "url": {
                            "type": "string",
                            "format": "uri"
                          }
                        }
                      }
                    },
                    "services": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "name",
                          "group",
                          "groupName",
                          "section",
                          "price",
                          "fromPrice",
                          "maxPrice",
                          "perHour",
                          "addOn",
                          "durationMinutes",
                          "tier",
                          "newClientOnly",
                          "newClientRule",
                          "url",
                          "bookingUrl"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Stable service id: the service parameter of the booking deep link."
                          },
                          "name": {
                            "type": "string"
                          },
                          "group": {
                            "type": "string",
                            "enum": [
                              "lashes",
                              "nails",
                              "hair",
                              "facials",
                              "waxing"
                            ]
                          },
                          "groupName": {
                            "type": "string"
                          },
                          "section": {
                            "type": "string"
                          },
                          "price": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Fixed price in USD, or null when the price is a from price or a range."
                          },
                          "fromPrice": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Starting price in USD, else null."
                          },
                          "maxPrice": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Top of a published range in USD, else null."
                          },
                          "perHour": {
                            "type": "boolean"
                          },
                          "addOn": {
                            "type": "boolean",
                            "description": "Added to another service, not booked on its own."
                          },
                          "durationMinutes": {
                            "type": "integer"
                          },
                          "tier": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "enum": [
                              "master",
                              "artist",
                              null
                            ],
                            "description": "Lash artist tier the price belongs to."
                          },
                          "newClientOnly": {
                            "type": "boolean"
                          },
                          "newClientRule": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "url": {
                            "type": "string",
                            "format": "uri"
                          },
                          "bookingUrl": {
                            "type": "string",
                            "format": "uri"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/availability.json": {
      "get": {
        "operationId": "getAvailability",
        "summary": "Open booking times for one service, by artist and date (read-only; never books)",
        "parameters": [
          {
            "name": "service",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 64
            },
            "description": "A service id from /services.json."
          },
          {
            "name": "date",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "First day, YYYY-MM-DD, from today up to 120 days ahead."
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 7,
              "default": 1
            }
          },
          {
            "name": "artist",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9-]{1,64}$"
            },
            "description": "Artist slug, or any."
          }
        ],
        "responses": {
          "200": {
            "description": "Open start times per artist per day",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "service",
                    "timezone",
                    "days",
                    "note"
                  ],
                  "properties": {
                    "service": {
                      "type": "object",
                      "required": [
                        "id",
                        "name",
                        "durationMin",
                        "priceCents",
                        "priceLabel",
                        "currency",
                        "bookingUrl"
                      ],
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "durationMin": {
                          "type": "integer"
                        },
                        "priceCents": {
                          "type": [
                            "integer",
                            "null"
                          ],
                          "description": "Server catalog price in cents, or null when the price is given on request."
                        },
                        "priceLabel": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Shown instead of a price when priceCents is null."
                        },
                        "currency": {
                          "type": "string"
                        },
                        "bookingUrl": {
                          "type": "string",
                          "format": "uri"
                        }
                      }
                    },
                    "timezone": {
                      "type": "string",
                      "description": "IANA time zone of the salon."
                    },
                    "days": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "date",
                          "weekday",
                          "artists"
                        ],
                        "properties": {
                          "date": {
                            "type": "string",
                            "format": "date",
                            "description": "Salon-local day."
                          },
                          "weekday": {
                            "type": "string",
                            "description": "Weekday of date in the salon."
                          },
                          "artists": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "required": [
                                "id",
                                "name",
                                "slug",
                                "slots",
                                "bookingUrl"
                              ],
                              "properties": {
                                "id": {
                                  "type": "string"
                                },
                                "name": {
                                  "type": "string",
                                  "description": "Public artist name."
                                },
                                "slug": {
                                  "type": "string",
                                  "description": "The artist parameter of the booking deep link."
                                },
                                "slots": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "required": [
                                      "start",
                                      "end",
                                      "startLocal",
                                      "endLocal"
                                    ],
                                    "properties": {
                                      "start": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "UTC instant."
                                      },
                                      "end": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "UTC instant."
                                      },
                                      "startLocal": {
                                        "type": "string",
                                        "description": "The same instant in the salon time zone, ISO 8601 with offset. Show this to people."
                                      },
                                      "endLocal": {
                                        "type": "string",
                                        "description": "The same instant in the salon time zone, ISO 8601 with offset."
                                      }
                                    }
                                  },
                                  "description": "Open start times; any of them can be taken at any moment."
                                },
                                "bookingUrl": {
                                  "type": "string",
                                  "format": "uri"
                                }
                              }
                            }
                          }
                        }
                      }
                    },
                    "note": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Unknown service or artist",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited; see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Availability is unavailable right now",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "operationId": "getLlmsTxt",
        "summary": "Salon summary, key facts and links for language models (llmstxt.org)",
        "responses": {
          "200": {
            "description": "Markdown text",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/llms-full.txt": {
      "get": {
        "operationId": "getLlmsFullTxt",
        "summary": "Full published menu, hours, policies, FAQs and academy courses in one file",
        "responses": {
          "200": {
            "description": "Markdown text",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  }
}
