{
 "openapi": "3.1.0",
 "info": {
  "title": "Blume Aesthetics Public API",
  "version": "1.0.0",
  "summary": "Read-only facts about Blume Aesthetics, a cosmetic clinic in Perth, Western Australia.",
  "description": "Clinic locations, phone numbers, opening hours, booking links and the list of treatment and concern pages on blumeaesthetics.com. No authentication. Read-only. Prices are not published and are not available here. Every page is also available as Markdown by sending Accept: text/markdown to the page URL. Rate limit: 60 requests per minute per client IP, counted per serving instance (best effort), announced in the RateLimit and RateLimit-Policy response headers.",
  "contact": {
   "name": "Blume Aesthetics",
   "email": "info@blumeaesthetics.com",
   "url": "https://blumeaesthetics.com/contact/"
  }
 },
 "servers": [
  {
   "url": "https://blumeaesthetics.com"
  }
 ],
 "externalDocs": {
  "description": "Developer documentation",
  "url": "https://blumeaesthetics.com/developers/"
 },
 "security": [],
 "paths": {
  "/api/v1/clinics/": {
   "get": {
    "operationId": "listClinics",
    "summary": "List Blume Aesthetics clinics",
    "description": "Returns both Blume Aesthetics clinics (Mount Lawley and Jindalee in Perth) with address, phone, email, map link, online booking link and, where published, opening hours.",
    "responses": {
     "200": {
      "description": "The clinics.",
      "headers": {
       "RateLimit": {
        "$ref": "#/components/headers/RateLimit"
       },
       "RateLimit-Policy": {
        "$ref": "#/components/headers/RateLimitPolicy"
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ClinicList"
        }
       }
      }
     },
     "404": {
      "description": "No resource at this address. The body explains what to do next.",
      "headers": {
       "RateLimit": {
        "$ref": "#/components/headers/RateLimit"
       },
       "RateLimit-Policy": {
        "$ref": "#/components/headers/RateLimitPolicy"
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit reached. Wait the number of seconds in Retry-After.",
      "headers": {
       "RateLimit": {
        "$ref": "#/components/headers/RateLimit"
       },
       "RateLimit-Policy": {
        "$ref": "#/components/headers/RateLimitPolicy"
       },
       "Retry-After": {
        "$ref": "#/components/headers/RetryAfter"
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/treatments/": {
   "get": {
    "operationId": "listTreatments",
    "summary": "List treatment and concern pages",
    "description": "Returns every public page on blumeaesthetics.com with its name, kind, web address, Markdown address and the page's own short description. Filter with kind.",
    "parameters": [
     {
      "name": "kind",
      "in": "query",
      "required": false,
      "description": "Only return pages of this kind.",
      "schema": {
       "type": "string",
       "enum": [
        "treatment",
        "concern",
        "location",
        "page"
       ]
      }
     }
    ],
    "responses": {
     "200": {
      "description": "The pages.",
      "headers": {
       "RateLimit": {
        "$ref": "#/components/headers/RateLimit"
       },
       "RateLimit-Policy": {
        "$ref": "#/components/headers/RateLimitPolicy"
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/TreatmentList"
        }
       }
      }
     },
     "404": {
      "description": "No resource at this address. The body explains what to do next.",
      "headers": {
       "RateLimit": {
        "$ref": "#/components/headers/RateLimit"
       },
       "RateLimit-Policy": {
        "$ref": "#/components/headers/RateLimitPolicy"
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit reached. Wait the number of seconds in Retry-After.",
      "headers": {
       "RateLimit": {
        "$ref": "#/components/headers/RateLimit"
       },
       "RateLimit-Policy": {
        "$ref": "#/components/headers/RateLimitPolicy"
       },
       "Retry-After": {
        "$ref": "#/components/headers/RetryAfter"
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "400": {
      "description": "The kind value is not one of the allowed values.",
      "headers": {
       "RateLimit": {
        "$ref": "#/components/headers/RateLimit"
       },
       "RateLimit-Policy": {
        "$ref": "#/components/headers/RateLimitPolicy"
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/treatments/{slug}/": {
   "get": {
    "operationId": "getTreatment",
    "summary": "Get one treatment or concern page",
    "description": "Returns one page by its slug, the last part of its web address (for example concern-crows-feet).",
    "parameters": [
     {
      "name": "slug",
      "in": "path",
      "required": true,
      "description": "Page slug: lowercase letters, numbers and hyphens.",
      "schema": {
       "type": "string",
       "pattern": "^[a-z0-9-]{1,80}$"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "The page.",
      "headers": {
       "RateLimit": {
        "$ref": "#/components/headers/RateLimit"
       },
       "RateLimit-Policy": {
        "$ref": "#/components/headers/RateLimitPolicy"
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/TreatmentItem"
        }
       }
      }
     },
     "404": {
      "description": "No resource at this address. The body explains what to do next.",
      "headers": {
       "RateLimit": {
        "$ref": "#/components/headers/RateLimit"
       },
       "RateLimit-Policy": {
        "$ref": "#/components/headers/RateLimitPolicy"
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit reached. Wait the number of seconds in Retry-After.",
      "headers": {
       "RateLimit": {
        "$ref": "#/components/headers/RateLimit"
       },
       "RateLimit-Policy": {
        "$ref": "#/components/headers/RateLimitPolicy"
       },
       "Retry-After": {
        "$ref": "#/components/headers/RetryAfter"
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  }
 },
 "components": {
  "headers": {
   "RateLimit": {
    "description": "Remaining requests (r) and seconds until the window resets (t), per the IETF RateLimit header fields draft.",
    "schema": {
     "type": "string",
     "examples": [
      "\"default\";r=59;t=60"
     ]
    }
   },
   "RateLimitPolicy": {
    "description": "The quota (q) per window (w, seconds).",
    "schema": {
     "type": "string",
     "examples": [
      "\"default\";q=60;w=60"
     ]
    }
   },
   "RetryAfter": {
    "description": "Seconds to wait before retrying.",
    "schema": {
     "type": "integer",
     "minimum": 1
    }
   }
  },
  "schemas": {
   "Address": {
    "type": "object",
    "required": [
     "streetAddress",
     "addressLocality",
     "addressRegion",
     "postalCode",
     "addressCountry"
    ],
    "properties": {
     "streetAddress": {
      "type": "string"
     },
     "addressLocality": {
      "type": "string"
     },
     "addressRegion": {
      "type": "string"
     },
     "postalCode": {
      "type": "string"
     },
     "addressCountry": {
      "type": "string",
      "description": "ISO 3166-1 alpha-2 country code."
     }
    }
   },
   "OpeningHours": {
    "type": "object",
    "required": [
     "days",
     "opens",
     "closes"
    ],
    "properties": {
     "days": {
      "type": "array",
      "items": {
       "type": "string"
      },
      "description": "Day names, for example Monday."
     },
     "opens": {
      "type": "string",
      "description": "Local time, 24-hour HH:MM (Perth, UTC+8)."
     },
     "closes": {
      "type": "string",
      "description": "Local time, 24-hour HH:MM (Perth, UTC+8)."
     }
    }
   },
   "Clinic": {
    "type": "object",
    "required": [
     "id",
     "name",
     "url",
     "telephone",
     "email",
     "address"
    ],
    "properties": {
     "id": {
      "type": "string",
      "description": "Stable clinic identifier, for example mount-lawley."
     },
     "name": {
      "type": "string"
     },
     "url": {
      "type": "string",
      "format": "uri"
     },
     "telephone": {
      "type": "string",
      "description": "E.164 phone number."
     },
     "email": {
      "type": "string",
      "format": "email"
     },
     "address": {
      "$ref": "#/components/schemas/Address"
     },
     "map_url": {
      "type": "string",
      "format": "uri"
     },
     "booking_url": {
      "type": "string",
      "format": "uri",
      "description": "Online booking calendar for this clinic. Send people here to book."
     },
     "opening_hours": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/OpeningHours"
      },
      "description": "Present only where the site publishes hours."
     }
    }
   },
   "ClinicList": {
    "type": "object",
    "required": [
     "clinics"
    ],
    "properties": {
     "clinics": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/Clinic"
      }
     }
    }
   },
   "Treatment": {
    "type": "object",
    "required": [
     "slug",
     "name",
     "kind",
     "url",
     "markdown_url"
    ],
    "properties": {
     "slug": {
      "type": "string"
     },
     "name": {
      "type": "string",
      "description": "The page heading."
     },
     "kind": {
      "type": "string",
      "enum": [
       "treatment",
       "concern",
       "location",
       "page"
      ]
     },
     "url": {
      "type": "string",
      "format": "uri"
     },
     "markdown_url": {
      "type": "string",
      "format": "uri"
     },
     "description": {
      "type": "string",
      "description": "The page's own short description."
     }
    }
   },
   "TreatmentList": {
    "type": "object",
    "required": [
     "treatments"
    ],
    "properties": {
     "treatments": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/Treatment"
      }
     }
    }
   },
   "TreatmentItem": {
    "type": "object",
    "required": [
     "treatment"
    ],
    "properties": {
     "treatment": {
      "$ref": "#/components/schemas/Treatment"
     }
    }
   },
   "Error": {
    "type": "object",
    "required": [
     "error"
    ],
    "properties": {
     "error": {
      "type": "object",
      "required": [
       "code",
       "message",
       "hint",
       "docs"
      ],
      "properties": {
       "code": {
        "type": "string",
        "enum": [
         "not_found",
         "method_not_allowed",
         "rate_limited",
         "bad_request"
        ]
       },
       "message": {
        "type": "string",
        "description": "What went wrong."
       },
       "hint": {
        "type": "string",
        "description": "How to fix the request."
       },
       "docs": {
        "type": "string",
        "format": "uri"
       }
      }
     }
    }
   }
  }
 }
}
