{
  "openapi": "3.1.0",
  "info": {
    "title": "Hapana API",
    "description": "The Hapana Member API. Member endpoints authenticate with a Firebase ID token (`Authorization: Bearer <firebase-id-token>`) plus the `X-Site-ID` header — the member signs in with your corporate’s Firebase tenant and passes that token directly. Lists return the Stripe-style envelope (`{object:\"list\",data,hasMore,nextCursor}`) with opaque cursor pagination, `?sort=` (prefix `-` for desc, allowlisted per endpoint), and `?expand[]=` for embedding related objects.",
    "version": "2026-09-01",
    "license": {
      "name": "Proprietary",
      "url": "https://hapana.com"
    }
  },
  "servers": [
    {
      "url": "https://api.hapana-dev.com",
      "description": "Development (default)"
    },
    {
      "url": "https://api.hapana-staging.com",
      "description": "Staging"
    },
    {
      "url": "https://api.hapana-app.com",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Member API",
      "description": "Member-facing endpoints (mobile app, kiosk, embed widget). Auth: `Authorization: Bearer <firebase-id-token>` + `X-Site-ID` header — the member signs in with your corporate’s Firebase tenant and passes the resulting Firebase ID token directly."
    }
  ],
  "paths": {
    "/public-api/v2/member/profile": {
      "get": {
        "tags": [
          "Member API"
        ],
        "summary": "Get member profile",
        "operationId": "get_member_profile",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Member profile."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "tags": [
          "Member API"
        ],
        "summary": "Update member profile",
        "operationId": "update_member_profile",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "firstName": {
                    "type": "string"
                  },
                  "lastName": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "phone": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "dateOfBirth": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated member profile."
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/public-api/v2/member/schedule": {
      "get": {
        "tags": [
          "Member API"
        ],
        "summary": "List upcoming sessions for the member",
        "operationId": "list_member_schedule",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "startDate",
            "in": "query",
            "description": "Start date (YYYY-MM-DD).",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "endDate",
            "in": "query",
            "description": "End date (YYYY-MM-DD).",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Max results (1–100).",
            "required": false,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Upcoming sessions."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/public-api/v2/member/schedule/{id}": {
      "get": {
        "tags": [
          "Member API"
        ],
        "summary": "Get a session from the member schedule",
        "operationId": "get_member_session",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "description": "Session id.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Session details."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/public-api/v2/member/bookings": {
      "post": {
        "tags": [
          "Member API"
        ],
        "summary": "Create a booking",
        "operationId": "create_member_booking",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sessionId": {
                    "type": "string"
                  },
                  "spotId": {
                    "type": "integer"
                  },
                  "notes": {
                    "type": "string"
                  }
                },
                "required": [
                  "sessionId"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Booking created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Booking"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "get": {
        "tags": [
          "Member API"
        ],
        "summary": "List the member's bookings",
        "operationId": "list_member_bookings",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by status (comma-separated).",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "startDate",
            "in": "query",
            "description": "Filter start date.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "endDate",
            "in": "query",
            "description": "Filter end date.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Max results.",
            "required": false,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Member bookings."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/public-api/v2/member/bookings/{id}": {
      "delete": {
        "tags": [
          "Member API"
        ],
        "summary": "Cancel a booking",
        "operationId": "cancel_member_booking",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "description": "Booking id.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Booking cancelled."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/public-api/v2/member/check-in": {
      "post": {
        "tags": [
          "Member API"
        ],
        "summary": "Self check-in at a site or into a session",
        "operationId": "member_checkin",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sessionId": {
                    "type": "string"
                  },
                  "locationId": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Check-in recorded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Checkin"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/public-api/v2/member/packages": {
      "get": {
        "tags": [
          "Member API"
        ],
        "summary": "List the member's purchased packages",
        "operationId": "list_member_packages",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Member packages."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/public-api/v2/member/packages/available": {
      "get": {
        "tags": [
          "Member API"
        ],
        "summary": "List packages available for purchase at the site",
        "operationId": "list_available_packages",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Available packages. Each has `promotional: true` when it is an intro/promotional offer."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/public-api/v2/member/packages/{id}": {
      "get": {
        "tags": [
          "Member API"
        ],
        "summary": "Get a purchased package",
        "operationId": "get_member_package",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "description": "Package id.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Package detail."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/public-api/v2/member/agreements": {
      "get": {
        "tags": [
          "Member API"
        ],
        "summary": "Get signed agreements for the member",
        "operationId": "get_member_agreements",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Signed policies, package agreements, and multi-signature agreements."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "tags": [
          "Member API"
        ],
        "summary": "Record a signed agreement (JSON text signature, or multipart package-waiver file)",
        "operationId": "sign_member_agreement",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Standalone agreement (application/json). For a package waiver, send multipart/form-data with a `signature` file part and `packageId` instead.",
                "properties": {
                  "agreementId": {
                    "type": "string"
                  },
                  "signature": {
                    "type": "string",
                    "description": "Text signature."
                  }
                },
                "required": [
                  "agreementId",
                  "signature"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Signature recorded (returns the signature id)."
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/public-api/v2/member/agreements/pending": {
      "get": {
        "tags": [
          "Member API"
        ],
        "summary": "List agreements awaiting the member’s signature",
        "operationId": "list_member_pending_agreements",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Pending agreements."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/public-api/v2/member/policies/pending": {
      "get": {
        "tags": [
          "Member API"
        ],
        "summary": "List policies the member still needs to accept",
        "operationId": "list_member_pending_policies",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Pending policies.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "type": "string",
                            "const": "policy"
                          },
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "policyRevisionId": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "The revision in force; send it back in displayedRevisions when accepting."
                          },
                          "revisionSha256": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/public-api/v2/member/policies/accept": {
      "post": {
        "tags": [
          "Member API"
        ],
        "summary": "Accept one or more site policies",
        "operationId": "accept_member_policies",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "policyIds": {
                    "type": "array",
                    "minItems": 1,
                    "items": {
                      "type": "string",
                      "minLength": 1
                    }
                  },
                  "displayedRevisions": {
                    "type": "array",
                    "maxItems": 50,
                    "description": "The revision of each policy the member was shown. A revision that is no longer the one in force is refused with 409 POLICY_VERSION_CHANGED. Without it the revision in force is recorded, except within 15 minutes of it replacing different text.",
                    "items": {
                      "type": "object",
                      "properties": {
                        "policyId": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "policyRevisionId": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "revisionSha256": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "minLength": 64,
                          "maxLength": 64
                        }
                      },
                      "required": [
                        "policyId",
                        "policyRevisionId"
                      ]
                    }
                  }
                },
                "required": [
                  "policyIds"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Policies accepted."
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/public-api/v2/member/memberships/{id}": {
      "get": {
        "tags": [
          "Member API"
        ],
        "summary": "Get membership details (incl. earliestCancelDate)",
        "operationId": "get_member_membership",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "description": "Membership (subscription) id.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Membership details."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/public-api/v2/member/memberships/{id}/cancel": {
      "post": {
        "tags": [
          "Member API"
        ],
        "summary": "Cancel a membership (immediate, or scheduled via cancelAt)",
        "operationId": "cancel_member_membership",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "description": "Membership (subscription) id.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string"
                  },
                  "cancelAt": {
                    "type": "string",
                    "description": "ISO date (YYYY-MM-DD); future = scheduled."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Cancellation recorded."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/public-api/v2/member/payments/methods": {
      "post": {
        "tags": [
          "Member API"
        ],
        "summary": "Initiate adding a payment method (returns Stripe SetupIntent)",
        "operationId": "initiate_payment_method",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "SetupIntent details: `setupIntentClientSecret` plus the site’s `publishableKey` to confirm it with Stripe.js / Elements."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "get": {
        "tags": [
          "Member API"
        ],
        "summary": "List payment methods",
        "operationId": "list_payment_methods",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Member payment methods."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/public-api/v2/member/payments/methods/{id}/complete": {
      "post": {
        "tags": [
          "Member API"
        ],
        "summary": "Complete payment method setup after Stripe confirmation",
        "operationId": "complete_payment_method",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "description": "Payment method id.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Payment method activated."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/public-api/v2/member/payments/methods/{id}": {
      "delete": {
        "tags": [
          "Member API"
        ],
        "summary": "Remove a payment method",
        "operationId": "delete_payment_method",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "description": "Payment method id.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Payment method removed."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/public-api/v2/member/payments/history": {
      "get": {
        "tags": [
          "Member API"
        ],
        "summary": "Get billing/payment history",
        "operationId": "get_payment_history",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by status (comma-separated).",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "startDate",
            "in": "query",
            "description": "Start date.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "endDate",
            "in": "query",
            "description": "End date.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Max results.",
            "required": false,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Payment history."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/public-api/v2/member/waitlist": {
      "get": {
        "tags": [
          "Member API"
        ],
        "summary": "List the member's waitlist entries",
        "operationId": "list_member_waitlist",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Active waitlist entries (with position)."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "tags": [
          "Member API"
        ],
        "summary": "Join a session waitlist",
        "operationId": "join_member_waitlist",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sessionId": {
                    "type": "string"
                  }
                },
                "required": [
                  "sessionId"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Waitlist entry created (with position)."
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/public-api/v2/member/waitlist/{id}": {
      "delete": {
        "tags": [
          "Member API"
        ],
        "summary": "Leave a waitlist",
        "operationId": "leave_member_waitlist",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "description": "Waitlist entry id.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Left the waitlist."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/public-api/v2/member/sites/{id}": {
      "get": {
        "tags": [
          "Member API"
        ],
        "summary": "Get member-safe site details",
        "operationId": "get_member_site",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Site-ID",
            "in": "header",
            "required": true,
            "description": "Site/location id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "description": "Site/location id.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Member-safe site details."
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Brand API key: `Authorization: Bearer hk_live_...` (or `hk_test_...` in test mode). Create and rotate keys in Control Center → API Integrations."
      },
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Firebase ID token for `/public-api/v2/member/*` — obtained by signing the member in with your corporate’s Firebase tenant. Passed as `Authorization: Bearer <firebase-id-token>` alongside the `X-Site-ID` header."
      }
    },
    "schemas": {
      "Client": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "client"
          },
          "id": {
            "type": "string"
          },
          "firstName": {
            "type": "string"
          },
          "lastName": {
            "type": "string"
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "phone": {
            "type": [
              "string",
              "null"
            ]
          },
          "dateOfBirth": {
            "type": [
              "string",
              "null"
            ]
          },
          "emergencyContact": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "name": {
                "type": "string"
              },
              "phone": {
                "type": "string"
              },
              "relationship": {
                "type": "string"
              }
            },
            "additionalProperties": false,
            "required": [
              "name",
              "phone",
              "relationship"
            ]
          },
          "membershipStatus": {
            "type": "string",
            "enum": [
              "active",
              "inactive",
              "suspended",
              "expired"
            ]
          },
          "clientStatus": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "suspended",
              "membership",
              "package",
              "intro",
              "alumni",
              "aggregator"
            ]
          },
          "barcode": {
            "type": [
              "string",
              "null"
            ]
          },
          "homeLocationId": {
            "type": [
              "string",
              "null"
            ]
          },
          "outstandingBalance": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "amount": {
                "type": "number"
              },
              "currency": {
                "type": "string"
              },
              "pastDueDays": {
                "type": "number"
              }
            },
            "additionalProperties": false,
            "required": [
              "amount",
              "currency",
              "pastDueDays"
            ]
          },
          "accessRights": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "allowedSiteIds": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "suspendedSiteIds": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            },
            "additionalProperties": false,
            "required": [
              "allowedSiteIds",
              "suspendedSiteIds"
            ]
          },
          "lastCheckInAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "notes": {
            "type": [
              "string",
              "null"
            ]
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {}
          },
          "createdAt": {
            "type": "string"
          },
          "updatedAt": {
            "type": "string"
          },
          "deletedAt": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "additionalProperties": false,
        "required": [
          "object",
          "id",
          "firstName",
          "lastName",
          "email",
          "phone",
          "dateOfBirth",
          "emergencyContact",
          "membershipStatus",
          "clientStatus",
          "barcode",
          "homeLocationId",
          "outstandingBalance",
          "accessRights",
          "lastCheckInAt",
          "notes",
          "metadata",
          "createdAt",
          "updatedAt",
          "deletedAt"
        ]
      },
      "Booking": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "booking"
          },
          "id": {
            "type": "string"
          },
          "clientId": {
            "type": "string"
          },
          "sessionId": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "confirmed",
              "waitlisted",
              "cancelled",
              "attended",
              "noshow"
            ]
          },
          "bookedAt": {
            "type": "string"
          },
          "cancelledAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "checkedInAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "spotNumber": {
            "type": [
              "number",
              "null"
            ]
          },
          "notes": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string"
          },
          "updatedAt": {
            "type": "string"
          },
          "deletedAt": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "additionalProperties": false,
        "required": [
          "object",
          "id",
          "clientId",
          "sessionId",
          "status",
          "bookedAt",
          "cancelledAt",
          "checkedInAt",
          "spotNumber",
          "notes",
          "createdAt",
          "updatedAt",
          "deletedAt"
        ]
      },
      "Session": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "session"
          },
          "id": {
            "type": "string"
          },
          "sessionTypeId": {
            "type": "string"
          },
          "locationId": {
            "type": "string"
          },
          "instructorId": {
            "type": [
              "string",
              "null"
            ]
          },
          "startTime": {
            "type": "string"
          },
          "endTime": {
            "type": "string"
          },
          "capacity": {
            "type": "number"
          },
          "bookedCount": {
            "type": "number"
          },
          "waitlistCount": {
            "type": "number"
          },
          "status": {
            "type": "string",
            "enum": [
              "scheduled",
              "in_progress",
              "completed",
              "cancelled"
            ]
          },
          "createdAt": {
            "type": "string"
          },
          "updatedAt": {
            "type": "string"
          },
          "deletedAt": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "additionalProperties": false,
        "required": [
          "object",
          "id",
          "sessionTypeId",
          "locationId",
          "instructorId",
          "startTime",
          "endTime",
          "capacity",
          "bookedCount",
          "waitlistCount",
          "status",
          "createdAt",
          "updatedAt",
          "deletedAt"
        ]
      },
      "Payment": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "payment"
          },
          "id": {
            "type": "string"
          },
          "clientId": {
            "type": "string"
          },
          "amount": {
            "type": "number"
          },
          "currency": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "succeeded",
              "failed",
              "refunded",
              "partially_refunded"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "invoiceId": {
            "type": "string"
          },
          "amountRefunded": {
            "type": "number"
          },
          "amountRefundable": {
            "type": "number"
          },
          "createdAt": {
            "type": "string"
          },
          "updatedAt": {
            "type": "string"
          }
        },
        "additionalProperties": false,
        "required": [
          "object",
          "id",
          "clientId",
          "amount",
          "currency",
          "status",
          "description",
          "invoiceId",
          "amountRefunded",
          "amountRefundable",
          "createdAt",
          "updatedAt"
        ]
      },
      "Package": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "package"
          },
          "id": {
            "type": "string"
          },
          "clientId": {
            "type": "string"
          },
          "packageTypeId": {
            "type": "string"
          },
          "creditsRemaining": {
            "type": "number"
          },
          "creditsUsed": {
            "type": "number"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "expired",
              "depleted",
              "cancelled"
            ]
          },
          "createdAt": {
            "type": "string"
          },
          "updatedAt": {
            "type": "string"
          },
          "deletedAt": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "additionalProperties": false,
        "required": [
          "object",
          "id",
          "clientId",
          "packageTypeId",
          "creditsRemaining",
          "creditsUsed",
          "expiresAt",
          "status",
          "createdAt",
          "updatedAt",
          "deletedAt"
        ]
      },
      "Checkin": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "checkin"
          },
          "id": {
            "type": "string"
          },
          "clientId": {
            "type": "string"
          },
          "locationId": {
            "type": "string"
          },
          "sessionId": {
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "general",
              "class"
            ]
          },
          "timestamp": {
            "type": "string"
          },
          "createdAt": {
            "type": "string"
          }
        },
        "additionalProperties": false,
        "required": [
          "object",
          "id",
          "clientId",
          "locationId",
          "sessionId",
          "type",
          "timestamp",
          "createdAt"
        ]
      },
      "Site": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "site"
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "shortName": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "inactive"
            ]
          },
          "isDigital": {
            "type": "boolean"
          },
          "timezone": {
            "type": "string"
          },
          "phone": {
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "website": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "object",
          "id",
          "name",
          "status",
          "createdAt",
          "updatedAt"
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string"
              },
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "param": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "hint": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "type",
              "code",
              "message"
            ]
          }
        },
        "required": [
          "error"
        ]
      }
    },
    "responses": {
      "Error": {
        "description": "Error response.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  }
}