{
  "openapi": "3.1.0",
  "info": {
    "title": "FeatShare Public API",
    "version": "1.0.0",
    "description": "REST API for integrating with a FeatShare business: members, leads, schedule & bookings, memberships, messages, tasks and reports.\n\n**Authentication** — every request (except `/v1/health` and `/v1/openapi.json`) needs an API key created in the app under Settings → API:\n`Authorization: Bearer fs_live_...` (or the `X-FeatShare-Key` header).\nKeys are scoped; `fs_test_...` keys run the same pipeline in dry-run mode.\n\n**Rate limits** — per-key burst plus per-business daily/monthly quotas; every response carries `X-RateLimit-*` headers, breaches return `429` with `Retry-After`.\n\n**Idempotency** — send an `Idempotency-Key` header on any POST to make retries safe for 24 hours.\n\n**Errors** — RFC 9457 `application/problem+json` with a stable `code` and a `request_id` to quote to support."
  },
  "servers": [
    {
      "url": "https://web.featshare.com/api",
      "description": "Live"
    }
  ],
  "security": [
    {
      "bearerKey": []
    },
    {
      "headerKey": []
    }
  ],
  "tags": [
    {
      "name": "Meta",
      "description": "Health, identity and the spec itself"
    },
    {
      "name": "Members",
      "description": "The business's member roster"
    },
    {
      "name": "Products",
      "description": "Product types (catalogue) and members' products — memberships, tickets, trials"
    },
    {
      "name": "Leads",
      "description": "Leads and the share-configured lookup maps"
    },
    {
      "name": "Schedule",
      "description": "Class occurrences, staff, locations and categories"
    },
    {
      "name": "Messages",
      "description": "Outbound push / chat / WhatsApp messages"
    },
    {
      "name": "Tasks",
      "description": "The business task board"
    },
    {
      "name": "Webhooks",
      "description": "Outbound event subscriptions with HMAC-signed deliveries"
    },
    {
      "name": "Reports",
      "description": "Named summary reports"
    }
  ],
  "paths": {
    "/v1/health": {
      "get": {
        "operationId": "getHealth",
        "summary": "Liveness probe",
        "tags": [
          "Meta"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "API is up",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "examples": [
                            "ok"
                          ]
                        },
                        "version": {
                          "type": "string"
                        }
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/openapi.json": {
      "get": {
        "operationId": "getOpenApi",
        "summary": "This specification",
        "tags": [
          "Meta"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "The OpenAPI 3.1 document",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/postman.json": {
      "get": {
        "operationId": "getPostmanCollection",
        "summary": "Postman collection (generated from this spec)",
        "tags": [
          "Meta"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Postman collection v2.1",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/members": {
      "post": {
        "operationId": "createMember",
        "summary": "Create a member",
        "description": "Runs the app's member-creation engine (roster + account doc). 409 when a member with this phone already exists in the business (its id is quoted in the error detail). Requires scope `members:create`. Send an `Idempotency-Key` header to make retries safe.",
        "tags": [
          "Members"
        ],
        "x-scope": "members:create",
        "parameters": [],
        "responses": {
          "201": {
            "description": "Create a member",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Member"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "phone"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string",
                    "description": "Any common format; normalized to +972 E.164"
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "gender": {
                    "type": "string",
                    "enum": [
                      "male",
                      "female",
                      "other"
                    ]
                  },
                  "birthday": {
                    "type": "string",
                    "format": "date"
                  },
                  "address": {
                    "type": "string"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listMembers",
        "summary": "List members",
        "description": "Ordered by last update (newest first) unless a search/sync filter changes the ordering. Requires scope `members:read`.",
        "tags": [
          "Members"
        ],
        "x-scope": "members:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "archived",
                "all"
              ],
              "default": "active"
            },
            "description": "Archive filter (applied per page — a page may hold fewer than limit items)"
          },
          {
            "name": "updated_since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Only members updated after this moment, oldest first — the sync mode"
          },
          {
            "name": "phone",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Exact phone match (any common format; normalized to E.164)"
          },
          {
            "name": "email",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "email"
            },
            "description": "Exact email match"
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Name prefix search"
          }
        ],
        "responses": {
          "200": {
            "description": "List members",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Member"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ListMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/members/{id}": {
      "get": {
        "operationId": "getMember",
        "summary": "Get a member",
        "description": "Requires scope `members:read`.",
        "tags": [
          "Members"
        ],
        "x-scope": "members:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          },
          {
            "name": "expand",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma list; supports `products`"
          }
        ],
        "responses": {
          "200": {
            "description": "Get a member",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Member"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      },
      "patch": {
        "operationId": "patchMember",
        "summary": "Update a member",
        "description": "Allow-listed profile fields only — anything else is rejected. Requires scope `members:update`.",
        "tags": [
          "Members"
        ],
        "x-scope": "members:update",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          }
        ],
        "responses": {
          "200": {
            "description": "Update a member",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Member"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "gender": {
                    "type": "string",
                    "enum": [
                      "male",
                      "female",
                      "other"
                    ]
                  },
                  "birthday": {
                    "type": "string",
                    "format": "date"
                  },
                  "address": {
                    "type": "string"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/v1/members/{id}/archive": {
      "post": {
        "operationId": "archiveMember",
        "summary": "Archive a member",
        "description": "In-place archive (reversible). 409 when already archived. Requires scope `members:archive`. Send an `Idempotency-Key` header to make retries safe.",
        "tags": [
          "Members"
        ],
        "x-scope": "members:archive",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          }
        ],
        "responses": {
          "200": {
            "description": "Archive a member",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Member"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/members/{id}/unarchive": {
      "post": {
        "operationId": "unarchiveMember",
        "summary": "Restore an archived member",
        "description": "Requires scope `members:archive`. Send an `Idempotency-Key` header to make retries safe.",
        "tags": [
          "Members"
        ],
        "x-scope": "members:archive",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          }
        ],
        "responses": {
          "200": {
            "description": "Restore an archived member",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Member"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/members/{id}/products": {
      "get": {
        "operationId": "listMemberProducts",
        "summary": "List a member's products",
        "description": "Requires scope `members:read`.",
        "tags": [
          "Members"
        ],
        "x-scope": "members:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          }
        ],
        "responses": {
          "200": {
            "description": "List a member's products",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Product"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ListMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/members/{id}/bookings": {
      "get": {
        "operationId": "listMemberBookings",
        "summary": "List a member's bookings",
        "description": "Requires scope `members:read`.",
        "tags": [
          "Members"
        ],
        "x-scope": "members:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Window start (default: yesterday)"
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Window end (max 62 days after from)"
          }
        ],
        "responses": {
          "200": {
            "description": "List a member's bookings",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Booking"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ListMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/product-types": {
      "get": {
        "operationId": "listProductTypes",
        "summary": "List product types",
        "description": "Requires scope `products:read`.",
        "tags": [
          "Products"
        ],
        "x-scope": "products:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "name": "include_inactive",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "Include inactive catalogue entries"
          }
        ],
        "responses": {
          "200": {
            "description": "List product types",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ProductType"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ListMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/products": {
      "post": {
        "operationId": "createProduct",
        "summary": "Grant a product to a member",
        "description": "Creates a product from the type (dates, entries and price copied from the catalogue), exactly like an in-app grant. Requires scope `products:grant`. Send an `Idempotency-Key` header to make retries safe.",
        "tags": [
          "Products"
        ],
        "x-scope": "products:grant",
        "parameters": [],
        "responses": {
          "201": {
            "description": "Grant a product to a member",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Product"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "member_id",
                  "type_id"
                ],
                "properties": {
                  "member_id": {
                    "type": "string"
                  },
                  "type_id": {
                    "type": "string",
                    "description": "A product type id from /v1/product-types"
                  },
                  "start_date": {
                    "type": "string",
                    "format": "date",
                    "description": "Default: today"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listProducts",
        "summary": "List products",
        "description": "Requires scope `products:read`.",
        "tags": [
          "Products"
        ],
        "x-scope": "products:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "name": "member_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Products of one member"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "freeze",
                "close"
              ]
            },
            "description": "Lifecycle filter"
          },
          {
            "name": "type_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Products created from one product type"
          },
          {
            "name": "expiring_before",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Products whose end date is on/before this day"
          }
        ],
        "responses": {
          "200": {
            "description": "List products",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Product"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ListMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/products/{id}": {
      "get": {
        "operationId": "getProduct",
        "summary": "Get a product",
        "description": "Requires scope `products:read`.",
        "tags": [
          "Products"
        ],
        "x-scope": "products:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          },
          {
            "name": "expand",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma list; supports `activities` (usage entries)"
          }
        ],
        "responses": {
          "200": {
            "description": "Get a product",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Product"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/products/{id}/close": {
      "post": {
        "operationId": "closeProduct",
        "summary": "Close a product",
        "description": "The app's full close engine (refund math, notifications, bookkeeping). 409 when already closed. There is NO delete on this API — close is final but auditable. Requires scope `products:close`. Send an `Idempotency-Key` header to make retries safe.",
        "tags": [
          "Products"
        ],
        "x-scope": "products:close",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          }
        ],
        "responses": {
          "200": {
            "description": "Close a product",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Product"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [],
                "properties": {
                  "closing_date": {
                    "type": "string",
                    "format": "date",
                    "description": "Default: now"
                  },
                  "refund": {
                    "type": "boolean",
                    "description": "Default true — run the engine's refund math"
                  },
                  "comment": {
                    "type": "string"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/v1/products/{id}/freeze": {
      "post": {
        "operationId": "freezeProduct",
        "summary": "Freeze a product",
        "description": "Adds a freeze window (start/end — no indefinite freezes). The response includes the `freezes` list with each window's `key` for unfreezing. Requires scope `products:freeze`. Send an `Idempotency-Key` header to make retries safe.",
        "tags": [
          "Products"
        ],
        "x-scope": "products:freeze",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          }
        ],
        "responses": {
          "200": {
            "description": "Freeze a product",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Product"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "start_date",
                  "end_date"
                ],
                "properties": {
                  "start_date": {
                    "type": "string",
                    "format": "date"
                  },
                  "end_date": {
                    "type": "string",
                    "format": "date"
                  },
                  "refund": {
                    "type": "boolean"
                  },
                  "comment": {
                    "type": "string"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/v1/products/{id}/unfreeze": {
      "post": {
        "operationId": "unfreezeProduct",
        "summary": "Remove a freeze window",
        "description": "Requires scope `products:freeze`. Send an `Idempotency-Key` header to make retries safe.",
        "tags": [
          "Products"
        ],
        "x-scope": "products:freeze",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          }
        ],
        "responses": {
          "200": {
            "description": "Remove a freeze window",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Product"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "freeze_key"
                ],
                "properties": {
                  "freeze_key": {
                    "type": "string"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/v1/messages": {
      "post": {
        "operationId": "sendMessages",
        "summary": "Send a message to members",
        "description": "Queues through the app's own pipelines; delivery is asynchronous. Archived/unknown members are skipped and reported. WhatsApp sends respect the business's quiet hours. EACH RECIPIENT counts against the daily message quota, so a batch that would exceed it is refused whole with 429 message_quota_exceeded and nothing is sent. Requires scope `messages:send`. Send an `Idempotency-Key` header to make retries safe.",
        "tags": [
          "Messages"
        ],
        "x-scope": "messages:send",
        "parameters": [],
        "responses": {
          "202": {
            "description": "Send a message to members",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "object": {
                          "type": "string",
                          "examples": [
                            "message_batch"
                          ]
                        },
                        "channel": {
                          "type": "string"
                        },
                        "queued": {
                          "type": "integer"
                        },
                        "skipped": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "member_id": {
                                "type": "string"
                              },
                              "reason": {
                                "type": "string"
                              }
                            }
                          }
                        }
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "channel",
                  "member_ids",
                  "text"
                ],
                "properties": {
                  "channel": {
                    "type": "string",
                    "enum": [
                      "push",
                      "chat",
                      "whatsapp"
                    ]
                  },
                  "member_ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 50
                  },
                  "text": {
                    "type": "string",
                    "maxLength": 1500
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/v1/tasks": {
      "get": {
        "operationId": "listTasks",
        "summary": "List tasks",
        "description": "Requires scope `tasks:read`.",
        "tags": [
          "Tasks"
        ],
        "x-scope": "tasks:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "closed",
                "all"
              ],
              "default": "open"
            },
            "description": "Task state filter"
          }
        ],
        "responses": {
          "200": {
            "description": "List tasks",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Task"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ListMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      },
      "post": {
        "operationId": "createTask",
        "summary": "Create a task",
        "description": "Requires scope `tasks:create`. Send an `Idempotency-Key` header to make retries safe.",
        "tags": [
          "Tasks"
        ],
        "x-scope": "tasks:create",
        "parameters": [],
        "responses": {
          "201": {
            "description": "Create a task",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Task"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text"
                ],
                "properties": {
                  "text": {
                    "type": "string"
                  },
                  "due_date": {
                    "type": "string",
                    "format": "date",
                    "description": "Default: today"
                  },
                  "member_id": {
                    "type": "string",
                    "description": "Attach the task to a member"
                  },
                  "type_key": {
                    "type": "string"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/v1/tasks/{id}/complete": {
      "post": {
        "operationId": "completeTask",
        "summary": "Close a task",
        "description": "409 when the task is already closed. Requires scope `tasks:complete`. Send an `Idempotency-Key` header to make retries safe.",
        "tags": [
          "Tasks"
        ],
        "x-scope": "tasks:complete",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          }
        ],
        "responses": {
          "200": {
            "description": "Close a task",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Task"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/leads": {
      "post": {
        "operationId": "createLead",
        "summary": "Create a lead",
        "description": "Triggers the same owner notification fan-out as in-app leads. 409 when an OPEN lead with this phone already exists (its id is quoted in the error detail). Requires scope `leads:create`. Send an `Idempotency-Key` header to make retries safe.",
        "tags": [
          "Leads"
        ],
        "x-scope": "leads:create",
        "parameters": [],
        "responses": {
          "201": {
            "description": "Create a lead",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Lead"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "full_name",
                  "phone"
                ],
                "properties": {
                  "full_name": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "source": {
                    "type": "string",
                    "description": "A key from /v1/lead-sources (default leadSource_api)"
                  },
                  "type": {
                    "type": "string"
                  },
                  "interest": {
                    "type": "string"
                  },
                  "campaign": {
                    "type": "string"
                  },
                  "comment": {
                    "type": "string"
                  },
                  "follow_up_at": {
                    "type": "string",
                    "format": "date-time"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listLeads",
        "summary": "List leads",
        "description": "Ordered by creation (newest first) unless a filter changes the ordering. Requires scope `leads:read`.",
        "tags": [
          "Leads"
        ],
        "x-scope": "leads:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "name": "open",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "true = open leads only, false = closed only"
          },
          {
            "name": "phone",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Exact phone match"
          },
          {
            "name": "updated_since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Only leads updated after this moment, oldest first"
          }
        ],
        "responses": {
          "200": {
            "description": "List leads",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Lead"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ListMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/leads/{id}": {
      "get": {
        "operationId": "getLead",
        "summary": "Get a lead",
        "description": "Requires scope `leads:read`.",
        "tags": [
          "Leads"
        ],
        "x-scope": "leads:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          },
          {
            "name": "expand",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma list; supports `comments`"
          }
        ],
        "responses": {
          "200": {
            "description": "Get a lead",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Lead"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      },
      "patch": {
        "operationId": "patchLead",
        "summary": "Update a lead",
        "description": "Requires scope `leads:update`.",
        "tags": [
          "Leads"
        ],
        "x-scope": "leads:update",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          }
        ],
        "responses": {
          "200": {
            "description": "Update a lead",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Lead"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [],
                "properties": {
                  "full_name": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "source": {
                    "type": "string"
                  },
                  "type": {
                    "type": "string"
                  },
                  "interest": {
                    "type": "string"
                  },
                  "campaign": {
                    "type": "string"
                  },
                  "follow_up_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "open": {
                    "type": "boolean",
                    "description": "false closes the lead, true reopens it"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/v1/leads/{id}/notes": {
      "post": {
        "operationId": "addLeadNote",
        "summary": "Add a note to a lead",
        "description": "Requires scope `leads:update`. Send an `Idempotency-Key` header to make retries safe.",
        "tags": [
          "Leads"
        ],
        "x-scope": "leads:update",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          }
        ],
        "responses": {
          "201": {
            "description": "Add a note to a lead",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "created_at": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "text": {
                          "type": "string"
                        }
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text"
                ],
                "properties": {
                  "text": {
                    "type": "string"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/v1/leads/{id}/lost": {
      "post": {
        "operationId": "markLeadLost",
        "summary": "Mark a lead as lost",
        "description": "Closes the lead and records the reason as a note. Requires scope `leads:update`. Send an `Idempotency-Key` header to make retries safe.",
        "tags": [
          "Leads"
        ],
        "x-scope": "leads:update",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          }
        ],
        "responses": {
          "200": {
            "description": "Mark a lead as lost",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Lead"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [],
                "properties": {
                  "reason": {
                    "type": "string"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/v1/lead-sources": {
      "get": {
        "operationId": "listLeadSources",
        "summary": "List lead sources",
        "description": "Requires scope `leads:read`.",
        "tags": [
          "Leads"
        ],
        "x-scope": "leads:read",
        "parameters": [],
        "responses": {
          "200": {
            "description": "List lead sources",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LookupItem"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ListMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/lead-types": {
      "get": {
        "operationId": "listLeadTypes",
        "summary": "List lead types",
        "description": "Requires scope `leads:read`.",
        "tags": [
          "Leads"
        ],
        "x-scope": "leads:read",
        "parameters": [],
        "responses": {
          "200": {
            "description": "List lead types",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LookupItem"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ListMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/lead-interests": {
      "get": {
        "operationId": "listLeadInterests",
        "summary": "List lead interests",
        "description": "Requires scope `leads:read`.",
        "tags": [
          "Leads"
        ],
        "x-scope": "leads:read",
        "parameters": [],
        "responses": {
          "200": {
            "description": "List lead interests",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LookupItem"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ListMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/schedule": {
      "get": {
        "operationId": "listSchedule",
        "summary": "List classes in a date window",
        "description": "Requires scope `schedule:read`.",
        "tags": [
          "Schedule"
        ],
        "x-scope": "schedule:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Window start (required)"
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Window end (required; max 62 days after from)"
          },
          {
            "name": "teacher_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Only classes assigned to this staff member"
          },
          {
            "name": "location",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Location key (see /v1/locations)"
          },
          {
            "name": "category_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Category id (see /v1/categories)"
          }
        ],
        "responses": {
          "200": {
            "description": "List classes in a date window",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Class"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ListMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/schedule/{id}": {
      "get": {
        "operationId": "getScheduleClass",
        "summary": "Get a class",
        "description": "Requires scope `schedule:read`.",
        "tags": [
          "Schedule"
        ],
        "x-scope": "schedule:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          },
          {
            "name": "expand",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma list; supports `participants`"
          }
        ],
        "responses": {
          "200": {
            "description": "Get a class",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Class"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/schedule/{id}/bookings": {
      "post": {
        "operationId": "createBooking",
        "summary": "Book a member into a class",
        "description": "Runs the app's full registration engine: capacity, product validity, entry caps, archive guard and locks all apply. 409 `meeting_full` when the class is full. Requires scope `bookings:book`. Send an `Idempotency-Key` header to make retries safe.",
        "tags": [
          "Schedule"
        ],
        "x-scope": "bookings:book",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          }
        ],
        "responses": {
          "201": {
            "description": "Book a member into a class",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/BookingResult"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "member_id"
                ],
                "properties": {
                  "member_id": {
                    "type": "string"
                  },
                  "product_id": {
                    "type": "string",
                    "description": "Optional — the engine picks a valid product when omitted"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/v1/schedule/{id}/bookings/{member_id}": {
      "delete": {
        "operationId": "cancelBooking",
        "summary": "Cancel a member's booking",
        "description": "Cancels a registration or waitlist entry. Fixed-slot registrations are app-only. Requires scope `bookings:cancel`.",
        "tags": [
          "Schedule"
        ],
        "x-scope": "bookings:cancel",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          },
          {
            "name": "member_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          }
        ],
        "responses": {
          "200": {
            "description": "Cancel a member's booking",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/BookingResult"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/schedule/{id}/waitlist": {
      "post": {
        "operationId": "joinWaitlist",
        "summary": "Join a class waiting list",
        "description": "Requires scope `bookings:waitlist`. Send an `Idempotency-Key` header to make retries safe.",
        "tags": [
          "Schedule"
        ],
        "x-scope": "bookings:waitlist",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          }
        ],
        "responses": {
          "201": {
            "description": "Join a class waiting list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/BookingResult"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "member_id"
                ],
                "properties": {
                  "member_id": {
                    "type": "string"
                  },
                  "product_id": {
                    "type": "string",
                    "description": "The product to hold the spot with — recommended; omit only for product-less classes"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/v1/staff": {
      "get": {
        "operationId": "listStaff",
        "summary": "List staff members",
        "description": "Requires scope `schedule:read`.",
        "tags": [
          "Schedule"
        ],
        "x-scope": "schedule:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "List staff members",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/StaffMember"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ListMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/locations": {
      "get": {
        "operationId": "listLocations",
        "summary": "List locations",
        "description": "Requires scope `schedule:read`.",
        "tags": [
          "Schedule"
        ],
        "x-scope": "schedule:read",
        "parameters": [],
        "responses": {
          "200": {
            "description": "List locations",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Location"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ListMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/categories": {
      "get": {
        "operationId": "listCategories",
        "summary": "List class categories",
        "description": "Requires scope `schedule:read`.",
        "tags": [
          "Schedule"
        ],
        "x-scope": "schedule:read",
        "parameters": [],
        "responses": {
          "200": {
            "description": "List class categories",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Category"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ListMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/reports/{name}": {
      "get": {
        "operationId": "getReport",
        "summary": "Run a named report",
        "description": "Results are cached for 10 minutes. Requires scope `reports:read`.",
        "tags": [
          "Reports"
        ],
        "x-scope": "reports:read",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "One of: active_members, new_members, birthdays, expiring_products, expired_products, attendance, no_shows, leads_funnel"
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Window start (windowed reports; default 30 days back)"
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Window end"
          },
          {
            "name": "month",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 12
            },
            "description": "birthdays report only"
          }
        ],
        "responses": {
          "200": {
            "description": "Run a named report",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Report"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/webhooks": {
      "get": {
        "operationId": "listWebhooks",
        "summary": "List webhook subscriptions",
        "description": "Requires scope `webhooks:manage`.",
        "tags": [
          "Webhooks"
        ],
        "x-scope": "webhooks:manage",
        "parameters": [],
        "responses": {
          "200": {
            "description": "List webhook subscriptions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Webhook"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ListMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      },
      "post": {
        "operationId": "createWebhook",
        "summary": "Create a webhook subscription",
        "description": "The signing `secret` (whsec_...) is returned ONCE in this response. Verify deliveries with `X-FeatShare-Signature: t=<unix>,v1=HMAC_SHA256(secret, t + '.' + rawBody)`. Retries: 1m/5m/30m/2h/12h; 20 consecutive failures auto-disable the subscription. Requires scope `webhooks:manage`. Send an `Idempotency-Key` header to make retries safe.",
        "tags": [
          "Webhooks"
        ],
        "x-scope": "webhooks:manage",
        "parameters": [],
        "responses": {
          "201": {
            "description": "Create a webhook subscription",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url",
                  "events"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "https:// endpoint"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Any of: lead.created, member.created, member.updated, member.archived, product.created, product.closed, product.frozen, task.created"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}": {
      "delete": {
        "operationId": "deleteWebhook",
        "summary": "Delete a webhook subscription",
        "description": "Requires scope `webhooks:manage`.",
        "tags": [
          "Webhooks"
        ],
        "x-scope": "webhooks:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          }
        ],
        "responses": {
          "200": {
            "description": "Delete a webhook subscription",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/webhooks/{id}/test": {
      "post": {
        "operationId": "testWebhook",
        "summary": "Send a test ping",
        "description": "Queues a `ping` event through the production delivery path (same signature). Requires scope `webhooks:manage`. Send an `Idempotency-Key` header to make retries safe.",
        "tags": [
          "Webhooks"
        ],
        "x-scope": "webhooks:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          }
        ],
        "responses": {
          "202": {
            "description": "Send a test ping",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "object": {
                          "type": "string",
                          "examples": [
                            "webhook_test"
                          ]
                        },
                        "webhook_id": {
                          "type": "string"
                        },
                        "queued": {
                          "type": "boolean"
                        }
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/webhooks/{id}/deliveries": {
      "get": {
        "operationId": "listWebhookDeliveries",
        "summary": "List recent delivery attempts",
        "description": "Requires scope `webhooks:manage`.",
        "tags": [
          "Webhooks"
        ],
        "x-scope": "webhooks:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": ""
          }
        ],
        "responses": {
          "200": {
            "description": "List recent delivery attempts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookDelivery"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ListMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/v1/me": {
      "get": {
        "operationId": "getMe",
        "summary": "Identify the calling key",
        "description": "Returns the business (share) this key belongs to, its scopes and environment. Useful as a connection test.",
        "tags": [
          "Meta"
        ],
        "responses": {
          "200": {
            "description": "The calling key's identity",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ApiIdentity"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key as a bearer token: `Authorization: Bearer fs_live_...`"
      },
      "headerKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-FeatShare-Key",
        "description": "API key in the FeatShare house header"
      }
    },
    "parameters": {
      "limit": {
        "name": "limit",
        "in": "query",
        "description": "Page size (1-200, default 50)",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200,
          "default": 50
        }
      },
      "cursor": {
        "name": "cursor",
        "in": "query",
        "description": "Opaque cursor from a previous response's `meta.next_cursor`",
        "schema": {
          "type": "string"
        }
      }
    },
    "headers": {
      "X-Request-Id": {
        "description": "Unique id of this request — quote it to support",
        "schema": {
          "type": "string"
        }
      },
      "Retry-After": {
        "description": "Seconds to wait before retrying",
        "schema": {
          "type": "integer"
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing or invalid API key (`missing_key`, `invalid_key`, `key_revoked`, `key_expired`)",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Key valid but not allowed (`api_disabled`, `insufficient_scope`, `ip_not_allowed`, `module_off`)",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource does not exist (`not_found`)",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "Conflict": {
        "description": "State conflict (`conflict`, `already_registered`, `meeting_full`, `idempotency_key_reused`)",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "Unprocessable": {
        "description": "Validation or business-rule failure (`validation_failed`, `business_rule`)",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Rate limit or quota exceeded (`rate_limited`, `daily_quota_exceeded`, `monthly_quota_exceeded`, `message_quota_exceeded`) — honor `Retry-After`",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "Unavailable": {
        "description": "API disabled globally or temporarily unavailable (`api_unavailable`)",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      }
    },
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details. `code` is the stable machine-readable identifier; the full catalogue is documented at https://web.featshare.com/api/docs/errors.",
        "required": [
          "type",
          "title",
          "status",
          "code",
          "request_id"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "code": {
            "type": "string",
            "examples": [
              "validation_failed"
            ]
          },
          "detail": {
            "type": "string"
          },
          "request_id": {
            "type": "string",
            "examples": [
              "req_mtj3gf2z182fe52d826e"
            ]
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "field": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "code": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "Meta": {
        "type": "object",
        "required": [
          "request_id"
        ],
        "properties": {
          "request_id": {
            "type": "string"
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          },
          "count": {
            "type": "integer"
          }
        }
      },
      "ListMeta": {
        "type": "object",
        "required": [
          "request_id",
          "has_more"
        ],
        "properties": {
          "request_id": {
            "type": "string"
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          },
          "count": {
            "type": "integer"
          }
        }
      },
      "Member": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "examples": [
              "member"
            ]
          },
          "name": {
            "type": "string"
          },
          "phone": {
            "type": [
              "string",
              "null"
            ],
            "description": "E.164 (+972...)"
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "role": {
            "type": "string",
            "enum": [
              "visitor",
              "member",
              "instructor",
              "secretary",
              "admin",
              "owner",
              "support"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "archived"
            ]
          },
          "gender": {
            "type": [
              "string",
              "null"
            ]
          },
          "birthday": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "address": {
            "type": [
              "string",
              "null"
            ]
          },
          "image_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "lead_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The lead this member was converted from"
          },
          "joined_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "last_visit_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "products": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Product"
            },
            "description": "Only with expand=products"
          }
        }
      },
      "StaffMember": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "examples": [
              "staff_member"
            ]
          },
          "name": {
            "type": "string"
          },
          "phone": {
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "role": {
            "type": "string"
          },
          "image_url": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Product": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "examples": [
              "product"
            ]
          },
          "member_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "type_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "kind": {
            "type": "string",
            "enum": [
              "membership",
              "ticket",
              "trial",
              "single",
              "group",
              "attendance",
              "other",
              "equipment",
              "application",
              "package"
            ]
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "freeze",
              "close"
            ]
          },
          "price": {
            "type": "number"
          },
          "entries": {
            "type": "object",
            "properties": {
              "total": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "null = unlimited entries"
              },
              "used": {
                "type": "integer"
              },
              "left": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            }
          },
          "starts_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "ends_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "final_ends_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "closed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "activities": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Only with expand=activities"
          }
        }
      },
      "ProductType": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "examples": [
              "product_type"
            ]
          },
          "name": {
            "type": "string"
          },
          "kind": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "price": {
            "type": "number"
          },
          "duration": {
            "type": "object",
            "properties": {
              "months": {
                "type": "integer"
              },
              "weeks": {
                "type": "integer"
              },
              "days": {
                "type": "integer"
              },
              "unlimited": {
                "type": "boolean"
              }
            }
          },
          "entries": {
            "type": "object",
            "properties": {
              "total": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "per_day": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "per_week": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "per_month": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            }
          },
          "active": {
            "type": "boolean"
          },
          "available_in_store": {
            "type": "boolean"
          }
        }
      },
      "Class": {
        "type": "object",
        "description": "One class occurrence on the schedule",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "examples": [
              "class"
            ]
          },
          "name": {
            "type": "string"
          },
          "starts_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "ends_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "location": {
            "type": "object",
            "properties": {
              "key": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "category": {
            "type": "object",
            "properties": {
              "id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "staff": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "member_id": {
                  "type": "string"
                }
              }
            }
          },
          "capacity": {
            "type": "object",
            "properties": {
              "max": {
                "type": "integer"
              },
              "registered": {
                "type": "integer"
              },
              "waiting_max": {
                "type": "integer"
              },
              "waiting": {
                "type": "integer"
              }
            }
          },
          "is_locked": {
            "type": "boolean"
          },
          "master_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "participants": {
            "type": "array",
            "description": "Only with expand=participants",
            "items": {
              "type": "object",
              "properties": {
                "member_id": {
                  "type": "string"
                },
                "name": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "state": {
                  "type": "string",
                  "enum": [
                    "registered",
                    "waiting",
                    "fixed"
                  ]
                },
                "attendance": {
                  "type": "string",
                  "enum": [
                    "attended",
                    "no_show",
                    "unknown"
                  ]
                },
                "product_id": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          }
        }
      },
      "Booking": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "examples": [
              "booking"
            ]
          },
          "class_id": {
            "type": "string"
          },
          "class_name": {
            "type": "string"
          },
          "starts_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "state": {
            "type": "string",
            "enum": [
              "registered",
              "waiting",
              "fixed"
            ]
          },
          "attendance": {
            "type": "string",
            "enum": [
              "attended",
              "no_show",
              "unknown"
            ]
          },
          "product_id": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Lead": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "examples": [
              "lead"
            ]
          },
          "full_name": {
            "type": "string"
          },
          "phone": {
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "open": {
            "type": "boolean"
          },
          "source": {
            "$ref": "#/components/schemas/KeyName"
          },
          "type": {
            "$ref": "#/components/schemas/KeyName"
          },
          "interest": {
            "$ref": "#/components/schemas/KeyName"
          },
          "campaign": {
            "type": [
              "string",
              "null"
            ]
          },
          "member_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Set when the lead became a member"
          },
          "last_comment": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "follow_up_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "comments": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Only with expand=comments"
          }
        }
      },
      "Report": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "examples": [
              "report"
            ]
          },
          "name": {
            "type": "string"
          },
          "summary": {
            "type": "object",
            "description": "Report-specific totals"
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Up to 1000 rows"
          }
        }
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "examples": [
              "webhook"
            ]
          },
          "url": {
            "type": "string"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "disabled",
              "deleted"
            ]
          },
          "secret": {
            "type": "string",
            "description": "Full whsec_ value on create only; masked afterwards"
          },
          "consecutive_failures": {
            "type": "integer"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "last_delivery_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "WebhookDelivery": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "examples": [
              "webhook_delivery"
            ]
          },
          "at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "event": {
            "type": "string"
          },
          "attempt": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "enum": [
              "delivered",
              "failed"
            ]
          },
          "http_status": {
            "type": "integer"
          },
          "latency_ms": {
            "type": "integer"
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "dead": {
            "type": "boolean",
            "description": "true when retries were exhausted"
          }
        }
      },
      "Task": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "examples": [
              "task"
            ]
          },
          "text": {
            "type": "string"
          },
          "open": {
            "type": "boolean"
          },
          "due_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "member_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "type_key": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "BookingResult": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "examples": [
              "booking"
            ]
          },
          "class_id": {
            "type": "string"
          },
          "member_id": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "enum": [
              "registered",
              "waiting",
              "cancelled"
            ]
          },
          "dry_run": {
            "type": "boolean",
            "description": "Present (true) for fs_test_ keys"
          }
        }
      },
      "KeyName": {
        "type": "object",
        "properties": {
          "key": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "LookupItem": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "info": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Location": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "examples": [
              "location"
            ]
          },
          "key": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "address": {
            "type": [
              "string",
              "null"
            ]
          },
          "color": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_doctor_calendar": {
            "type": "boolean"
          }
        }
      },
      "Category": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "examples": [
              "category"
            ]
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "ApiIdentity": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "examples": [
              "api_identity"
            ]
          },
          "share_id": {
            "type": "string",
            "description": "The business this key belongs to. All API calls are implicitly scoped to it."
          },
          "key": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "env": {
                "type": "string",
                "enum": [
                  "live",
                  "test"
                ]
              },
              "scopes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "rate_plan": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          }
        }
      }
    }
  }
}