{
 "openapi": "3.0.0",
 "paths": {
  "/.well-known/security.txt": {
   "get": {
    "operationId": "WellKnownController_securityTxt",
    "summary": "",
    "description": "RFC 9116 security.txt: where researchers report vulnerabilities.\nSECURITY_CONTACT / SECURITY_POLICY_URL override the defaults; Expires\nis always one year ahead.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "security": []
   }
  },
  "/abuse/reasons": {
   "get": {
    "operationId": "AbuseController_reasons",
    "summary": "Public: the reasons a report can give, for a reporting menu",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Abuse reports"
    ],
    "security": []
   }
  },
  "/abuse/reports": {
   "post": {
    "operationId": "AbuseController_report",
    "summary": "Report an account, profile, business, channel, message, media item or group ({ received, reference })",
    "description": "A message needs target.sender_account_id; a media item is filed on its owner (account, else channel). A group is named by your app's group id (never looked up) and may name up to 10 members in target.member_account_ids, each filed as its own report and counted against the limits (the answer then adds references); with no member named it is filed on your channel. Evidence: up to 10 references (ids, https URLs, SHA-256 hashes, excerpts you choose to share). 20 reports per hour and 100 per day per person; reporting the same target again adds your new evidence to your first report.",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/AbuseReportDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Abuse reports"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/abuse/reports/mine": {
   "get": {
    "operationId": "AbuseController_mine",
    "summary": "My reports: what I reported and whether it has been reviewed (never the decision)",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Abuse reports"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/addresses": {
   "post": {
    "operationId": "AddressesController_createAddress",
    "summary": "Create A Business Address",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateAddressDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Address created successfully",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Addresses"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "AddressesController_fetchPersonalAddresses",
    "summary": "Fetch All Personal Addresses",
    "parameters": [],
    "responses": {
     "200": {
      "description": "List of personal addresses returned",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Addresses"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/addresses/delete/{id}": {
   "post": {
    "operationId": "AddressesController_deleteAddress",
    "summary": "Delete A Business Address",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Address deleted successfully",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Addresses"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/addresses/update/{id}": {
   "post": {
    "operationId": "AddressesController_updateAddress",
    "summary": "Update A Business Address",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateAddressDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Address updated successfully",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Addresses"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/addresses/{businessId}": {
   "get": {
    "operationId": "AddressesController_fetchAllAddresses",
    "summary": "Fetch All Business Addresses for a specific business",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "List of addresses returned",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Addresses"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/ads/ads/{id}": {
   "patch": {
    "operationId": "AdsController_updateAd",
    "summary": "Change or pause an ad",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/AdDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Ads"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "AdsController_removeAd",
    "summary": "Remove an ad",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Ads"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/ads/businesses/{businessId}/campaigns": {
   "get": {
    "operationId": "AdsController_list",
    "summary": "The business's campaigns, ads and last 30 days' results",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Ads"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "AdsController_create",
    "summary": "Start a campaign (draft) promoting one of the business's channels",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CampaignDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Ads"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/ads/campaigns/{id}": {
   "get": {
    "operationId": "AdsController_get",
    "summary": "One campaign with its ads and results",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Ads"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "AdsController_update",
    "summary": "Change budget, bid, dates (at once) or audience (back to review)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CampaignDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Ads"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/ads/campaigns/{id}/ads": {
   "post": {
    "operationId": "AdsController_addAd",
    "summary": "Add an ad (a running campaign goes back to review)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/AdDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Ads"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/ads/campaigns/{id}/archive": {
   "post": {
    "operationId": "AdsController_archive",
    "summary": "Archive a campaign",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Ads"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/ads/campaigns/{id}/pause": {
   "post": {
    "operationId": "AdsController_pause",
    "summary": "Pause a running campaign",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Ads"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/ads/campaigns/{id}/resume": {
   "post": {
    "operationId": "AdsController_resume",
    "summary": "Resume a paused campaign",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Ads"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/ads/campaigns/{id}/stats": {
   "get": {
    "operationId": "AdsController_stats",
    "summary": "Results per ad and day (last 30 days)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Ads"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/ads/campaigns/{id}/submit": {
   "post": {
    "operationId": "AdsController_submit",
    "summary": "Send for review (accepts the advertising policy)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/SubmitCampaignDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Ads"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/ads/channels/{channelId}/partner": {
   "get": {
    "operationId": "AdsController_partner",
    "summary": "The channel's ad partner enrolment, this month's results and statements",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Ads"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "AdsController_enroll",
    "summary": "Enrol the channel in the Ad Partner Program (reviewed by Intersink)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/EnrollPartnerDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Ads"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "AdsController_updatePartner",
    "summary": "Change how the platform is described",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PartnerDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Ads"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/ads/channels/{channelId}/partner/leave": {
   "post": {
    "operationId": "AdsController_leave",
    "summary": "Leave the Ad Partner Program",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Ads"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/ads/click/{id}": {
   "get": {
    "operationId": "AdsController_click",
    "summary": "Follow an ad (counts the click, then redirects)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "t",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "p",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Ads"
    ],
    "security": []
   }
  },
  "/ads/library": {
   "get": {
    "operationId": "AdsController_library",
    "summary": "Ad Library: every ad an advertiser has run (?q=business or brand)",
    "parameters": [
     {
      "name": "q",
      "required": true,
      "in": "query",
      "description": "A business or brand name",
      "schema": {
       "minLength": 2,
       "maxLength": 80,
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Ads"
    ],
    "security": []
   }
  },
  "/ads/platforms": {
   "get": {
    "operationId": "AdsController_platforms",
    "summary": "Partner platforms advertisers can choose (Svayam's first)",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Ads"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/ads/serve": {
   "get": {
    "operationId": "AdsController_serve",
    "summary": "Ads for a Sponsored slot on a partner platform (?partner=<its channel id>&country=)",
    "parameters": [
     {
      "name": "partner",
      "required": true,
      "in": "query",
      "description": "The partner platform's channel id (the slot's owner)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "country",
      "required": false,
      "in": "query",
      "schema": {
       "minLength": 2,
       "maxLength": 2,
       "example": "GB",
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 6,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Ads"
    ],
    "security": []
   }
  },
  "/all-categories": {
   "get": {
    "operationId": "CategoriesController_findAll",
    "parameters": [
     {
      "name": "x-ref",
      "in": "header",
      "description": "Channel id",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "type",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Categories"
    ],
    "security": []
   }
  },
  "/all-categories/{id}": {
   "get": {
    "operationId": "CategoriesController_findOne",
    "parameters": [
     {
      "name": "x-ref",
      "in": "header",
      "description": "Channel id",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Categories"
    ],
    "security": []
   }
  },
  "/app-builder/apps/{id}": {
   "get": {
    "operationId": "AppBuilderController_describe",
    "summary": "An app's capabilities, navigation and prices",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "App builder"
    ],
    "security": []
   },
   "patch": {
    "operationId": "AppBuilderController_devUpdate",
    "summary": "Edit my developer app",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/AppInputDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "App builder"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "AppBuilderController_devArchive",
    "summary": "Archive my developer app",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "App builder"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/app-builder/apps/{id}/capability-request": {
   "delete": {
    "operationId": "AppBuilderController_withdrawCapabilityRequest",
    "summary": "Take back my app's capability change that is waiting for review",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "App builder"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/app-builder/apps/{id}/capability-versions": {
   "get": {
    "operationId": "AppBuilderController_capabilityHistory",
    "summary": "My app's capability versions, newest first (approved, pending review, rejected, withdrawn)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "App builder"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/app-builder/apps/{id}/submit": {
   "post": {
    "operationId": "AppBuilderController_submit",
    "summary": "Ask the platform channel to review the app for the Store",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "App builder"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/app-builder/businesses/{businessId}/apps": {
   "get": {
    "operationId": "AppBuilderController_devList",
    "summary": "My business's developer apps",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "App builder"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "AppBuilderController_devCreate",
    "summary": "Create an app (private to your channels until its review is approved)",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/AppInputDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "App builder"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/app-builder/capabilities": {
   "get": {
    "operationId": "AppBuilderController_capabilities",
    "summary": "Every capability an app can bundle (key, label, panel nav, API prefixes)",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "App builder"
    ],
    "security": []
   }
  },
  "/app-config": {
   "get": {
    "operationId": "PagesController_getAppConfig",
    "summary": "Get global app configuration and branding (Public)",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Pages & Configuration"
    ],
    "security": []
   }
  },
  "/apps": {
   "get": {
    "operationId": "AppsController_listApps",
    "summary": "List published apps. Query: ?q=&page=&limit= (max 100)",
    "parameters": [
     {
      "name": "q",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 100,
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "default": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "default": 20,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Apps"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/apps/channel": {
   "post": {
    "operationId": "AppsController_linkApp",
    "summary": "Install an app into a channel you manage (body channel_id, else your token's channel)",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateChannelAppDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Apps"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "AppsController_channelApps",
    "summary": "List apps installed on a channel: ?channel_id=, else x-ref, else your token's channel. Only a channel you can read: a live channel, or one you manage",
    "parameters": [
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "description": "The channel to read (UUID)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Apps"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/apps/channel/{channelId}/{appId}": {
   "delete": {
    "operationId": "AppsAccessController_uninstall",
    "summary": "Uninstall an app from a channel (link archived, not deleted)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "appId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Apps"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/apps/channel/{channelId}/{appId}/access": {
   "get": {
    "operationId": "AppsAccessController_getAccess",
    "summary": "Which channel roles can use an installed app",
    "parameters": [
     {
      "name": "appId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Apps"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "put": {
    "operationId": "AppsAccessController_setAccess",
    "summary": "Set the channel roles that can use an installed app (others lose access)",
    "parameters": [
     {
      "name": "appId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/AppAccessDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Apps"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/apps/{id}": {
   "get": {
    "operationId": "AppsController_getApp",
    "summary": "Get an app by id",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Apps"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/apps/{id}/reviews": {
   "get": {
    "operationId": "AppsController_appReviews",
    "summary": "An app's reviews, newest first, with its average rating",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Apps"
    ],
    "security": []
   },
   "post": {
    "operationId": "AppsController_reviewApp",
    "summary": "Rate and review an app (1–5). Only managers of a channel that runs it; one review per person, replaced on repeat",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/AppReviewDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Apps"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "AppsController_deleteReview",
    "summary": "Delete your review of an app",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Apps"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/attributes": {
   "post": {
    "operationId": "AttributesController_createAttribute",
    "summary": "Create a new attribute",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateAttributeDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Attributes"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "AttributesController_getAttributes",
    "summary": "Fetch attributes (can filter by group id in query)",
    "parameters": [
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "attribute_group",
      "required": false,
      "in": "query",
      "description": "Filter by attribute group id",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Attributes"
    ],
    "security": []
   }
  },
  "/attributes/data": {
   "post": {
    "operationId": "AttributesController_createAttributeData",
    "summary": "Assign attribute data to a product/campaign",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateAttributeDataDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Attributes"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "AttributesController_getAttributeData",
    "summary": "Fetch attribute data assignments",
    "parameters": [
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "attribute_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "product_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "campaign_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Attributes"
    ],
    "security": []
   }
  },
  "/attributes/data/{id}": {
   "patch": {
    "operationId": "AttributesController_updateAttributeData",
    "summary": "Update an attribute data assignment",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateAttributeDataDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Attributes"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "AttributesController_deleteAttributeData",
    "summary": "Delete an attribute data assignment",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Attributes"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/attributes/groups": {
   "post": {
    "operationId": "AttributesController_createGroup",
    "summary": "Create a new attribute group",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateAttributeGroupDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Attributes"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "AttributesController_getGroups",
    "summary": "Fetch all attribute groups",
    "parameters": [
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Attributes"
    ],
    "security": []
   }
  },
  "/attributes/groups/{id}": {
   "get": {
    "operationId": "AttributesController_getGroupById",
    "summary": "Fetch a specific attribute group",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Attributes"
    ],
    "security": []
   },
   "patch": {
    "operationId": "AttributesController_updateGroup",
    "summary": "Update an attribute group",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateAttributeGroupDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Attributes"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "AttributesController_deleteGroup",
    "summary": "Delete an attribute group",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Attributes"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/attributes/{id}": {
   "patch": {
    "operationId": "AttributesController_updateAttribute",
    "summary": "Update an attribute",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateAttributeDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Attributes"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "AttributesController_deleteAttribute",
    "summary": "Delete an attribute",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Attributes"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/apple": {
   "post": {
    "operationId": "AuthController_loginApple",
    "summary": "Login with Apple (Sign in with Apple)",
    "description": "Client sends the Apple identity token; the server verifies it against Apple's public keys and logs the user in (creating the account on first sign-in). Returns the same { access_token, refresh_token, user } as OTP.",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-install-id",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/AppleLoginDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Login successful",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/google": {
   "post": {
    "operationId": "AuthController_loginGoogle",
    "summary": "Login with Google (Sign in with Google)",
    "description": "Client sends the Google ID token; the server verifies it with Google and logs the user in (creating the account on first sign-in). Returns the same { access_token, refresh_token, user } as OTP login.",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-install-id",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/GoogleLoginDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Login successful",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/login": {
   "post": {
    "operationId": "AuthController_login",
    "summary": "2. Verify OTP & Login",
    "description": "Any code sent to this address on this channel in the last 15 minutes works (the newest first), once. A wrong code: 401 INVALID_CODE with `attemptsLeft` (\"That code didn't match. 4 tries left.\"). The 5th wrong try burns the code: 429 TOO_MANY_ATTEMPTS without retryAfterSeconds, ask for a new code. More than 20 wrong codes in an hour for the address lock code checks: 429 TOO_MANY_ATTEMPTS with `retryAfterSeconds` and `unlockAt`. A used or replaced code: 401 CODE_EXPIRED.",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/LoginOtpDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Login successful",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/login-app": {
   "post": {
    "operationId": "AuthController_loginApp",
    "summary": "Verify OTP and Login (Mobile Apps)",
    "description": "The app's twin of /auth/login: tokens come in the body. Send the channel's app key (X-App-Key) and `X-Install-Id`: a random id the app makes once per install (a UUID, or 16 to 64 random letters, digits, '-' or '_') and sends on every request. The session is then bound to that install, never to the IP or user agent: it survives Wi-Fi/cellular changes and OS updates, and its tokens are refused (401 INSTALL_MISMATCH) from any other install. Without the header the session is bound to nothing. Two answers: a session (`access_token`, `refresh_token`, `user`), or, when the account has an authenticator or a 2-step passkey, `mfa_required: true` with `methods` and a 5-minute `pending_token` to finish at /auth/mfa/totp, /auth/mfa/otp or /auth/mfa/passkey/verify (send the same X-Install-Id there). Errors: 401 INVALID_CODE (with attemptsLeft), 401 CODE_EXPIRED, 429 TOO_MANY_ATTEMPTS, 403 ACCOUNT_CLOSED (restore with restore_account: true), 400 INVALID_INSTALL_ID.",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-install-id",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/LoginOtpDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "A session, or a second step to finish",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "oneOf": [
              {
               "$ref": "#/components/schemas/LoginTokensDto"
              },
              {
               "$ref": "#/components/schemas/MfaRequiredDto"
              }
             ]
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/login-password": {
   "post": {
    "operationId": "AuthController_loginPassword",
    "summary": "Login with email + password (OTP alternative)",
    "description": "Logs in with a password. If the account has a second factor enrolled, no tokens are returned yet: the response is { mfa_required: true, methods, pending_token } and the client finishes with /auth/mfa/totp, /auth/mfa/otp or /auth/mfa/passkey/verify.",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-install-id",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/LoginPasswordDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Login successful or OTP required",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/login-totp": {
   "post": {
    "operationId": "AuthController_loginTotp",
    "summary": "Finish a TOTP-protected login with an authenticator/backup code",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-install-id",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/LoginTotpDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/logout": {
   "post": {
    "operationId": "AuthController_logout",
    "summary": "Logout and revoke session",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Logged out",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/me": {
   "get": {
    "operationId": "AuthController_getProfile",
    "summary": "Get current user profile",
    "parameters": [],
    "responses": {
     "200": {
      "description": "User profile returned",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/methods": {
   "post": {
    "operationId": "AuthController_authMethods",
    "summary": "Which login methods an email supports (password/totp/otp/passkey)",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/AuthMethodsDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/mfa/otp": {
   "post": {
    "operationId": "AuthController_mfaOtp",
    "summary": "Complete login with the emailed OTP",
    "parameters": [
     {
      "name": "x-install-id",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/MfaOtpDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/mfa/passkey/options": {
   "post": {
    "operationId": "AuthController_mfaPasskeyOptions",
    "summary": "Second-factor passkey: get options",
    "parameters": [
     {
      "name": "x-install-id",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/MfaPendingDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/mfa/passkey/verify": {
   "post": {
    "operationId": "AuthController_mfaPasskeyVerify",
    "summary": "Second-factor passkey: verify and complete login",
    "parameters": [
     {
      "name": "x-install-id",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/MfaPasskeyVerifyDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/mfa/totp": {
   "post": {
    "operationId": "AuthController_mfaTotp",
    "summary": "Complete login with an authenticator/backup code",
    "parameters": [
     {
      "name": "x-install-id",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/MfaTotpDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/opaque/credential/finish": {
   "post": {
    "operationId": "OpaqueAuthController_credentialFinish",
    "summary": "Change the password or recovery key, step 2",
    "description": "Stores the new record. Changing the password signs out every other session.",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/OpaqueCredentialFinishDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/opaque/credential/start": {
   "post": {
    "operationId": "OpaqueAuthController_credentialStart",
    "summary": "Change the password or recovery key, step 1",
    "description": "Needs a recent sign-in (an OPAQUE sign-in counts for 10 minutes). Otherwise 401 STEP_UP_REQUIRED.",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/OpaqueCredentialStartDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/opaque/login/finish": {
   "post": {
    "operationId": "OpaqueAuthController_loginFinish",
    "summary": "OPAQUE sign-in, step 2",
    "description": "App tokens { account_id, access_token, refresh_token, expires_in } (rotate with /auth/refresh-app); 401 INVALID_CREDENTIALS. An enrolled authenticator or passkey still applies (mfa_required).",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/OpaqueLoginFinishDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "401": {
      "description": "INVALID_CREDENTIALS"
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/opaque/login/start": {
   "post": {
    "operationId": "OpaqueAuthController_loginStart",
    "summary": "OPAQUE sign-in, step 1",
    "description": "credential = password | recovery. Unknown usernames get a well-formed fake response. 429 TOO_MANY_ATTEMPTS with retryAfterSeconds (and retry_after) after 10 failed sign-ins per username per hour.",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/OpaqueLoginStartDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/opaque/register/finish": {
   "post": {
    "operationId": "OpaqueAuthController_registerFinish",
    "summary": "OPAQUE signup, step 2: create the account",
    "description": "Stores the password and recovery records and signs in. Needs a solved proof-of-work, a Turnstile token when the channel asks, and at most 5 new accounts per IP per day. QA mode (dev only): a `.test` email proven by its code from the test inbox makes a QA account, counted against the shared QA quota instead of the per-IP limit and purged after 7 days.",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/OpaqueRegisterFinishDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ account_id, access_token, refresh_token, expires_in }",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "400": {
      "description": "POW_INVALID, EMAIL_REQUIRED, EMAIL_OTP_REQUIRED, BAD_RECORD, QA_EMAIL_REFUSED (a .test email outside QA mode)"
     },
     "401": {
      "description": "INVALID_CODE or CODE_EXPIRED: the email's code is wrong or old"
     },
     "429": {
      "description": "SIGNUP_LIMIT (per IP), QA_QUOTA_REACHED (QA sign-ups), TOO_MANY_ATTEMPTS"
     },
     "503": {
      "description": "QA_STORE_NOT_READY: QA mode is on but its tables can't be read yet"
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/opaque/register/start": {
   "post": {
    "operationId": "OpaqueAuthController_registerStart",
    "summary": "OPAQUE signup, step 1 (once per credential)",
    "description": "Checks the username is free in the channel and answers the OPAQUE registration request. Call it twice with the same username: once for the password, once for the recovery key.",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/OpaqueRegisterStartDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "409": {
      "description": "USERNAME_TAKEN"
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/passkey/login/options": {
   "post": {
    "operationId": "AuthController_passkeyLoginOptions",
    "summary": "Passkey login, step 1: get options",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PasskeyLoginOptionsDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/passkey/login/verify": {
   "post": {
    "operationId": "AuthController_passkeyLoginVerify",
    "summary": "Passkey login, step 2: verify the assertion and issue tokens",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-install-id",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PasskeyLoginVerifyDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/passkey/register/options": {
   "post": {
    "operationId": "AuthController_passkeyRegisterOptions",
    "summary": "Passkey registration, step 1: get options",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/passkey/register/verify": {
   "post": {
    "operationId": "AuthController_passkeyRegisterVerify",
    "summary": "Passkey registration, step 2: verify and store",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PasskeyRegisterVerifyDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/passkeys": {
   "get": {
    "operationId": "AuthController_listPasskeys",
    "summary": "List the signed-in user's passkeys",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/passkeys/{id}": {
   "delete": {
    "operationId": "AuthController_removePasskey",
    "summary": "Remove one of the signed-in user's passkeys",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/pow": {
   "get": {
    "operationId": "OpaqueAuthController_pow",
    "summary": "Proof-of-work challenge for a new OPAQUE account",
    "description": "Stateless: { salt, bits, exp, sig }. Find a nonce so that sha256(salt ‖ nonce) has `bits` leading zero bits, then send { salt, bits, exp, sig, nonce } as `pow` to /auth/opaque/register/finish. Valid 10 minutes, one account per solution.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/profile": {
   "patch": {
    "operationId": "AuthController_updateProfile",
    "summary": "Update user profile details",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateProfileDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Profile updated successfully",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/recovery-codes": {
   "get": {
    "operationId": "AuthController_recoveryCodesStatus",
    "summary": "How many unused recovery codes remain (never the codes)",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "AuthController_regenerateRecoveryCodes",
    "summary": "Replace all recovery codes (needs a current authenticator code). The new codes are returned once.",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RegenerateRecoveryCodesDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/refresh": {
   "post": {
    "operationId": "AuthController_refresh",
    "summary": "Refresh authentication tokens (Web)",
    "parameters": [],
    "responses": {
     "200": {
      "description": "New tokens issued",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/refresh-app": {
   "post": {
    "operationId": "AuthController_refreshApp",
    "summary": "Refresh authentication tokens (Mobile Apps)",
    "description": "Trade the refresh token for a new pair. Never bound to the IP or user agent. A session signed in with X-Install-Id needs that same header here (401 INSTALL_MISMATCH otherwise: sign in again, refreshing won't help). An older session refreshed with the header becomes bound to that install. 401 UNAUTHENTICATED: the refresh token is unknown, spent, revoked or older than 30 days.",
    "parameters": [
     {
      "name": "x-install-id",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RefreshTokenDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "New tokens issued",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/RefreshResultDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/request-otp": {
   "post": {
    "operationId": "AuthController_requestOtp",
    "summary": "1. Request 6-digit OTP (Login/Register)",
    "description": "Always answers 200 with the same body for any address: an unknown address, an existing account, an account with no saved mobile (delivery sms/whatsapp), a channel closed to new accounts and a blocked new address can't be told apart. A code is sent only when the address can sign in or sign up on this channel (signup policy, or a pending team invite there). The answer takes a minimum time (it follows the route's own speed) and does not wait for delivery. `retryAfterSeconds` says when Resend opens. Resend: 30 s after the first code, 60 s after the second, then 120 s, at most 5 codes per address and channel in 15 minutes (429 OTP_RATE_LIMIT_REACHED, `reason` cooldown or window). Every code sent stays valid for 15 minutes. Wider caps: per address across all channels (429 OTP_RECIPIENT_LIMIT), per IP, IPv6 by /64 network (429 OTP_IP_LIMIT) and per channel (429 OTP_CHANNEL_LIMIT). Every 429 carries the exact `retryAfterSeconds` and a Retry-After header. Parallel requests can't overshoot any of them.",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RequestOtpDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Accepted. `message` is the same for every address; a code was sent if the address can sign in here.",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/RequestOtpResultDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "429": {
      "description": "OTP_RATE_LIMIT_REACHED, OTP_RECIPIENT_LIMIT, OTP_IP_LIMIT or OTP_CHANNEL_LIMIT, with retryAfterSeconds"
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/reset-password": {
   "post": {
    "operationId": "AuthController_resetPassword",
    "summary": "Reset password using an OTP (forgot password)",
    "description": "No current password needed. First call request-otp, then submit the code here with the new password.",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ResetPasswordDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Password reset successfully",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/security/activity": {
   "get": {
    "operationId": "AuthController_securityActivity",
    "summary": "The signed-in user's security log: sign-ins, failed attempts, password / two-factor / passkey changes, session sign-outs (paged, max 100)",
    "parameters": [
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "example": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "description": "Max 100",
      "schema": {
       "minimum": 1,
       "example": 25,
       "type": "number"
      }
     },
     {
      "name": "category",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "sign_in",
        "session",
        "account",
        "mfa",
        "privacy",
        "vault"
       ],
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/security/summary": {
   "get": {
    "operationId": "AuthController_securitySummary",
    "summary": "What protects the signed-in account: password set/changed, two-step methods, passkey and recovery-code counts (flags only)",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/sessions": {
   "get": {
    "operationId": "AuthController_getSessions",
    "summary": "List all active sessions",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/sessions/logout-all": {
   "post": {
    "operationId": "AuthController_revokeAllSessions",
    "summary": "Sign out everywhere: revoke every session and refresh token except this one (step-up)",
    "description": "Needs a step-up in the last 10 minutes (401 STEP_UP_REQUIRED until POST /auth/step-up). With `linked_devices: true` (alias `e2ee_devices`), every linked end-to-end-encrypted device of the account is removed too, except this session's own device; pending device-link tokens stop working. The devices of the revoked sessions stop getting push notifications. revoked_sessions counts only the sessions this call deleted (one removed by a refresh while it runs is skipped). Any value of linked_devices other than a boolean form is 400 VALIDATION_FAILED. A row that cannot be deleted gives 503 SIGN_OUT_INCOMPLETE (send it again).",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/LogoutAllDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/sessions/revoke-all": {
   "post": {
    "operationId": "AuthController_revokeAllSessions_2",
    "summary": "Sign out everywhere: revoke every session and refresh token except this one (step-up)",
    "description": "Needs a step-up in the last 10 minutes (401 STEP_UP_REQUIRED until POST /auth/step-up). With `linked_devices: true` (alias `e2ee_devices`), every linked end-to-end-encrypted device of the account is removed too, except this session's own device; pending device-link tokens stop working. The devices of the revoked sessions stop getting push notifications. revoked_sessions counts only the sessions this call deleted (one removed by a refresh while it runs is skipped). Any value of linked_devices other than a boolean form is 400 VALIDATION_FAILED. A row that cannot be deleted gives 503 SIGN_OUT_INCOMPLETE (send it again).",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/LogoutAllDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/sessions/{id}/revoke": {
   "post": {
    "operationId": "AuthController_revokeSession",
    "summary": "Revoke a specific session",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/sign-in-options": {
   "get": {
    "operationId": "AuthController_signInOptions",
    "summary": "Public: the bot check and sender address for a channel's sign-in pages",
    "description": "Send the channel as x-ref. `captcha` is { provider: 'none' } or { provider: 'turnstile', sitekey }. When it is Turnstile, request-otp, login-password, login-totp and opaque/login/start need the widget's token as `captcha`. `sender` is the address sign-in codes come from.",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": []
   }
  },
  "/auth/step-up": {
   "get": {
    "operationId": "AuthController_stepUpStatus",
    "summary": "Whether this session has confirmed it's you in the last 10 minutes, and the ways it can",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "AuthController_stepUpVerify",
    "summary": "Confirm it's you (passkey, authenticator, password or e-mailed code); lasts 10 minutes for this session",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/StepUpDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/step-up/email": {
   "post": {
    "operationId": "AuthController_stepUpEmail",
    "summary": "E-mail a 6-digit confirmation code to the account's own address",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/step-up/end": {
   "post": {
    "operationId": "AuthController_stepUpEnd",
    "summary": "End the confirmation early",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/step-up/opaque/finish": {
   "post": {
    "operationId": "OpaqueAuthController_stepUpFinish",
    "summary": "Confirm it's you with the account's password (OPAQUE), step 2",
    "description": "Steps up THIS session for 10 minutes, as every step-up method does, and answers the GET /auth/step-up status. No new session and no tokens. If the account has an authenticator, passkey or e-mail codes, nothing is granted yet: the answer is { active: false, mfa_required: true, methods, expires_in: 300 } and the client finishes at /auth/step-up/opaque/second-factor. 401 INVALID_CREDENTIALS for a wrong password and for an expired, used or foreign login_id; 429 TOO_MANY_ATTEMPTS. Recorded as step_up_opaque (failures as step_up_failed, or login_locked at the limit).",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/OpaqueStepUpFinishDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "401": {
      "description": "INVALID_CREDENTIALS"
     },
     "429": {
      "description": "TOO_MANY_ATTEMPTS"
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/step-up/opaque/second-factor": {
   "post": {
    "operationId": "OpaqueAuthController_stepUpSecondFactor",
    "summary": "Confirm it's you with the password (OPAQUE), the second factor",
    "description": "Only after /auth/step-up/opaque/finish answered mfa_required, within 5 minutes, on the same session and client. method = one of its methods: totp (authenticator or recovery code), passkey (assertion for POST /auth/step-up/passkey/options) or email (code from POST /auth/step-up/email). A wrong code can be retried until the step-up lockout; success steps up this session for 10 minutes, once. Errors as at /auth/mfa/*: 401 INVALID_CODE, INVALID_CREDENTIALS (passkey, other client), CODE_EXPIRED (nothing pending, or already used), 400 FACTOR_NOT_AVAILABLE, 429 TOO_MANY_ATTEMPTS.",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/OpaqueStepUpSecondFactorDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "400": {
      "description": "FACTOR_NOT_AVAILABLE"
     },
     "401": {
      "description": "INVALID_CODE, INVALID_CREDENTIALS, CODE_EXPIRED"
     },
     "429": {
      "description": "TOO_MANY_ATTEMPTS"
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/step-up/opaque/start": {
   "post": {
    "operationId": "OpaqueAuthController_stepUpStart",
    "summary": "Confirm it's you with the account's password (OPAQUE), step 1",
    "description": "The OPAQUE login exchange for the signed-in account (the username comes from the session, never the body). credential = password (default) | recovery. Answers { login_id, login_response }; login_id lives 2 minutes, works once, and only for this session from this client. The same lockout as sign-in: 429 TOO_MANY_ATTEMPTS after 10 failed tries an hour, sign-in and step-up together. 400 STEP_UP_METHOD_UNAVAILABLE when the account has no such credential; 404 METHOD_DISABLED when its channel turned OPAQUE off.",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/OpaqueStepUpStartDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "{ login_id, login_response }",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "400": {
      "description": "STEP_UP_METHOD_UNAVAILABLE"
     },
     "429": {
      "description": "TOO_MANY_ATTEMPTS"
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/step-up/passkey/options": {
   "post": {
    "operationId": "AuthController_stepUpPasskeyOptions",
    "summary": "Passkey challenge to confirm it's you",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/switch-business": {
   "post": {
    "operationId": "AuthController_switchProfile",
    "summary": "Stage 2: Switch active profile/business and get new tokens (Web)",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/SwitchProfileDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/switch-business-app": {
   "post": {
    "operationId": "AuthController_switchProfileApp",
    "summary": "Stage 2: Switch active profile/business/channel (Mobile/CRM Apps)",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/SwitchProfileDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/switch-channel": {
   "post": {
    "operationId": "AuthController_switchProfileApp_2",
    "summary": "Stage 2: Switch active profile/business/channel (Mobile/CRM Apps)",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/SwitchProfileDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/switch-profile": {
   "post": {
    "operationId": "AuthController_switchProfile_2",
    "summary": "Stage 2: Switch active profile/business and get new tokens (Web)",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/SwitchProfileDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/switch-profile-app": {
   "post": {
    "operationId": "AuthController_switchProfileApp_3",
    "summary": "Stage 2: Switch active profile/business/channel (Mobile/CRM Apps)",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/SwitchProfileDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/totp/disable": {
   "post": {
    "operationId": "AuthController_totpDisable",
    "summary": "Disable authenticator (TOTP) two-factor",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/EnableTotpDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/totp/enable": {
   "post": {
    "operationId": "AuthController_totpEnable",
    "summary": "Confirm a code to enable TOTP; returns backup codes",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/EnableTotpDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/totp/setup": {
   "post": {
    "operationId": "AuthController_totpSetup",
    "summary": "Start authenticator (TOTP) setup; returns a QR code",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/two-factor": {
   "patch": {
    "operationId": "AuthController_setTwoFactor",
    "summary": "Enable/disable two-factor authentication",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/TwoFactorDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Two-factor preference updated",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Authentication & Profile"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/auth/web/login-password": {
   "post": {
    "operationId": "AuthWebController_loginPassword",
    "summary": "Web: email + password → session cookies (or a pending second factor)",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/LoginPasswordDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Auth"
    ],
    "security": []
   }
  },
  "/auth/web/login-totp": {
   "post": {
    "operationId": "AuthWebController_loginTotp",
    "summary": "Web: email + authenticator code → session cookies",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/LoginTotpDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Auth"
    ],
    "security": []
   }
  },
  "/auth/web/mfa/otp": {
   "post": {
    "operationId": "AuthWebController_mfaOtp",
    "summary": "Web: finish sign-in with an emailed code",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/MfaOtpDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Auth"
    ],
    "security": []
   }
  },
  "/auth/web/mfa/passkey/verify": {
   "post": {
    "operationId": "AuthWebController_mfaPasskeyVerify",
    "summary": "Web: finish sign-in with a passkey",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/MfaPasskeyVerifyDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Auth"
    ],
    "security": []
   }
  },
  "/auth/web/mfa/totp": {
   "post": {
    "operationId": "AuthWebController_mfaTotp",
    "summary": "Web: finish sign-in with an authenticator code",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/MfaTotpDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Auth"
    ],
    "security": []
   }
  },
  "/auth/web/passkey/login/verify": {
   "post": {
    "operationId": "AuthWebController_passkeyLoginVerify",
    "summary": "Web: passkey sign-in → session cookies",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PasskeyLoginVerifyDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Auth"
    ],
    "security": []
   }
  },
  "/banking": {
   "post": {
    "operationId": "BankingController_createBanking",
    "summary": "Create Banking for Business",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateBankingDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Banking created successfully",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Banking"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "BankingController_fetchPersonalBanking",
    "summary": "Fetch All Personal Banking",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Personal Banking list fetched successfully",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Banking"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/banking/delete/{id}": {
   "post": {
    "operationId": "BankingController_deleteBanking",
    "summary": "Delete Banking for Business",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Banking deleted successfully",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Banking"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/banking/update/{id}": {
   "post": {
    "operationId": "BankingController_updateBanking",
    "summary": "Update Banking for Business",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateBankingDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Banking updated successfully",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Banking"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/banking/{businessId}": {
   "get": {
    "operationId": "BankingController_fetchAllBanking",
    "summary": "Fetch All Banking for Business",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Banking list fetched successfully",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Banking"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/banners": {
   "get": {
    "operationId": "BannersController_getBanners",
    "summary": "Fetch a channel's published banners and their images",
    "parameters": [
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "description": "Channel id",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "placement",
      "required": false,
      "in": "query",
      "schema": {
       "example": "home-hero",
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Banners"
    ],
    "security": []
   }
  },
  "/billing/accounts": {
   "post": {
    "operationId": "BillingController_createAccount",
    "summary": "Set up billing for a business you own",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateBillingAccountDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Billing"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/billing/accounts/{businessId}": {
   "get": {
    "operationId": "BillingController_account",
    "summary": "Billing account, standing and credit balance",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Billing"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "BillingController_updateAccount",
    "summary": "Update billing name, email, address or VAT number",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateBillingAccountDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Billing"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/billing/accounts/{businessId}/credit-applications": {
   "post": {
    "operationId": "CreditApplicationsController_create",
    "summary": "Apply for a credit programme (business owner)",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateCreditApplicationDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Billing"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "CreditApplicationsController_list",
    "summary": "This business's credit applications, newest first",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Billing"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/billing/accounts/{businessId}/credits": {
   "get": {
    "operationId": "BillingController_credits",
    "summary": "Credit grants with what is left of each",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Billing"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/billing/accounts/{businessId}/invoices": {
   "get": {
    "operationId": "BillingController_invoices",
    "summary": "Issued invoices, newest first",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Billing"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/billing/accounts/{businessId}/usage": {
   "get": {
    "operationId": "BillingController_usage",
    "summary": "Charges accrued so far this month (not yet invoiced)",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Billing"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/billing/businesses/{businessId}/card": {
   "get": {
    "operationId": "BillingController_card",
    "summary": "The business's card on file (brand, last 4, expiry) and Stripe's publishable key",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Billing"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "BillingController_cardRemove",
    "summary": "Remove the card on file",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Billing"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/billing/businesses/{businessId}/card/confirm": {
   "post": {
    "operationId": "BillingController_cardConfirm",
    "summary": "Make the confirmed card the default: { setup_intent_id }",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Billing"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/billing/businesses/{businessId}/card/setup": {
   "post": {
    "operationId": "BillingController_cardSetup",
    "summary": "Start adding a card: returns a SetupIntent client_secret for Stripe.js",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Billing"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/billing/credit-applications/{id}": {
   "patch": {
    "operationId": "CreditApplicationsController_update",
    "summary": "Revise answers after the reviewer asked for more information",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateCreditApplicationDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Billing"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/billing/credit-programs": {
   "get": {
    "operationId": "CreditApplicationsController_programs",
    "summary": "Credit programmes a business can apply for (amount per currency)",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Billing"
    ],
    "security": []
   }
  },
  "/billing/invoices/{id}": {
   "get": {
    "operationId": "BillingController_invoice",
    "summary": "One invoice with its lines and the credits applied",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Billing"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/billing/invoices/{id}/pay": {
   "post": {
    "operationId": "BillingController_pay",
    "summary": "Settle an open invoice with a successful /payments payment (amount = total due, metadata.invoice_id = this invoice)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PayInvoiceDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Billing"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/billing/plans": {
   "get": {
    "operationId": "BillingController_plans",
    "summary": "Paid app plans and their prices (GBP / USD per month)",
    "parameters": [
     {
      "name": "app_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Billing"
    ],
    "security": []
   }
  },
  "/business/address": {
   "post": {
    "operationId": "BusinessController_updateAddress",
    "summary": "5. Update or create business address details",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateAddressDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Address details saved successfully",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/banking": {
   "post": {
    "operationId": "BusinessController_updateBanking",
    "summary": "4. Update or create business banking details",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateBankingDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Banking details saved successfully",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/channel/create": {
   "post": {
    "operationId": "BusinessController_createChannel",
    "summary": "3. Create a channel for the business",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateChannelDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Channel created successfully",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/documents/types": {
   "get": {
    "operationId": "BusinessOrgController_documentTypes",
    "summary": "Document types a business can upload",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/group": {
   "get": {
    "operationId": "BusinessController_getBusinessGroups",
    "summary": "Get list of Business Groups",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": []
   }
  },
  "/business/groups": {
   "get": {
    "operationId": "BusinessController_getBusinessGroups_2",
    "summary": "Get list of Business Groups",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": []
   }
  },
  "/business/list": {
   "get": {
    "operationId": "BusinessController_getMyBusiness",
    "summary": "Get current user business list",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Business list returned",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/members/{memberId}": {
   "patch": {
    "operationId": "BusinessMembersController_update",
    "summary": "Update a business member (permission/status)",
    "parameters": [
     {
      "name": "memberId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateMemberDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Members"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "BusinessMembersController_remove",
    "summary": "Remove a business member, or leave the business (your own active or suspended seat; not the owner)",
    "parameters": [
     {
      "name": "memberId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Members"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/members/{memberId}/act-for-owner": {
   "put": {
    "operationId": "BusinessMembersController_grantActForOwner",
    "summary": "Owner only, after step-up: let an active admin member act for the owner (billing, paid apps, developer) for 1–365 days",
    "parameters": [
     {
      "name": "memberId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ActForOwnerDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Members"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "BusinessMembersController_revokeActForOwner",
    "summary": "End a member's permission to act for the owner (the owner, or the member themselves). Takes effect at once.",
    "parameters": [
     {
      "name": "memberId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Members"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/register": {
   "post": {
    "operationId": "BusinessController_register",
    "summary": "1. Register a new business",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateBusinessDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Business registered successfully",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "401": {
      "description": "Unauthorized"
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/transfers/{transferId}": {
   "get": {
    "operationId": "BusinessOrgController_incomingTransfer",
    "summary": "A transfer offer addressed to me",
    "parameters": [
     {
      "name": "transferId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/transfers/{transferId}/accept": {
   "post": {
    "operationId": "BusinessOrgController_acceptTransfer",
    "summary": "Step 2: the named account accepts and becomes the owner",
    "parameters": [
     {
      "name": "transferId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "404": {
      "description": "Not a transfer addressed to you"
     },
     "410": {
      "description": "Expired"
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/transfers/{transferId}/decline": {
   "post": {
    "operationId": "BusinessOrgController_declineTransfer",
    "summary": "Decline an ownership transfer addressed to you",
    "parameters": [
     {
      "name": "transferId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/type": {
   "get": {
    "operationId": "BusinessController_getBusinessTypes",
    "summary": "Get list of Business Types",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": []
   }
  },
  "/business/types": {
   "get": {
    "operationId": "BusinessController_getBusinessTypes_2",
    "summary": "Get list of Business Types",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": []
   }
  },
  "/business/update/{id}": {
   "post": {
    "operationId": "BusinessController_update",
    "summary": "2. Update business information by ID",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateBusinessDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Business updated successfully",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/upload/{id}": {
   "post": {
    "operationId": "BusinessController_uploadAssets",
    "summary": "3. Upload business logo and cover",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Assets uploaded successfully",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/verification/types": {
   "get": {
    "operationId": "BusinessOrgController_verificationTypes",
    "summary": "Kinds of organisation and the documents each must upload",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/{businessId}/act-for-owner/me": {
   "get": {
    "operationId": "BusinessMembersController_actForOwnerMe",
    "summary": "Am I the owner, or acting for the owner, of this business?",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Members"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/{businessId}/audit": {
   "get": {
    "operationId": "BusinessAuditController_list",
    "summary": "Audit log of money, access, data and settings changes (owner, newest first)",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "kind",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "money",
        "access",
        "data",
        "settings",
        "support"
       ],
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "maximum": 200,
       "default": 100,
       "type": "number"
      }
     },
     {
      "name": "offset",
      "required": false,
      "in": "query",
      "schema": {
       "default": 0,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/{businessId}/members": {
   "post": {
    "operationId": "BusinessMembersController_invite",
    "summary": "Invite a member to a business",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/InviteMemberDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Members"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "BusinessMembersController_list",
    "summary": "List a business's members",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "status",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Members"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/{id}": {
   "get": {
    "operationId": "BusinessController_getFullBusinessById",
    "summary": "Full business profile by ID. Banking, the address record and the owner's address, location, phone and signatory are for the owner only; members get null for them.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Full business details returned",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/{id}/change-requests": {
   "get": {
    "operationId": "BusinessOrgController_listChangeRequests",
    "summary": "Change requests of a business (paged, max 100)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "default": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "default": 20,
       "type": "number"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "pending",
        "approved",
        "rejected",
        "cancelled"
       ],
       "type": "string"
      }
     },
     {
      "name": "business_id",
      "required": false,
      "in": "query",
      "description": "Only this business's requests (the channel's queue)",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "BusinessOrgController_createChangeRequest",
    "summary": "Request a change to a reviewed field (legal name, address, …)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateChangeRequestDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/{id}/change-requests/batch": {
   "post": {
    "operationId": "BusinessOrgController_createChangeRequests",
    "summary": "Request several changes with one reason and proof (all are stored, or none)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateChangeRequestsDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/{id}/change-requests/{requestId}/cancel": {
   "post": {
    "operationId": "BusinessOrgController_cancelChangeRequest",
    "summary": "Cancel a pending change request",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "requestId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/{id}/close": {
   "post": {
    "operationId": "BusinessOrgController_close",
    "summary": "Close the business (owner only). A soft close: the business and its channels are archived.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CloseBusinessDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/{id}/documents": {
   "get": {
    "operationId": "BusinessOrgController_listDocuments",
    "summary": "Review documents of a business (paged, max 100)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "default": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "default": 20,
       "type": "number"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "pending",
        "verified",
        "rejected"
       ],
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "BusinessOrgController_uploadDocument",
    "summary": "Upload a review document (multipart: file + document_type + document_no?)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "multipart/form-data": {
       "schema": {
        "$ref": "#/components/schemas/UploadDocumentDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/{id}/documents/{documentId}": {
   "delete": {
    "operationId": "BusinessOrgController_removeDocument",
    "summary": "Remove a document (archived; verified documents stay)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "documentId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/{id}/review": {
   "get": {
    "operationId": "BusinessOrgController_getReview",
    "summary": "Review status (draft/submitted/in_review/approved/rejected)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/{id}/review/submit": {
   "post": {
    "operationId": "BusinessOrgController_submitReview",
    "summary": "Submit the business for verification (draft|rejected → submitted)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/{id}/review/withdraw": {
   "post": {
    "operationId": "BusinessOrgController_withdrawReview",
    "summary": "Withdraw a submission before review starts (submitted → draft)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/{id}/transfer": {
   "post": {
    "operationId": "BusinessOrgController_initiateTransfer",
    "summary": "Step 1: owner offers the business to another account (7 days)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/InitiateTransferDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "BusinessOrgController_getTransfer",
    "summary": "The pending ownership transfer, if any",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/{id}/transfer/cancel": {
   "post": {
    "operationId": "BusinessOrgController_cancelTransfer",
    "summary": "Cancel the pending ownership transfer",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/{id}/verification": {
   "get": {
    "operationId": "BusinessOrgController_verificationState",
    "summary": "Verification checklist: details, documents, call and agreement, and what is missing",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/{id}/verification/agreement": {
   "get": {
    "operationId": "BusinessOrgController_verificationAgreement",
    "summary": "The customer agreement to sign (text, version, SHA-256) and the signature if signed",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/{id}/verification/agreement/sign": {
   "post": {
    "operationId": "BusinessOrgController_verificationSign",
    "summary": "Sign the customer agreement electronically (typed full name; version and SHA-256 of the text read)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/{id}/verification/call": {
   "post": {
    "operationId": "BusinessOrgController_verificationCall",
    "summary": "Ask for the verification call with our team (times that suit, phone)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/{id}/verification/call/cancel": {
   "post": {
    "operationId": "BusinessOrgController_verificationCallCancel",
    "summary": "Cancel the requested or booked verification call",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/business/{id}/verification/details": {
   "patch": {
    "operationId": "BusinessOrgController_verificationDetails",
    "summary": "Kind of organisation, legal name, registration and tax numbers, website, signatory",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Business Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/calendar/events": {
   "get": {
    "operationId": "CalendarController_list",
    "summary": "My events in a date window (max 366 days), recurring series expanded into occurrences",
    "parameters": [
     {
      "name": "from",
      "required": true,
      "in": "query",
      "schema": {
       "example": "2026-10-01T00:00:00Z",
       "type": "string"
      }
     },
     {
      "name": "to",
      "required": true,
      "in": "query",
      "schema": {
       "example": "2026-11-01T00:00:00Z",
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "description": "Max occurrences returned (default 500, max 1000)",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Calendar"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "CalendarController_create",
    "summary": "Add a calendar event",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateCalendarEventDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Calendar"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/calendar/events/{id}": {
   "get": {
    "operationId": "CalendarController_getOne",
    "summary": "One of my calendar events (the series)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Calendar"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "CalendarController_update",
    "summary": "Edit a calendar event (the whole series)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateCalendarEventDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Calendar"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "CalendarController_remove",
    "summary": "Delete a calendar event (returns it)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Calendar"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/campaigns": {
   "post": {
    "operationId": "CampaignsController_create",
    "summary": "Create a new campaign",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "multipart/form-data": {
       "schema": {
        "$ref": "#/components/schemas/CreateCampaignDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Campaigns"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "CampaignsController_getAllCampaigns",
    "summary": "Fetch all campaigns (with optional search/filters)",
    "parameters": [
     {
      "name": "q",
      "required": false,
      "in": "query",
      "description": "Global text search query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "category",
      "required": false,
      "in": "query",
      "description": "Filter by category ID",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "description": "Filter by status (e.g. published)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "sort",
      "required": false,
      "in": "query",
      "description": "Sorting string (e.g. -date_created)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "description": "Maximum number of items to return",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "required": false,
      "in": "query",
      "description": "Number of items to skip for pagination",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": false,
      "in": "query",
      "description": "Active profile ID to fetch contextual data (likes, follow status)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "user_profile_id",
      "required": false,
      "in": "query",
      "description": "Filter by author profile id",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "description": "Page number",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Campaigns"
    ],
    "security": []
   }
  },
  "/campaigns/category/{categoryId}": {
   "get": {
    "operationId": "CampaignsController_getCampaignsByCategory",
    "summary": "Fetch campaigns by a specific category ID",
    "parameters": [
     {
      "name": "categoryId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Campaigns"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/campaigns/my": {
   "get": {
    "operationId": "CampaignsController_getMyCampaigns",
    "summary": "Fetch all campaigns created by me",
    "parameters": [
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Campaigns"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/campaigns/search": {
   "get": {
    "operationId": "CampaignsController_searchCampaigns",
    "summary": "Search campaigns by text, category, and pagination",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Campaigns"
    ],
    "security": []
   }
  },
  "/campaigns/statuses": {
   "get": {
    "operationId": "CampaignsController_getStatuses",
    "summary": "Fetch all available campaign statuses",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Campaigns"
    ],
    "security": []
   }
  },
  "/campaigns/trending": {
   "get": {
    "operationId": "CampaignsController_getTrendingCampaigns",
    "summary": "Get trending campaigns feed based on total donations",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Campaigns"
    ],
    "security": []
   }
  },
  "/campaigns/updates/{updateId}": {
   "patch": {
    "operationId": "CampaignsController_updateCampaignUpdate",
    "summary": "Edit an existing campaign update",
    "parameters": [
     {
      "name": "updateId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateCampaignUpdateDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Campaigns"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "CampaignsController_deleteCampaignUpdate",
    "summary": "Delete a campaign update",
    "parameters": [
     {
      "name": "updateId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Campaigns"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/campaigns/{id}": {
   "patch": {
    "operationId": "CampaignsController_update",
    "summary": "Update an existing campaign",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "multipart/form-data": {
       "schema": {
        "$ref": "#/components/schemas/UpdateCampaignDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Campaigns"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "CampaignsController_delete",
    "summary": "Delete a campaign",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Campaigns"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "CampaignsController_getCampaignById",
    "summary": "Get a specific campaign by ID",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Campaigns"
    ],
    "security": []
   }
  },
  "/campaigns/{id}/publish": {
   "post": {
    "operationId": "CampaignsController_publish",
    "summary": "Publish a draft campaign (re-runs moderation; approved -> published)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Campaigns"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/campaigns/{id}/updates": {
   "post": {
    "operationId": "CampaignsController_createUpdate",
    "summary": "Create a new update for a campaign",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateCampaignUpdateDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Campaigns"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "CampaignsController_getUpdates",
    "summary": "Get all updates for a campaign",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Campaigns"
    ],
    "security": []
   }
  },
  "/categories": {
   "get": {
    "operationId": "CategoriesController_list",
    "summary": "",
    "description": "C1: list published categories of a type (default job). Public (guests).",
    "parameters": [
     {
      "name": "type",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "security": []
   }
  },
  "/channel": {
   "post": {
    "operationId": "ChannelController_createMyChannel",
    "summary": "1. Create My Channel",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateChannelDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Channel created successfully",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "ChannelController_getMyChannels",
    "summary": "2. Fetch my channels",
    "description": "The channels of the active business. `has_app=true` keeps the channels with a mobile app (a live or test publishable app key that is not revoked or expired, an app-updates setup, or APNs/FCM push credentials); `has_app=false` keeps the others. With the filter, each channel also carries `has_app`, and archived channels are left out unless `include_archived=true`. Both take exactly `true` or `false`, once; anything else is a 400.",
    "parameters": [
     {
      "name": "include_archived",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "true",
        "false"
       ],
       "type": "string"
      }
     },
     {
      "name": "has_app",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "true",
        "false"
       ],
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Channels list returned",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "400": {
      "description": "has_app or include_archived is not exactly true or false, or is repeated"
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/app-config": {
   "get": {
    "operationId": "ChannelController_appConfig",
    "summary": "Public: everything an app needs at start from its app key",
    "description": "Send the channel's publishable app key as X-App-Key. The same answer as /channel/key-info: the channel's public fields (id, title, logo, domain, installed app ids), `signup` (open | restricted | closed), `branding`, `currency` (ISO 4217, GBP when unset), `media`, `app_key.mode`, and `config`: the entries marked public in Settings › App config (NAME → value; secrets never). Before 1 Nov 2026 this route answered only the `config` map.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/AppKeyChannelDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "400": {
      "description": "No X-App-Key header"
     },
     "401": {
      "description": "Unknown, revoked or expired app key"
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": []
   }
  },
  "/channel/config": {
   "get": {
    "operationId": "ChannelController_serverConfig",
    "summary": "Server: every config entry of the key's channel, secrets included (NAME → value)",
    "description": "For the channel's own servers: a secret API key of the channel with scope channel:config:read. Cache it; never ship it to a browser or app.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/domain-challenge": {
   "get": {
    "operationId": "ChannelController_domainChallenge",
    "summary": "Server: the value the channel's site serves at /.well-known/kodkila-challenge for a host",
    "description": "HTTP proof of a custom domain: the channel's own site answers GET https://<host>/.well-known/kodkila-challenge (the pre-rename /.well-known/westmonk-challenge is still checked until go-live + 90 days) with this value, then Verify in the domain settings (or the site's Domains card) succeeds. Send a secret server key of the channel (Bearer, any scope) or its app key (X-App-Key). Only pending domains of that same channel; 404 otherwise.",
    "parameters": [
     {
      "name": "host",
      "required": true,
      "in": "query",
      "schema": {
       "example": "example.com",
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "example": {
              "host": "example.com",
              "value": "kodkila-verify=…"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "401": {
      "description": "No key of a channel was sent"
     },
     "404": {
      "description": "No pending domain of this channel for that host"
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": []
   }
  },
  "/channel/key-info": {
   "get": {
    "operationId": "ChannelController_keyInfo",
    "summary": "Public: the channel an app key belongs to",
    "description": "Send the channel's publishable app key as X-App-Key. Answers the same public fields as /channel/resolve (title, logo, domain, installed app ids, sign-up mode, branding), so an app needs no separate channel id.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/AppKeyChannelDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "400": {
      "description": "No X-App-Key header"
     },
     "401": {
      "description": "Unknown, revoked or expired app key"
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": []
   }
  },
  "/channel/me": {
   "get": {
    "operationId": "ChannelController_keyChannel",
    "summary": "Server: the channel a secret API key belongs to, with the key's mode and scopes",
    "description": "Any secret API key of the channel (no scope needed). Same public fields as /channel/key-info.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/members/{memberId}": {
   "patch": {
    "operationId": "ChannelMembersController_update",
    "summary": "Update a channel member (permission/status)",
    "parameters": [
     {
      "name": "memberId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateMemberDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Members"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "ChannelMembersController_remove",
    "summary": "Remove a channel member, or leave the channel (your own active or suspended seat; not the owner)",
    "parameters": [
     {
      "name": "memberId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Members"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/public": {
   "get": {
    "operationId": "ChannelController_getChannelByDomainQuery",
    "summary": "Public: Fetch a published channel by exact domain or id (Query Param)",
    "parameters": [
     {
      "name": "domain",
      "required": false,
      "in": "query",
      "schema": {
       "example": "svayam.in",
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": false,
      "in": "query",
      "schema": {
       "example": "65a4a10a-a7d0-4037-abc2-04445fedf8bb",
       "type": "string"
      }
     },
     {
      "name": "search",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Channel details returned",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": []
   }
  },
  "/channel/public/domain/{domain}": {
   "get": {
    "operationId": "ChannelController_getChannelByDomainParam",
    "summary": "Public: Fetch a published channel by exact domain or id (Route Param)",
    "parameters": [
     {
      "name": "domain",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Channel details returned",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": []
   }
  },
  "/channel/resolve": {
   "get": {
    "operationId": "ChannelController_resolveChannel",
    "summary": "Public: resolve the channel serving a hostname",
    "description": "Entry point for storefronts/apps. Looks up the EXACT lowercase hostname in the `domain` collection (published/active/verified rows), then falls back to `channel.domain`. Only published/active channels are returned, and only public fields (no owner, contact, IP or banking data).",
    "parameters": [
     {
      "name": "host",
      "required": true,
      "in": "query",
      "schema": {
       "example": "shop.example.com",
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "The public channel for this host",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "example": {
              "id": "65a4a10a-a7d0-4037-abc2-04445fedf8bb",
              "title": "My Online Store",
              "description": "Official channel for our business",
              "logo": "https://cdn.example.com/logo.png",
              "icon": null,
              "cover": null,
              "domain": "shop.example.com",
              "link": "https://shop.example.com",
              "keywords": "fashion, retail",
              "category": {
               "name": "Retail"
              },
              "business": {
               "tradename": "Acme",
               "logo": null
              },
              "apps": [
               "9b1f0c3e-1d2a-4c5b-8e7f-0a1b2c3d4e5f"
              ]
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "400": {
      "description": "host missing or not a hostname"
     },
     "404": {
      "description": "No channel is configured for this host"
     },
     "429": {
      "description": "Too many requests"
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": []
   }
  },
  "/channel/{channelId}/accounts": {
   "get": {
    "operationId": "ChannelDirectoryController_accounts",
    "summary": "Accounts that signed up on this channel",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "description": "recheck: verified businesses checked again after a change to their legal details (draft = not verified yet)",
      "schema": {
       "default": "all",
       "enum": [
        "all",
        "draft",
        "submitted",
        "in_review",
        "approved",
        "rejected",
        "archived",
        "recheck"
       ],
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "description": "Search name or e-mail",
      "schema": {
       "maxLength": 100,
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel · Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{channelId}/businesses": {
   "get": {
    "operationId": "ChannelDirectoryController_businesses",
    "summary": "Businesses created on this channel (?status=all|draft|submitted|…)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "description": "recheck: verified businesses checked again after a change to their legal details (draft = not verified yet)",
      "schema": {
       "default": "all",
       "enum": [
        "all",
        "draft",
        "submitted",
        "in_review",
        "approved",
        "rejected",
        "archived",
        "recheck"
       ],
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "description": "Search name or e-mail",
      "schema": {
       "maxLength": 100,
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel · Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{channelId}/businesses/{businessId}": {
   "get": {
    "operationId": "ChannelDirectoryController_business",
    "summary": "One business created on this channel",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel · Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{channelId}/businesses/{businessId}/decision": {
   "post": {
    "operationId": "ChannelDirectoryController_decide",
    "summary": "Approve or reject a business created on this channel",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ReviewDecisionDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel · Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{channelId}/businesses/{businessId}/verification": {
   "get": {
    "operationId": "ChannelDirectoryController_verificationState",
    "summary": "Verification checklist of a business created on this channel, with call notes",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel · Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{channelId}/businesses/{businessId}/verification/agreement": {
   "get": {
    "operationId": "ChannelDirectoryController_verificationAgreement",
    "summary": "The agreement text and signature of a business created on this channel",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel · Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{channelId}/businesses/{businessId}/verification/call": {
   "post": {
    "operationId": "ChannelDirectoryController_verificationCall",
    "summary": "Book the verification call (time, meeting link); the business is emailed",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel · Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{channelId}/businesses/{businessId}/verification/call/result": {
   "post": {
    "operationId": "ChannelDirectoryController_verificationCallResult",
    "summary": "Record the call: pass, fail or no_show, with what was checked",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel · Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{channelId}/businesses/{businessId}/verification/invite": {
   "post": {
    "operationId": "ChannelDirectoryController_verificationInvite",
    "summary": "Open (or close) verification for a business while it is invite-only",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel · Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{channelId}/change-requests": {
   "get": {
    "operationId": "ChannelDirectoryController_changeRequests",
    "summary": "Changes to business details waiting for this channel (?status=pending)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "default": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "default": 20,
       "type": "number"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "pending",
        "approved",
        "rejected",
        "cancelled"
       ],
       "type": "string"
      }
     },
     {
      "name": "business_id",
      "required": false,
      "in": "query",
      "description": "Only this business's requests (the channel's queue)",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel · Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{channelId}/change-requests/{requestId}/decision": {
   "post": {
    "operationId": "ChannelDirectoryController_decideChange",
    "summary": "Approve (applies the new value) or reject a change request",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "requestId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ReviewDecisionDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel · Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{channelId}/config/entries": {
   "get": {
    "operationId": "ChannelController_configEntries",
    "summary": "Settings › App config: names, visibility, public values (managers)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{channelId}/config/entries/{name}": {
   "put": {
    "operationId": "ChannelController_setConfig",
    "summary": "Add or replace an entry: { value, visibility: public|secret }",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "name",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "ChannelController_removeConfig",
    "summary": "Remove an entry",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "name",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{channelId}/documents/{documentId}/review": {
   "post": {
    "operationId": "ChannelDirectoryController_document",
    "summary": "Verify or reject a document of a business created on this channel",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "documentId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ReviewDocumentDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel · Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{channelId}/members": {
   "post": {
    "operationId": "ChannelMembersController_invite",
    "summary": "Invite a member to a channel",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/InviteMemberDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Members"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "ChannelMembersController_list",
    "summary": "List a channel's members",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "status",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Members"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{channelId}/signup-policy": {
   "get": {
    "operationId": "ChannelDirectoryController_getSignupPolicy",
    "summary": "Who may create an account on this channel",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel · Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "ChannelDirectoryController_setSignupPolicy",
    "summary": "Open to anyone, restricted to listed e-mails and @domains, or closed to new accounts",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateSignupPolicyDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel · Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{channelId}/stats": {
   "get": {
    "operationId": "ChannelController_stats",
    "summary": "A channel's numbers for a period: orders, revenue by currency, new customers, leads",
    "description": "Channel managers (owner, admins, managers, business admins), or the channel's own server key with orders:read. Every figure is a database aggregate, so it is cheap at any size: use it for dashboards instead of paging /orders/seller. Revenue sums order totals per currency and leaves cancelled orders out. `previous` is the window of the same length just before.",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "period",
      "required": false,
      "in": "query",
      "description": "today: start of today in `tz` until now. 7d / 30d: today and the 6 / 29 days before. custom: `from` to `to` (dates, both days included, at most 366 days).",
      "schema": {
       "default": "today",
       "enum": [
        "today",
        "7d",
        "30d",
        "custom"
       ],
       "type": "string"
      }
     },
     {
      "name": "from",
      "required": false,
      "in": "query",
      "description": "period=custom: first day (YYYY-MM-DD in `tz`) or an ISO date-time",
      "schema": {
       "maxLength": 40,
       "example": "2026-10-01",
       "type": "string"
      }
     },
     {
      "name": "to",
      "required": false,
      "in": "query",
      "description": "period=custom: last day, included (YYYY-MM-DD in `tz`) or an ISO date-time (excluded)",
      "schema": {
       "maxLength": 40,
       "example": "2026-10-31",
       "type": "string"
      }
     },
     {
      "name": "tz",
      "required": false,
      "in": "query",
      "description": "IANA time zone the days are counted in",
      "schema": {
       "maxLength": 64,
       "default": "UTC",
       "example": "Europe/London",
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/ChannelStatsDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "400": {
      "description": "Bad period, dates or time zone"
     },
     "403": {
      "description": "Not a manager of this channel"
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{id}": {
   "get": {
    "operationId": "ChannelController_getMySingleChannel",
    "summary": "3. Fetch my single channel",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Channel details returned",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "ChannelController_updateMyChannel",
    "summary": "4. Update my channel",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateChannelDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Channel updated successfully",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{id}/allowed-origins": {
   "get": {
    "operationId": "ChannelOriginsController_list",
    "summary": "Web origins this channel's browser apps may call the API from",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "ChannelOriginsController_add",
    "summary": "Add an origin (https://host[:port], or http://localhost:* for development)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/OriginDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "400": {
      "description": "ORIGIN_* validation code with a message"
     },
     "409": {
      "description": "ORIGIN_EXISTS or ORIGIN_LIMIT"
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "ChannelOriginsController_remove",
    "summary": "Remove an origin (?origin=, or body { origin })",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "origin",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "404": {
      "description": "ORIGIN_NOT_FOUND"
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{id}/allowed-origins/credentials": {
   "put": {
    "operationId": "ChannelOriginsController_credentials",
    "summary": "Turn credentialed CORS (cookies) on or off for this channel's origins",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/OriginCredentialsDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{id}/archive": {
   "post": {
    "operationId": "ChannelAdminController_archive",
    "summary": "Archive a channel (owner only). Channels are never deleted.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ArchiveChannelDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "409": {
      "description": "Already archived"
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{id}/booking-types": {
   "get": {
    "operationId": "ChannelAdminController_bookingTypes",
    "summary": "The channel's calendar booking types, for every member (no settings access needed)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{id}/domains": {
   "get": {
    "operationId": "ChannelAdminController_listDomains",
    "summary": "Custom domains of a channel with their TXT challenge",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "ChannelAdminController_addDomain",
    "summary": "Add a custom domain; returns the TXT record to create",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/AddDomainDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{id}/domains/{domainId}": {
   "delete": {
    "operationId": "ChannelAdminController_removeDomain",
    "summary": "Remove a domain (archived, never deleted)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "domainId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{id}/domains/{domainId}/verify": {
   "post": {
    "operationId": "ChannelAdminController_verifyDomain",
    "summary": "Check the TXT record in DNS and mark the domain verified",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "domainId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "422": {
      "description": "TXT record not found yet"
     },
     "503": {
      "description": "DNS lookup failed or timed out"
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channel/{id}/settings": {
   "get": {
    "operationId": "ChannelAdminController_getSettings",
    "summary": "Channel settings (all sections, or ?section=)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "section",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "general",
        "channel",
        "notifications",
        "languages",
        "privacy",
        "protection",
        "auth",
        "usernames",
        "calendar",
        "branding",
        "web",
        "system"
       ],
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "ChannelAdminController_patchSettings",
    "summary": "Change keys of one settings section (schema-validated)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PatchChannelSettingsDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel Management"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channels/{channelId}/mail/sender": {
   "get": {
    "operationId": "ChannelMailController_status",
    "summary": "The channel's email sender (no secrets) and how its email goes out now (own / platform until a date / off)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel · Email"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "put": {
    "operationId": "ChannelMailController_save",
    "summary": "Save the sender: provider (smtp, ses, resend, postmark, sendgrid), from name/address, credentials. Used after a test gets through.",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel · Email"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "ChannelMailController_remove",
    "summary": "Remove the sender (the channel's email stops unless the platform relay still covers it)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel · Email"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/channels/{channelId}/mail/sender/test": {
   "post": {
    "operationId": "ChannelMailController_test",
    "summary": "Send a test message through the saved sender; success switches the channel's email to it",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Channel · Email"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/checkout": {
   "post": {
    "operationId": "CheckoutController_checkout",
    "summary": "Process checkout and create order",
    "parameters": [
     {
      "name": "Idempotency-Key",
      "in": "header",
      "description": "Optional client-generated key (8-128 chars, [A-Za-z0-9_-]). A retry with the same key and body replays the first response (Idempotent-Replayed: true); 409 while the first is in flight; 422 if the body differs.",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CheckoutDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Checkout"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}": {
   "get": {
    "operationId": "CloudController_catalog",
    "summary": "Cloud services, what is enabled, and whether ordering is live",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/domains": {
   "post": {
    "operationId": "CloudController_register",
    "summary": "Register a domain: { domain, years, privacy, contact{…registrant} }",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/domains/search": {
   "get": {
    "operationId": "CloudController_domainSearch",
    "summary": "Availability and our yearly price across popular endings: ?q=yourbrand",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/domains/transfer": {
   "get": {
    "operationId": "CloudController_transferCheck",
    "summary": "Can this domain move here, and at what price: ?domain=yourbrand.com",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "domain",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "CloudController_transfer",
    "summary": "Transfer a domain in: { domain, auth_code, privacy?, contact{…registrant} } (paid now, adds a year)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/domains/{id}/auto-renew": {
   "put": {
    "operationId": "CloudController_autoRenew",
    "summary": "Turn auto-renew on or off: { on }",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/domains/{id}/dns": {
   "get": {
    "operationId": "CloudController_dns",
    "summary": "DNS records of a domain",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "CloudController_dnsAdd",
    "summary": "Add a record: { type, host, value, ttl?, priority? }",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/domains/{id}/dns/delete": {
   "post": {
    "operationId": "CloudController_dnsDelete",
    "summary": "Delete a record: { type, host, value }",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/functions": {
   "post": {
    "operationId": "CloudController_fnCreate",
    "summary": "Deploy a function: { name, code } (an ES module with export default { fetch })",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/functions/{id}": {
   "put": {
    "operationId": "CloudController_fnUpdate",
    "summary": "Deploy new code: { code }",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "CloudController_fnDelete",
    "summary": "Delete a function (billing stops today)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/functions/{id}/code": {
   "get": {
    "operationId": "CloudController_fnCode",
    "summary": "A function's current code and URL",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/git": {
   "get": {
    "operationId": "SitesController_connections",
    "summary": "The channel's GitHub and GitLab connections",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/git/github": {
   "post": {
    "operationId": "SitesController_githubStart",
    "summary": "Start installing the GitHub App: returns GitHub's install URL",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/git/github/link": {
   "post": {
    "operationId": "SitesController_githubLink",
    "summary": "Reuse a GitHub connection of another channel in the same business: { connection_id } (you must manage both)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/git/github/shareable": {
   "get": {
    "operationId": "SitesController_githubShareable",
    "summary": "GitHub connections on your other channels of this business that this channel can reuse",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/git/gitlab": {
   "post": {
    "operationId": "SitesController_gitlab",
    "summary": "Connect GitLab: { base_url?, token } (a token with the api scope, kept encrypted)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/git/{id}": {
   "delete": {
    "operationId": "SitesController_disconnect",
    "summary": "Disconnect a git connection no site uses",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/git/{id}/branches": {
   "get": {
    "operationId": "SitesController_branches",
    "summary": "Branches of a repository: ?repo=owner/name (GitHub) or project id (GitLab)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "repo",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "string"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/git/{id}/repos": {
   "get": {
    "operationId": "SitesController_repos",
    "summary": "Repositories a connection can read",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/networks": {
   "post": {
    "operationId": "CloudController_netCreate",
    "summary": "Create a private network: { name, region }",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/networks/{id}": {
   "delete": {
    "operationId": "CloudController_netDelete",
    "summary": "Delete a private network with no servers",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/networks/{id}/servers/{serverId}": {
   "put": {
    "operationId": "CloudController_netAttach",
    "summary": "Attach a server: { on: true } (or detach: { on: false })",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "serverId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/offers/{service}": {
   "get": {
    "operationId": "CloudController_offers",
    "summary": "Plans and our monthly prices per term for hosting, email or ssl",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "service",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/orders/{product}": {
   "post": {
    "operationId": "CloudController_rcOrder",
    "summary": "Order hosting, email or SSL: { plan_id, months, domain, accounts?, contact? } (paid up front)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "product",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/panel": {
   "post": {
    "operationId": "CloudController_panel",
    "summary": "A one-time sign-in link to the control panel (mailboxes, files, certificates)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/provider-catalog": {
   "get": {
    "operationId": "CloudController_providerCatalog",
    "summary": "What the providers offer (read-only)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/resources": {
   "get": {
    "operationId": "CloudController_resources",
    "summary": "The channel's domains, servers… (?service=domains|vm)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "service",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/services/{key}": {
   "put": {
    "operationId": "CloudController_setService",
    "summary": "Enable or disable a service: { enabled }",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "key",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/sites": {
   "get": {
    "operationId": "SitesController_list",
    "summary": "The channel's sites",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "SitesController_create",
    "summary": "Create a site and deploy it: { name, plan, source{kind…}, branch, framework, … env[] } (first month paid now)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/sites/address-check": {
   "get": {
    "operationId": "SitesController_addressCheck",
    "summary": "Whether a default address <slug>.<SITES_BASE_DOMAIN> can be used: ?slug= → { slug, available, reason, url }",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "slug",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/sites/options": {
   "get": {
    "operationId": "SitesController_options",
    "summary": "Plans, build presets and what is set up",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/sites/{id}": {
   "get": {
    "operationId": "SitesController_get",
    "summary": "One site with its domains and deploy hook",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "SitesController_update",
    "summary": "Build settings: { branch, framework, root_dir, commands, port, plan (from next month), redeploy? }",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "SitesController_remove",
    "summary": "Delete a site: stops it and removes its build, keys and hooks. Storage it adopted from an earlier app is kept unless ?delete_adopted_volumes=true",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "delete_adopted_volumes",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/sites/{id}/address": {
   "put": {
    "operationId": "SitesController_setAddress",
    "summary": "Change the site's default address: { slug } → https://<slug>.<SITES_BASE_DOMAIN> (redeploys; the old address stops answering)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/sites/{id}/deploy-hook": {
   "post": {
    "operationId": "SitesController_rotateHook",
    "summary": "Make a new deploy hook URL (the old one stops working)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/sites/{id}/deployments": {
   "get": {
    "operationId": "SitesController_deployments",
    "summary": "Recent deployments",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "SitesController_deploy",
    "summary": "Deploy now: { force? } (force rebuilds without cache)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/sites/{id}/deployments/{dep}/cancel": {
   "post": {
    "operationId": "SitesController_cancel",
    "summary": "Cancel a queued or running deployment",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "dep",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/sites/{id}/deployments/{dep}/log": {
   "get": {
    "operationId": "SitesController_log",
    "summary": "Build log of a deployment",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "dep",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/sites/{id}/domains": {
   "post": {
    "operationId": "SitesController_addDomain",
    "summary": "Add a domain: { domain }. Returns the DNS record to set.",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/sites/{id}/domains/{domainId}": {
   "delete": {
    "operationId": "SitesController_delDomain",
    "summary": "Remove a domain",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "domainId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/sites/{id}/domains/{domainId}/verify": {
   "post": {
    "operationId": "SitesController_verifyDomain",
    "summary": "Check DNS: an A record pointing here, or (behind a proxy like Cloudflare) the TXT proof _kodkila-challenge.<domain> (pre-rename _westmonk-challenge still accepted); then the domain goes live with HTTPS",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "domainId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/sites/{id}/env": {
   "get": {
    "operationId": "SitesController_env",
    "summary": "Environment variables",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "put": {
    "operationId": "SitesController_setEnv",
    "summary": "Add or change variables: { vars: [{ key, value }] }",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/sites/{id}/env/{envId}": {
   "delete": {
    "operationId": "SitesController_delEnv",
    "summary": "Delete a variable",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "envId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/sites/{id}/logs": {
   "get": {
    "operationId": "SitesController_runtime",
    "summary": "The running app's latest log lines",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/sites/{id}/rollback": {
   "post": {
    "operationId": "SitesController_rollback",
    "summary": "Go back to a kept build: { commit }",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/sites/{id}/rollbacks": {
   "get": {
    "operationId": "SitesController_rollbacks",
    "summary": "Builds kept for rollback",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/sites/{id}/volumes": {
   "post": {
    "operationId": "SitesController_addVolume",
    "summary": "Keep a folder's files across deploys: { mount_path } (e.g. /data; used from the next deploy)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/sites/{id}/volumes/delete": {
   "post": {
    "operationId": "SitesController_delVolume",
    "summary": "Stop keeping a folder across deploys: { mount_path }. Its files stay on the server (returned as kept_volume)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/storage": {
   "post": {
    "operationId": "CloudController_bucketCreate",
    "summary": "Create a bucket: { name, region: uk|eu|us|us-west|asia }",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/storage/{id}": {
   "delete": {
    "operationId": "CloudController_bucketDelete",
    "summary": "Delete an empty bucket (billing stops today)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/storage/{id}/keys": {
   "post": {
    "operationId": "CloudController_bucketKey",
    "summary": "New S3 credentials for a bucket { label, read_only } (the secret is shown once)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/storage/{id}/keys/{keyId}": {
   "delete": {
    "operationId": "CloudController_bucketKeyDelete",
    "summary": "Delete a bucket's credentials",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "keyId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/storage/{id}/public": {
   "put": {
    "operationId": "CloudController_bucketPublic",
    "summary": "Serve the bucket publicly from the CDN: { on }",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/vm": {
   "post": {
    "operationId": "CloudController_vmCreate",
    "summary": "Create a server: { name, plan, region, image, ssh_key }",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/vm/options": {
   "get": {
    "operationId": "CloudController_vmOptions",
    "summary": "Plans with our monthly prices, regions and OS images",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/vm/{id}": {
   "delete": {
    "operationId": "CloudController_vmCancel",
    "summary": "Cancel a server (billing stops today)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/vm/{id}/actions/{action}": {
   "post": {
    "operationId": "CloudController_vmAction",
    "summary": "Start, stop or restart a server",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "action",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/vm/{id}/refresh": {
   "post": {
    "operationId": "CloudController_vmRefresh",
    "summary": "Refresh status and IP from the provider",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/vm/{id}/snapshots": {
   "get": {
    "operationId": "CloudController_snapshots",
    "summary": "Snapshots of a server",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "CloudController_snapshot",
    "summary": "Take a snapshot: { name? }",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/vm/{id}/snapshots/{sid}": {
   "delete": {
    "operationId": "CloudController_snapshotDelete",
    "summary": "Delete a snapshot",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "sid",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/channels/{channelId}/vm/{id}/snapshots/{sid}/restore": {
   "post": {
    "operationId": "CloudController_restore",
    "summary": "Restore a server to a snapshot (data after it is lost)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "sid",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/git/github/callback": {
   "post": {
    "operationId": "SitesHooksController_githubCallback",
    "summary": "Finish connecting GitHub: { state, installation_id, code } from GitHub's redirect",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cloud/hooks/deploy/{siteId}/{token}": {
   "post": {
    "operationId": "SitesHooksController_deployHook",
    "summary": "Deploy hook: POST from CI or a CMS to deploy the site",
    "parameters": [
     {
      "name": "siteId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "token",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": []
   }
  },
  "/cloud/hooks/github": {
   "post": {
    "operationId": "SitesHooksController_github",
    "summary": "GitHub App webhook (signed): pushes deploy matching sites",
    "parameters": [
     {
      "name": "x-github-event",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-hub-signature-256",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": []
   }
  },
  "/cloud/hooks/gitlab/{siteId}": {
   "post": {
    "operationId": "SitesHooksController_gitlab",
    "summary": "GitLab push webhook of one site (X-Gitlab-Token)",
    "parameters": [
     {
      "name": "siteId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-gitlab-token",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Cloud · Sites"
    ],
    "security": []
   }
  },
  "/cms/channels/{channelId}/banners": {
   "get": {
    "operationId": "BannersAdminController_list",
    "summary": "List the channel's banners (all statuses)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "default": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "default": 20,
       "type": "number"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "draft",
        "published",
        "archived"
       ],
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "description": "Search in the title/name",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Banners"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "BannersAdminController_create",
    "summary": "Create a banner (draft by default)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateBannerDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Banners"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/banners/{bannerId}": {
   "get": {
    "operationId": "BannersAdminController_get",
    "summary": "Get a banner with its images",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "bannerId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Banners"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "BannersAdminController_update",
    "summary": "Update a banner (name, placement, window, status)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "bannerId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateBannerDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Banners"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "BannersAdminController_remove",
    "summary": "Delete a banner and its images",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "bannerId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Banners"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/banners/{bannerId}/images": {
   "post": {
    "operationId": "BannersAdminController_addImage",
    "summary": "Add an image/slide to a banner",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "bannerId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/BannerImageDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Banners"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/banners/{bannerId}/images/{imageId}": {
   "patch": {
    "operationId": "BannersAdminController_updateImage",
    "summary": "Update a banner image",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "bannerId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "imageId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/BannerImageDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Banners"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "BannersAdminController_removeImage",
    "summary": "Delete a banner image",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "bannerId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "imageId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Banners"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/collections": {
   "get": {
    "operationId": "CollectionsAdminController_list",
    "summary": "List the channel's collections with product counts",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "default": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "default": 20,
       "type": "number"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "draft",
        "published",
        "archived"
       ],
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "description": "Search in the title/name",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Collections"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "CollectionsAdminController_create",
    "summary": "Create a collection",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "Idempotency-Key",
      "in": "header",
      "description": "Optional client-generated key (8-128 chars, [A-Za-z0-9_-]). A retry with the same key and body replays the first response (Idempotent-Replayed: true); 409 while the first is in flight; 422 if the body differs.",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateCollectionDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Collections"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/collections/{id}": {
   "patch": {
    "operationId": "CollectionsAdminController_update",
    "summary": "Edit a collection",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateCollectionDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Collections"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "CollectionsAdminController_remove",
    "summary": "Delete a collection (products stay; children move to the root)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Collections"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/doc-versions": {
   "get": {
    "operationId": "CmsDocVersionsController_list",
    "summary": "Versions with page counts, what latest resolves to, and deprecation",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/DocVersionsAdminResultDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Docs"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/doc-versions/{name}": {
   "put": {
    "operationId": "CmsDocVersionsController_put",
    "summary": "Create or change a version's settings: label, is_latest, deprecated + banner, order",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "name",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PutDocVersionDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/DocVersionRecordDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "400": {
      "description": "Bad version tag (errorCode: DOC_VERSION_INVALID)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Docs"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "CmsDocVersionsController_remove",
    "summary": "Delete a version's settings",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "name",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/DocVersionDeletedDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "404": {
      "description": "No settings for this version (errorCode: DOC_VERSION_NOT_FOUND)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "409": {
      "description": "The version still has pages (errorCode: DOC_VERSION_HAS_PAGES)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Docs"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/doc-versions/{name}/clone": {
   "post": {
    "operationId": "CmsDocVersionsController_clone",
    "summary": "Start this version as a copy of another (copies start as drafts unless as_draft is false)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "name",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CloneDocVersionDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Copied",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/DocCloneResultDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "400": {
      "description": "Bad version tags (errorCode: DOC_VERSION_INVALID, DOC_SAME_VERSION)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "404": {
      "description": "The source version has no pages (errorCode: DOC_VERSION_NOT_FOUND)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "409": {
      "description": "The target version already has pages (errorCode: DOC_VERSION_NOT_EMPTY, DOC_BUSY)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Docs"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/docs": {
   "get": {
    "operationId": "CmsDocsController_list",
    "summary": "List the channel's doc pages (all statuses; no bodies)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 10000,
       "default": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "default": 20,
       "type": "number"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "draft",
        "published",
        "archived"
       ],
       "type": "string"
      }
     },
     {
      "name": "version",
      "required": false,
      "in": "query",
      "schema": {
       "pattern": "^(?!latest$)[a-z0-9][a-z0-9._-]{0,31}$",
       "example": "v1",
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "description": "Search in the title and path",
      "schema": {
       "maxLength": 100,
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/DocListResultDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Docs"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "CmsDocsController_create",
    "summary": "Create a doc page or sidebar group (Markdown is made safe; the answer lists changes as warnings)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateDocDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Created",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/DocWriteResultDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "400": {
      "description": "Invalid page (errorCode: DOC_TITLE_REQUIRED, DOC_PARENT_NOT_FOUND, DOC_PARENT_OTHER_VERSION, DOC_DEPTH_LIMIT, DOC_LIMIT_REACHED, DOC_GROUP_HAS_BODY, DOC_VERSION_INVALID)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "409": {
      "description": "The path is taken, or another change is running (errorCode: DOC_PATH_TAKEN, DOC_BUSY)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "422": {
      "description": "The Markdown is too long, nests too deep, has too many table columns or unmatched brackets, or takes over 2 s to process (errorCode: DOC_TOO_COMPLEX)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "503": {
      "description": "Every Markdown worker is busy; retry shortly (errorCode: DOC_MARKDOWN_BUSY)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Docs"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/docs/preview": {
   "post": {
    "operationId": "CmsDocsController_preview",
    "summary": "Check Markdown without saving: the safe Markdown, TOC, reading time and warnings",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PreviewDocDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/DocPreviewResultDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "422": {
      "description": "The Markdown is too long, nests too deep, has too many table columns or unmatched brackets, or takes over 2 s to process (errorCode: DOC_TOO_COMPLEX)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "503": {
      "description": "Every Markdown worker is busy; retry shortly (errorCode: DOC_MARKDOWN_BUSY)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Docs"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/docs/reorder": {
   "post": {
    "operationId": "CmsDocsController_reorder",
    "summary": "Move and reorder pages of one version in one go (all or nothing; paths follow)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ReorderDocsDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/DocReorderResultDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "400": {
      "description": "Impossible moves (errorCode: DOC_CYCLE, DOC_DEPTH_LIMIT, DOC_NOT_FOUND, DOC_PARENT_NOT_FOUND, DOC_VERSION_INVALID)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "409": {
      "description": "Two pages would share a path, or another change is running (errorCode: DOC_PATH_TAKEN, DOC_BUSY)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Docs"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/docs/tree": {
   "get": {
    "operationId": "CmsDocsController_tree",
    "summary": "Every page and group of a version as a tree, drafts included (default: the latest version)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "version",
      "required": false,
      "in": "query",
      "description": "Default: the latest version",
      "schema": {
       "pattern": "^(?!latest$)[a-z0-9][a-z0-9._-]{0,31}$",
       "example": "v1",
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/DocTreeResultDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "400": {
      "description": "Bad version tag (errorCode: DOC_VERSION_INVALID)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Docs"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/docs/{id}": {
   "get": {
    "operationId": "CmsDocsController_get",
    "summary": "One doc page with its Markdown",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/DocAdminDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "404": {
      "description": "No such page in this channel (errorCode: DOC_NOT_FOUND)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Docs"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "CmsDocsController_update",
    "summary": "Update a doc page (a new slug or parent moves the pages under it too, atomically)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateDocDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/DocWriteResultDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "400": {
      "description": "Invalid change (errorCode: DOC_TITLE_REQUIRED, DOC_CYCLE, DOC_DEPTH_LIMIT, DOC_PARENT_NOT_FOUND, DOC_PARENT_OTHER_VERSION, DOC_GROUP_HAS_BODY)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "404": {
      "description": "No such page in this channel (errorCode: DOC_NOT_FOUND)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "409": {
      "description": "The new path is taken, or another change is running (errorCode: DOC_PATH_TAKEN, DOC_BUSY)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "422": {
      "description": "The Markdown is too long, nests too deep, has too many table columns or unmatched brackets, or takes over 2 s to process (errorCode: DOC_TOO_COMPLEX)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "503": {
      "description": "Every Markdown worker is busy; retry shortly (errorCode: DOC_MARKDOWN_BUSY)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Docs"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "CmsDocsController_remove",
    "summary": "Delete a doc page",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/DocDeletedDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "404": {
      "description": "No such page in this channel (errorCode: DOC_NOT_FOUND)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "409": {
      "description": "It still has pages under it (errorCode: DOC_HAS_CHILDREN, DOC_BUSY)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Docs"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/email-templates": {
   "get": {
    "operationId": "EmailTemplatesController_list",
    "summary": "List the channel's email templates",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "default": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "default": 20,
       "type": "number"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "draft",
        "published",
        "archived"
       ],
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "description": "Search in the title/name",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Email templates"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "EmailTemplatesController_create",
    "summary": "Create an email template (key unique per channel)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateEmailTemplateDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Email templates"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/email-templates/system": {
   "get": {
    "operationId": "EmailTemplatesController_system",
    "summary": "Emails sent on the channel's behalf (sign-in codes, invites, notifications) with their built-in copy, and whether the channel customised each",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Email templates"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/email-templates/{id}": {
   "get": {
    "operationId": "EmailTemplatesController_get",
    "summary": "Get an email template",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Email templates"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "EmailTemplatesController_update",
    "summary": "Update an email template (incl. status)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateEmailTemplateDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Email templates"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "EmailTemplatesController_remove",
    "summary": "Delete an email template",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Email templates"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/email-templates/{id}/preview": {
   "post": {
    "operationId": "EmailTemplatesController_preview",
    "summary": "Render with sample variables → {subject, html, text, missing}. {{x}} is HTML-escaped",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PreviewEmailTemplateDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Email templates"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/faq/categories": {
   "get": {
    "operationId": "FaqAdminController_listGroups",
    "summary": "List the channel's FAQ categories",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · FAQ"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "FaqAdminController_createGroup",
    "summary": "Create a FAQ category (max 3 levels deep)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateFaqGroupDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · FAQ"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/faq/categories/{groupId}": {
   "patch": {
    "operationId": "FaqAdminController_updateGroup",
    "summary": "Update / move a FAQ category",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "groupId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateFaqGroupDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · FAQ"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "FaqAdminController_removeGroup",
    "summary": "Delete an empty FAQ category",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "groupId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · FAQ"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/faq/items": {
   "get": {
    "operationId": "FaqAdminController_listFaqs",
    "summary": "List the channel's FAQs (all statuses)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "default": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "default": 20,
       "type": "number"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "draft",
        "published",
        "archived"
       ],
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "description": "Search in the title/name",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "group_id",
      "required": false,
      "in": "query",
      "description": "Only this category",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · FAQ"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "FaqAdminController_createFaq",
    "summary": "Create a FAQ (answer is sanitized HTML)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateFaqDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · FAQ"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/faq/items/{faqId}": {
   "patch": {
    "operationId": "FaqAdminController_updateFaq",
    "summary": "Update a FAQ (incl. publish/unpublish via status)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "faqId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateFaqDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · FAQ"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "FaqAdminController_removeFaq",
    "summary": "Delete a FAQ",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "faqId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · FAQ"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/layout": {
   "get": {
    "operationId": "CmsLayoutController_get",
    "summary": "Get the channel's layout/theme settings",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Layout"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "put": {
    "operationId": "CmsLayoutController_put",
    "summary": "Replace the layout/theme (schema-validated, max 16 KB)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/SiteLayoutDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Layout"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/menus": {
   "get": {
    "operationId": "CmsMenusController_list",
    "summary": "List the channel's menus",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Menus"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "CmsMenusController_create",
    "summary": "Create a menu",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateMenuDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Menus"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/menus/{menuId}": {
   "get": {
    "operationId": "CmsMenusController_get",
    "summary": "Get a menu with its item tree",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "menuId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Menus"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "CmsMenusController_update",
    "summary": "Update a menu (name, location, status)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "menuId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateMenuDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Menus"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "CmsMenusController_remove",
    "summary": "Delete a menu and all its items",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "menuId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Menus"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/menus/{menuId}/items": {
   "post": {
    "operationId": "CmsMenusController_addItem",
    "summary": "Add a menu item",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "menuId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateMenuItemDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Menus"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/menus/{menuId}/items/order": {
   "put": {
    "operationId": "CmsMenusController_reorder",
    "summary": "Re-parent/re-sort every item of the menu",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "menuId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ReorderMenuItemsDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Menus"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/menus/{menuId}/items/{itemId}": {
   "patch": {
    "operationId": "CmsMenusController_updateItem",
    "summary": "Update / move a menu item",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "menuId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "itemId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateMenuItemDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Menus"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "CmsMenusController_removeItem",
    "summary": "Delete a menu item and its sub-items",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "menuId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "itemId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Menus"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/pages": {
   "get": {
    "operationId": "PagesAdminController_list",
    "summary": "List the channel's pages (all statuses)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "default": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "default": 20,
       "type": "number"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "draft",
        "published",
        "archived"
       ],
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "description": "Search in the title/name",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Pages"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "PagesAdminController_create",
    "summary": "Create a page (draft by default)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreatePageDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Pages"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/pages/{pageId}": {
   "get": {
    "operationId": "PagesAdminController_get",
    "summary": "Get a page with its sections",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "pageId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Pages"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "PagesAdminController_update",
    "summary": "Update a page (title, slug, SEO, status)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "pageId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdatePageDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Pages"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "PagesAdminController_remove",
    "summary": "Delete a page and its sections",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "pageId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Pages"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/pages/{pageId}/publish": {
   "post": {
    "operationId": "PagesAdminController_publish",
    "summary": "Publish a page",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "pageId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Pages"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/pages/{pageId}/sections": {
   "post": {
    "operationId": "PagesAdminController_addSection",
    "summary": "Add a section (content is sanitized HTML)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "pageId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateSectionDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Pages"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/pages/{pageId}/sections/order": {
   "put": {
    "operationId": "PagesAdminController_reorder",
    "summary": "Reorder sections: ids = every section, in order",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "pageId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ReorderDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Pages"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/pages/{pageId}/sections/{sectionId}": {
   "patch": {
    "operationId": "PagesAdminController_updateSection",
    "summary": "Update a section",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "pageId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "sectionId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateSectionDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Pages"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "PagesAdminController_removeSection",
    "summary": "Delete a section",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "pageId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "sectionId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Pages"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/pages/{pageId}/unpublish": {
   "post": {
    "operationId": "PagesAdminController_unpublish",
    "summary": "Unpublish a page (back to draft)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "pageId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Pages"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/posts": {
   "get": {
    "operationId": "CmsBlogController_list",
    "summary": "List the channel's blog posts (all statuses)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "default": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "default": 20,
       "type": "number"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "description": "Search in the title/name",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "draft",
        "scheduled",
        "published",
        "archived"
       ],
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Blog"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "CmsBlogController_create",
    "summary": "Create a blog post (body is sanitized)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateBlogPostDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Blog"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/posts/{id}": {
   "get": {
    "operationId": "CmsBlogController_get",
    "summary": "One blog post with its body",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Blog"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "CmsBlogController_update",
    "summary": "Update a blog post (incl. status / schedule)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateBlogPostDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Blog"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "CmsBlogController_remove",
    "summary": "Delete a blog post",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Blog"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/posts/{id}/cover": {
   "post": {
    "operationId": "CmsBlogController_cover",
    "summary": "Upload the post's cover image (field: image)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Blog"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/reviews": {
   "get": {
    "operationId": "ReviewsAdminController_list",
    "summary": "List the channel's customer reviews",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 10000,
       "default": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "default": 20,
       "type": "number"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "published",
        "hidden"
       ],
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "description": "Search in the title / text",
      "schema": {
       "maxLength": 100,
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Reviews"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/reviews/{id}": {
   "patch": {
    "operationId": "ReviewsAdminController_moderate",
    "summary": "Show or hide a review",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ModerateReviewDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Reviews"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/surfaces": {
   "get": {
    "operationId": "CmsSurfacesController_list",
    "summary": "The channel's home surfaces (summaries)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Home surfaces"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "CmsSurfacesController_create",
    "summary": "Create a surface (a draft; publish it when ready)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateSurfaceDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Home surfaces"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/surfaces/check-block": {
   "post": {
    "operationId": "CmsSurfacesController_check",
    "summary": "Validate one block without saving it (returns its stored form or 400 with every problem)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CheckBlockDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Home surfaces"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/surfaces/images": {
   "post": {
    "operationId": "CmsSurfacesController_image",
    "summary": "Upload an image for the channel's surfaces (field: image; PNG, JPEG, WebP or GIF, up to 2 MB) → {id, url}; use id as a block's image",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Home surfaces"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/surfaces/{surface}": {
   "get": {
    "operationId": "CmsSurfacesController_get",
    "summary": "One surface: its draft blocks, status and published summary (ETag = version)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "surface",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Home surfaces"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "put": {
    "operationId": "CmsSurfacesController_replace",
    "summary": "Replace the draft: title, description and/or the whole ordered block list",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "surface",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "if-match",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "If-Match",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ReplaceSurfaceDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Home surfaces"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "CmsSurfacesController_remove",
    "summary": "Delete a surface (it disappears from clients at once)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "surface",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "if-match",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "version",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "If-Match",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Home surfaces"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/surfaces/{surface}/blocks": {
   "post": {
    "operationId": "CmsSurfacesController_add",
    "summary": "Add one block (at `position`, default the end)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "surface",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "if-match",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/AddBlockDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Home surfaces"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/surfaces/{surface}/blocks/order": {
   "put": {
    "operationId": "CmsSurfacesController_reorder",
    "summary": "Reorder: every block id, in the new order",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "surface",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "if-match",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ReorderBlocksDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Home surfaces"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/surfaces/{surface}/blocks/{blockId}": {
   "patch": {
    "operationId": "CmsSurfacesController_update",
    "summary": "Change one block (null clears a field)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "surface",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "blockId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "if-match",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateBlockDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Home surfaces"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "CmsSurfacesController_removeBlock",
    "summary": "Remove one block",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "surface",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "blockId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "if-match",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "version",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Home surfaces"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/surfaces/{surface}/discard": {
   "post": {
    "operationId": "CmsSurfacesController_discard",
    "summary": "Drop unpublished changes: the draft goes back to what is published",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "surface",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "if-match",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/VersionDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Home surfaces"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/surfaces/{surface}/history": {
   "get": {
    "operationId": "CmsSurfacesController_history",
    "summary": "Who changed and published the surface, newest first (max 100): by is the person's name (or address when they have none), by_email their address",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "surface",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Home surfaces"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/surfaces/{surface}/preview": {
   "get": {
    "operationId": "CmsSurfacesController_preview",
    "summary": "What one audience sees: the draft (default) or the published surface, filtered like the public read",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "surface",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "of",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "draft",
        "published"
       ],
       "type": "string"
      }
     },
     {
      "name": "at",
      "required": false,
      "in": "query",
      "description": "ISO time to preview a schedule",
      "schema": {}
     },
     {
      "name": "country",
      "required": false,
      "in": "query",
      "schema": {
       "example": "GB"
      }
     },
     {
      "name": "platform",
      "required": false,
      "in": "query",
      "schema": {
       "example": "windows"
      }
     },
     {
      "name": "locale",
      "required": false,
      "in": "query",
      "schema": {
       "example": "en-GB"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Home surfaces"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/surfaces/{surface}/publish": {
   "post": {
    "operationId": "CmsSurfacesController_publish",
    "summary": "Publish the draft as it is at `version`; clients refresh within seconds",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "surface",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "if-match",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/VersionDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Home surfaces"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/surfaces/{surface}/unpublish": {
   "post": {
    "operationId": "CmsSurfacesController_unpublish",
    "summary": "Take the surface off clients (the draft stays)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "surface",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "if-match",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/VersionDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Home surfaces"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/testimonials": {
   "get": {
    "operationId": "CmsTestimonialsController_list",
    "summary": "List the channel's testimonials (all statuses)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "default": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "default": 20,
       "type": "number"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "draft",
        "published",
        "archived"
       ],
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "description": "Search in the title/name",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Testimonials"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "CmsTestimonialsController_create",
    "summary": "Create a testimonial",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateTestimonialDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Testimonials"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/channels/{channelId}/testimonials/{id}": {
   "patch": {
    "operationId": "CmsTestimonialsController_update",
    "summary": "Update a testimonial (incl. status)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateTestimonialDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Testimonials"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "CmsTestimonialsController_remove",
    "summary": "Delete a testimonial",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Testimonials"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/cms/docs/nav": {
   "get": {
    "operationId": "CmsPublicDocsController_nav",
    "summary": "The sidebar of a version: nested {id, kind, title, path, deprecated, children} (Public; weak ETag)",
    "parameters": [
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "description": "The channel, when no X-App-Key / x-ref is sent",
      "schema": {
       "format": "uuid",
       "type": "string"
      }
     },
     {
      "name": "version",
      "required": false,
      "in": "query",
      "description": "A version tag, or latest (default)",
      "schema": {
       "maxLength": 32,
       "example": "latest",
       "type": "string"
      }
     },
     {
      "name": "X-App-Key",
      "in": "header",
      "description": "The channel's app key (names the channel)",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "in": "header",
      "description": "Or the channel id",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "If-None-Match",
      "in": "header",
      "description": "A previous weak ETag; a match answers 304",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK. Headers: ETag (weak), Cache-Control (public, short), Vary: Accept-Encoding, X-App-Key, X-Ref",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/PublicDocNavDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "304": {
      "description": "Not modified (If-None-Match matched the weak ETag); no body"
     },
     "400": {
      "description": "No channel, or a bad version tag (errorCode: DOC_CHANNEL_REQUIRED, DOC_VERSION_INVALID)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "404": {
      "description": "Nothing published there (errorCode: DOC_VERSION_NOT_FOUND)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Public"
    ],
    "security": []
   }
  },
  "/cms/docs/page": {
   "get": {
    "operationId": "CmsPublicDocsController_page",
    "summary": "One page by path: Markdown, TOC, reading time, breadcrumbs, prev/next, deprecation, other versions (Public; weak ETag)",
    "parameters": [
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "description": "The channel, when no X-App-Key / x-ref is sent",
      "schema": {
       "format": "uuid",
       "type": "string"
      }
     },
     {
      "name": "version",
      "required": false,
      "in": "query",
      "description": "A version tag, or latest (default)",
      "schema": {
       "maxLength": 32,
       "example": "latest",
       "type": "string"
      }
     },
     {
      "name": "path",
      "required": true,
      "in": "query",
      "description": "The page's full path (leading/trailing slashes and case are ignored)",
      "schema": {
       "maxLength": 700,
       "example": "guides/auth/sessions",
       "type": "string"
      }
     },
     {
      "name": "X-App-Key",
      "in": "header",
      "description": "The channel's app key (names the channel)",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "in": "header",
      "description": "Or the channel id",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "If-None-Match",
      "in": "header",
      "description": "A previous weak ETag; a match answers 304",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK. Headers: ETag (weak), Cache-Control (public, short), Vary: Accept-Encoding, X-App-Key, X-Ref",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/PublicDocPageDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "304": {
      "description": "Not modified (If-None-Match matched the weak ETag); no body"
     },
     "400": {
      "description": "No channel, or a bad version tag (errorCode: DOC_CHANNEL_REQUIRED, DOC_VERSION_INVALID)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "404": {
      "description": "Nothing published there (errorCode: DOC_NOT_FOUND, DOC_VERSION_NOT_FOUND)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Public"
    ],
    "security": []
   }
  },
  "/cms/docs/search": {
   "get": {
    "operationId": "CmsPublicDocsController_search",
    "summary": "Search a version's live pages: title, path, breadcrumbs, excerpt, matching headings, highlight offsets (Public; weak ETag)",
    "parameters": [
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "description": "The channel, when no X-App-Key / x-ref is sent",
      "schema": {
       "format": "uuid",
       "type": "string"
      }
     },
     {
      "name": "version",
      "required": false,
      "in": "query",
      "description": "A version tag, or latest (default)",
      "schema": {
       "maxLength": 32,
       "example": "latest",
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": true,
      "in": "query",
      "schema": {
       "maxLength": 200,
       "example": "refresh token",
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 50,
       "default": 10,
       "type": "number"
      }
     },
     {
      "name": "X-App-Key",
      "in": "header",
      "description": "The channel's app key (names the channel)",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "in": "header",
      "description": "Or the channel id",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "If-None-Match",
      "in": "header",
      "description": "A previous weak ETag; a match answers 304",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK. Headers: ETag (weak), Cache-Control (public, short), Vary: Accept-Encoding, X-App-Key, X-Ref",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/PublicDocSearchDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "304": {
      "description": "Not modified (If-None-Match matched the weak ETag); no body"
     },
     "400": {
      "description": "No channel, or a bad version tag (errorCode: DOC_CHANNEL_REQUIRED, DOC_VERSION_INVALID)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "404": {
      "description": "Nothing published there (errorCode: DOC_VERSION_NOT_FOUND)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Public"
    ],
    "security": []
   }
  },
  "/cms/docs/versions": {
   "get": {
    "operationId": "CmsPublicDocsController_versions",
    "summary": "Readable docs versions, which one latest is, and deprecation banners (Public; weak ETag)",
    "parameters": [
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "description": "The channel, when no X-App-Key / x-ref is sent",
      "schema": {
       "format": "uuid",
       "type": "string"
      }
     },
     {
      "name": "version",
      "required": false,
      "in": "query",
      "description": "A version tag, or latest (default)",
      "schema": {
       "maxLength": 32,
       "example": "latest",
       "type": "string"
      }
     },
     {
      "name": "X-App-Key",
      "in": "header",
      "description": "The channel's app key (names the channel)",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "in": "header",
      "description": "Or the channel id",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "If-None-Match",
      "in": "header",
      "description": "A previous weak ETag; a match answers 304",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK. Headers: ETag (weak), Cache-Control (public, short), Vary: Accept-Encoding, X-App-Key, X-Ref",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/PublicDocVersionsDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "304": {
      "description": "Not modified (If-None-Match matched the weak ETag); no body"
     },
     "400": {
      "description": "No channel, or a bad version tag (errorCode: DOC_CHANNEL_REQUIRED, DOC_VERSION_INVALID)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorEnvelope"
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Public"
    ],
    "security": []
   }
  },
  "/cms/public/{channelId}/layout": {
   "get": {
    "operationId": "CmsPublicController_layoutFor",
    "summary": "Site layout / theme settings (Public)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Public"
    ],
    "security": []
   }
  },
  "/cms/public/{channelId}/menus": {
   "get": {
    "operationId": "CmsPublicController_menusFor",
    "summary": "Published menus with their item trees (Public)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "location",
      "required": false,
      "in": "query",
      "schema": {
       "example": "header",
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Public"
    ],
    "security": []
   }
  },
  "/cms/public/{channelId}/posts": {
   "get": {
    "operationId": "CmsPublicController_postsFor",
    "summary": "Live blog posts, newest first (Public, max 50)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Public"
    ],
    "security": []
   }
  },
  "/cms/public/{channelId}/posts/{slug}": {
   "get": {
    "operationId": "CmsPublicController_postFor",
    "summary": "One live blog post by slug (Public)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "slug",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Public"
    ],
    "security": []
   }
  },
  "/cms/public/{channelId}/surfaces/{surface}": {
   "get": {
    "operationId": "CmsPublicSurfacesController_read",
    "summary": "A published home surface for one audience: {banners[], shortcuts[], ads[], texts{}} (Public; ETag/304; cached)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "surface",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "If-None-Match",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "locale",
      "required": false,
      "in": "query",
      "schema": {
       "example": "en-GB"
      }
     },
     {
      "name": "platform",
      "required": false,
      "in": "query",
      "description": "web, ios, android, mac, windows or linux",
      "schema": {
       "example": "windows"
      }
     },
     {
      "name": "country",
      "required": false,
      "in": "query",
      "schema": {
       "example": "GB"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Public"
    ],
    "security": []
   }
  },
  "/cms/public/{channelId}/surfaces/{surface}/events": {
   "get": {
    "operationId": "CmsPublicSurfacesController_stream",
    "summary": "Live 'surface changed' signal (SSE, Public)",
    "description": "Server-Sent Events: `surface.version` on connect (the current public\nversion), then `surface.changed` {surface, version, published} each time\nit is published, unpublished or deleted. No content travels; refetch the\nsurface (with If-None-Match) when the version is newer than yours.",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "surface",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Public"
    ],
    "security": []
   }
  },
  "/cms/public/{channelId}/surfaces/{surface}/version": {
   "get": {
    "operationId": "CmsPublicSurfacesController_version",
    "summary": "Just the public version of a surface (cheap polling fallback for the stream)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "surface",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Public"
    ],
    "security": []
   }
  },
  "/cms/public/{channelId}/testimonials": {
   "get": {
    "operationId": "CmsPublicController_testimonialsFor",
    "summary": "Published testimonials (Public, max 100)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Public"
    ],
    "security": []
   }
  },
  "/cms/surfaces/{surface}": {
   "get": {
    "operationId": "CmsPublicSurfacesController_readByRef",
    "summary": "The same, naming the channel with x-ref, X-App-Key or ?channel_id (Public)",
    "parameters": [
     {
      "name": "surface",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "description": "Channel id (or send X-App-Key)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {}
     },
     {
      "name": "locale",
      "required": false,
      "in": "query",
      "schema": {
       "example": "en-GB"
      }
     },
     {
      "name": "platform",
      "required": false,
      "in": "query",
      "description": "web, ios, android, mac, windows or linux",
      "schema": {
       "example": "windows"
      }
     },
     {
      "name": "country",
      "required": false,
      "in": "query",
      "schema": {
       "example": "GB"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CMS · Public"
    ],
    "security": []
   }
  },
  "/comms/call-quality": {
   "post": {
    "operationId": "CommsController_callQuality",
    "summary": "Report one finished call's quality numbers (numbers and types only; no addresses or content)",
    "description": "One report per account per call; a second answers { stored: false, reason: duplicate }. If the person turned off call_quality in their preferences (PATCH /users/me/preferences), nothing is kept: { stored: false, reason: opted_out }. Rows hold the channel, call id and numbers only, and are deleted after 30 days. 60 reports an hour per account. A call rung through the relay (POST /e2ee/calls/:call_id/ring) takes reports only from its caller and callee for a day: anyone else gets 403 NOT_IN_CALL.",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CallQualityDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Communications"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/comms/channels/{channelId}/overview": {
   "get": {
    "operationId": "CommsController_overview",
    "summary": "Status, limits and this month's usage (channel managers)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Communications"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/comms/channels/{channelId}/rooms": {
   "get": {
    "operationId": "CommsController_rooms",
    "summary": "The channel's rooms, newest first (channel managers)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Communications"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/comms/channels/{channelId}/rooms/{id}": {
   "delete": {
    "operationId": "CommsController_endRoom",
    "summary": "End a call on the channel (channel managers)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Communications"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/comms/channels/{channelId}/settings": {
   "put": {
    "operationId": "CommsController_settings",
    "summary": "Turn calls on or off for the channel (channel managers)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Communications"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/comms/ice-servers": {
   "get": {
    "operationId": "CommsController_iceServers",
    "summary": "STUN/TURN servers with TURN credentials for peer-to-peer calls",
    "description": "TURN URLs over UDP and TCP (3478) and, when configured, TURN over TLS (turns:, port 443). The credential is computed on the server without any network call and lives 24 hours by default (`expires_at`); cache the answer and ask again at `refresh_at`. 60 requests an hour per account.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Communications"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/comms/rooms": {
   "post": {
    "operationId": "CommsController_create",
    "summary": "Open a room for a resource (or return its open one), or an ad hoc room",
    "parameters": [],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Communications"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/comms/rooms/find": {
   "get": {
    "operationId": "CommsController_find",
    "summary": "The open room of a group, business or connection, if any",
    "parameters": [
     {
      "name": "kind",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "resource_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Communications"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/comms/rooms/{id}": {
   "get": {
    "operationId": "CommsController_get",
    "summary": "A room you can join, with who is in the call",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Communications"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "CommsController_close",
    "summary": "End the call for everyone (host/moderator)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Communications"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/comms/rooms/{id}/invite": {
   "post": {
    "operationId": "CommsController_invite",
    "summary": "Invite people of your channel to an ad hoc room (host/moderator)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Communications"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/comms/rooms/{id}/remove": {
   "post": {
    "operationId": "CommsController_remove",
    "summary": "Remove someone from the call (host/moderator)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Communications"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/comms/rooms/{id}/token": {
   "post": {
    "operationId": "CommsController_token",
    "summary": "A join token for this room only, as you",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Communications"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/coupons/channels/{channelId}": {
   "get": {
    "operationId": "CouponsController_list",
    "summary": "List the channel's coupons",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "default": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "default": 20,
       "type": "number"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "description": "Search in the title/name",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "active",
        "paused",
        "archived"
       ],
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Commerce · Coupons"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "CouponsController_create",
    "summary": "Create a coupon",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateCouponDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Commerce · Coupons"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/coupons/channels/{channelId}/validate": {
   "post": {
    "operationId": "CouponsController_validate",
    "summary": "What a code takes off a cart (Public)",
    "description": "Shopper check before paying. Rate-limited: codes must not be guessable by brute force.",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ValidateCouponDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Commerce · Coupons"
    ],
    "security": []
   }
  },
  "/coupons/channels/{channelId}/{id}": {
   "patch": {
    "operationId": "CouponsController_update",
    "summary": "Update a coupon (incl. pause / resume)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateCouponDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Commerce · Coupons"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "CouponsController_remove",
    "summary": "Delete an unused coupon (a used one is archived)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Commerce · Coupons"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/crm/activities": {
   "get": {
    "operationId": "CrmActivitiesController_list",
    "summary": "List activities (filter by contact / deal / type / done)",
    "parameters": [
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "contact_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "deal_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "type",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "note",
        "call",
        "email",
        "meeting",
        "task",
        "stage_change",
        "status_change",
        "consent",
        "lead_created"
       ],
       "type": "string"
      }
     },
     {
      "name": "done",
      "required": false,
      "in": "query",
      "description": "Tasks: open (false) / done (true). Sent as the string \"true\"/\"false\".",
      "schema": {
       "type": "boolean"
      }
     },
     {
      "name": "due_from",
      "required": false,
      "in": "query",
      "description": "Tasks and meetings due on or after this time (ISO 8601): the calendar window.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "due_to",
      "required": false,
      "in": "query",
      "description": "Tasks / meetings due before (ISO 8601).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 10000,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     },
     {
      "name": "created_from",
      "required": false,
      "in": "query",
      "description": "Created on/after (ISO 8601).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "created_to",
      "required": false,
      "in": "query",
      "description": "Created before (ISO 8601).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "CrmActivitiesController_create",
    "summary": "Log a note / call / email / meeting / task",
    "parameters": [
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "Idempotency-Key",
      "in": "header",
      "description": "Optional client-generated key (8-128 chars, [A-Za-z0-9_-]). A retry with the same key and body replays the first response (Idempotent-Replayed: true); 409 while the first is in flight; 422 if the body differs.",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateActivityDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/crm/activities/{id}": {
   "patch": {
    "operationId": "CrmActivitiesController_update",
    "summary": "Edit an activity / tick a task (not history entries)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateActivityDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "CrmActivitiesController_remove",
    "summary": "Delete an activity (not history entries)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/crm/contacts": {
   "get": {
    "operationId": "CrmContactsController_list",
    "summary": "List / search / filter contacts (staff)",
    "parameters": [
     {
      "name": "q",
      "required": false,
      "in": "query",
      "description": "Search name / email / company / phone (case-insensitive).",
      "schema": {
       "maxLength": 100,
       "type": "string"
      }
     },
     {
      "name": "tag",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 40,
       "type": "string"
      }
     },
     {
      "name": "owner_id",
      "required": false,
      "in": "query",
      "description": "Owner id, or \"none\" for unassigned.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "source",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 40,
       "type": "string"
      }
     },
     {
      "name": "marketing_consent",
      "required": false,
      "in": "query",
      "schema": {
       "type": "boolean"
      }
     },
     {
      "name": "sort",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "date_created",
        "-date_created",
        "date_updated",
        "-date_updated",
        "name",
        "-name"
       ],
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 10000,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     },
     {
      "name": "created_from",
      "required": false,
      "in": "query",
      "description": "Created on/after (ISO 8601).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "created_to",
      "required": false,
      "in": "query",
      "description": "Created before (ISO 8601).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "CrmContactsController_create",
    "summary": "Create a contact (409 on duplicate email/phone)",
    "parameters": [
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "Idempotency-Key",
      "in": "header",
      "description": "Optional client-generated key (8-128 chars, [A-Za-z0-9_-]). A retry with the same key and body replays the first response (Idempotent-Replayed: true); 409 while the first is in flight; 422 if the body differs.",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateContactDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/crm/contacts/export": {
   "get": {
    "operationId": "CrmContactsController_exportCsv",
    "summary": "Export the filtered contacts as CSV (streamed, staff)",
    "parameters": [
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "created_from",
      "required": false,
      "in": "query",
      "description": "Created on/after (ISO 8601).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "created_to",
      "required": false,
      "in": "query",
      "description": "Created before (ISO 8601).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "description": "Search name / email / company / phone (case-insensitive).",
      "schema": {
       "maxLength": 100,
       "type": "string"
      }
     },
     {
      "name": "tag",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 40,
       "type": "string"
      }
     },
     {
      "name": "owner_id",
      "required": false,
      "in": "query",
      "description": "Owner id, or \"none\" for unassigned.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "source",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 40,
       "type": "string"
      }
     },
     {
      "name": "marketing_consent",
      "required": false,
      "in": "query",
      "schema": {
       "type": "boolean"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/crm/contacts/import": {
   "post": {
    "operationId": "CrmContactsController_importCsv",
    "summary": "Import contacts from CSV (max 5,000 rows) with a rejected-rows report (staff)",
    "parameters": [
     {
      "name": "duplicates",
      "required": false,
      "in": "query",
      "description": "Existing contact with the same email/phone: skip (reject row) or update it.",
      "schema": {
       "enum": [
        "skip",
        "update"
       ],
       "type": "string"
      }
     },
     {
      "name": "dry_run",
      "required": false,
      "in": "query",
      "description": "Validate only; write nothing.",
      "schema": {
       "type": "boolean"
      }
     },
     {
      "name": "phone_country",
      "required": false,
      "in": "query",
      "description": "Country for national-format phones in the file (default GB).",
      "schema": {
       "enum": [
        "GB",
        "US",
        "IE",
        "IN"
       ],
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "multipart/form-data": {
       "schema": {
        "type": "object",
        "required": [
         "file"
        ],
        "properties": {
         "file": {
          "type": "string",
          "format": "binary"
         }
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/crm/contacts/{id}": {
   "get": {
    "operationId": "CrmContactsController_getOne",
    "summary": "Get a contact",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "CrmContactsController_update",
    "summary": "Update a contact (consent changes are timestamped)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateContactDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "CrmContactsController_remove",
    "summary": "Erase a contact and its timeline (deals are kept, unlinked)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/crm/contacts/{id}/timeline": {
   "get": {
    "operationId": "CrmContactsController_timeline",
    "summary": "Contact timeline: its and its deals' activities, newest first",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "contact_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "deal_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "type",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "note",
        "call",
        "email",
        "meeting",
        "task",
        "stage_change",
        "status_change",
        "consent",
        "lead_created"
       ],
       "type": "string"
      }
     },
     {
      "name": "done",
      "required": false,
      "in": "query",
      "description": "Tasks: open (false) / done (true). Sent as the string \"true\"/\"false\".",
      "schema": {
       "type": "boolean"
      }
     },
     {
      "name": "due_from",
      "required": false,
      "in": "query",
      "description": "Tasks and meetings due on or after this time (ISO 8601): the calendar window.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "due_to",
      "required": false,
      "in": "query",
      "description": "Tasks / meetings due before (ISO 8601).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 10000,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     },
     {
      "name": "created_from",
      "required": false,
      "in": "query",
      "description": "Created on/after (ISO 8601).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "created_to",
      "required": false,
      "in": "query",
      "description": "Created before (ISO 8601).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/crm/deals": {
   "get": {
    "operationId": "CrmDealsController_list",
    "summary": "List / search / filter deals",
    "parameters": [
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "pipeline_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "stage_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "owner_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "contact_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "open",
        "won",
        "lost"
       ],
       "type": "string"
      }
     },
     {
      "name": "tag",
      "required": false,
      "in": "query",
      "description": "Tag of the deal's contact.",
      "schema": {
       "maxLength": 40,
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "description": "Search the title and the contact's name / email / company.",
      "schema": {
       "maxLength": 100,
       "type": "string"
      }
     },
     {
      "name": "sort",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "date_created",
        "-date_created",
        "date_updated",
        "-date_updated",
        "value_minor",
        "-value_minor",
        "expected_close_date",
        "-expected_close_date",
        "stage_entered_at",
        "-stage_entered_at"
       ],
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 10000,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     },
     {
      "name": "created_from",
      "required": false,
      "in": "query",
      "description": "Created on/after (ISO 8601).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "created_to",
      "required": false,
      "in": "query",
      "description": "Created before (ISO 8601).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "CrmDealsController_create",
    "summary": "Create a deal (default pipeline / first open stage when omitted)",
    "parameters": [
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "Idempotency-Key",
      "in": "header",
      "description": "Optional client-generated key (8-128 chars, [A-Za-z0-9_-]). A retry with the same key and body replays the first response (Idempotent-Replayed: true); 409 while the first is in flight; 422 if the body differs.",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateDealDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/crm/deals/board": {
   "get": {
    "operationId": "CrmDealsController_board",
    "summary": "Kanban: deals grouped by stage, paged per stage",
    "parameters": [
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "pipeline_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "stage_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "owner_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "contact_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "open",
        "won",
        "lost"
       ],
       "type": "string"
      }
     },
     {
      "name": "tag",
      "required": false,
      "in": "query",
      "description": "Tag of the deal's contact.",
      "schema": {
       "maxLength": 40,
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "description": "Search the title and the contact's name / email / company.",
      "schema": {
       "maxLength": 100,
       "type": "string"
      }
     },
     {
      "name": "sort",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "date_created",
        "-date_created",
        "date_updated",
        "-date_updated",
        "value_minor",
        "-value_minor",
        "expected_close_date",
        "-expected_close_date",
        "stage_entered_at",
        "-stage_entered_at"
       ],
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 10000,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     },
     {
      "name": "created_from",
      "required": false,
      "in": "query",
      "description": "Created on/after (ISO 8601).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "created_to",
      "required": false,
      "in": "query",
      "description": "Created before (ISO 8601).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "per_stage",
      "required": false,
      "in": "query",
      "description": "Deals per stage column (default 20, max 100).",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/crm/deals/{id}": {
   "get": {
    "operationId": "CrmDealsController_getOne",
    "summary": "Get a deal",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "CrmDealsController_update",
    "summary": "Update a deal. To change its stage, use /move or /close.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateDealDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "CrmDealsController_remove",
    "summary": "Delete a deal",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/crm/deals/{id}/close": {
   "post": {
    "operationId": "CrmDealsController_close",
    "summary": "Mark won / lost with a reason",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CloseDealDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/crm/deals/{id}/history": {
   "get": {
    "operationId": "CrmDealsController_history",
    "summary": "Stage / status history of a deal",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "contact_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "deal_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "type",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "note",
        "call",
        "email",
        "meeting",
        "task",
        "stage_change",
        "status_change",
        "consent",
        "lead_created"
       ],
       "type": "string"
      }
     },
     {
      "name": "done",
      "required": false,
      "in": "query",
      "description": "Tasks: open (false) / done (true). Sent as the string \"true\"/\"false\".",
      "schema": {
       "type": "boolean"
      }
     },
     {
      "name": "due_from",
      "required": false,
      "in": "query",
      "description": "Tasks and meetings due on or after this time (ISO 8601): the calendar window.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "due_to",
      "required": false,
      "in": "query",
      "description": "Tasks / meetings due before (ISO 8601).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 10000,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     },
     {
      "name": "created_from",
      "required": false,
      "in": "query",
      "description": "Created on/after (ISO 8601).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "created_to",
      "required": false,
      "in": "query",
      "description": "Created before (ISO 8601).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/crm/deals/{id}/move": {
   "post": {
    "operationId": "CrmDealsController_move",
    "summary": "Move to a stage (recorded in the deal history)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/MoveDealDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/crm/deals/{id}/timeline": {
   "get": {
    "operationId": "CrmDealsController_timeline",
    "summary": "Deal timeline, newest first",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "contact_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "deal_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "type",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "note",
        "call",
        "email",
        "meeting",
        "task",
        "stage_change",
        "status_change",
        "consent",
        "lead_created"
       ],
       "type": "string"
      }
     },
     {
      "name": "done",
      "required": false,
      "in": "query",
      "description": "Tasks: open (false) / done (true). Sent as the string \"true\"/\"false\".",
      "schema": {
       "type": "boolean"
      }
     },
     {
      "name": "due_from",
      "required": false,
      "in": "query",
      "description": "Tasks and meetings due on or after this time (ISO 8601): the calendar window.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "due_to",
      "required": false,
      "in": "query",
      "description": "Tasks / meetings due before (ISO 8601).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 10000,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     },
     {
      "name": "created_from",
      "required": false,
      "in": "query",
      "description": "Created on/after (ISO 8601).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "created_to",
      "required": false,
      "in": "query",
      "description": "Created before (ISO 8601).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/crm/pipelines": {
   "get": {
    "operationId": "CrmPipelinesController_list",
    "summary": "Pipelines with their ordered stages (creates the default on first use)",
    "parameters": [
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "CrmPipelinesController_create",
    "summary": "Create a pipeline (with stages)",
    "parameters": [
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "Idempotency-Key",
      "in": "header",
      "description": "Optional client-generated key (8-128 chars, [A-Za-z0-9_-]). A retry with the same key and body replays the first response (Idempotent-Replayed: true); 409 while the first is in flight; 422 if the body differs.",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreatePipelineDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/crm/pipelines/{id}": {
   "patch": {
    "operationId": "CrmPipelinesController_update",
    "summary": "Rename / reorder / make default",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdatePipelineDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "CrmPipelinesController_remove",
    "summary": "Delete an empty, non-default pipeline",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/crm/pipelines/{id}/stages": {
   "post": {
    "operationId": "CrmPipelinesController_addStage",
    "summary": "Append a stage",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "Idempotency-Key",
      "in": "header",
      "description": "Optional client-generated key (8-128 chars, [A-Za-z0-9_-]). A retry with the same key and body replays the first response (Idempotent-Replayed: true); 409 while the first is in flight; 422 if the body differs.",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateStageDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/crm/pipelines/{id}/stages/order": {
   "put": {
    "operationId": "CrmPipelinesController_reorder",
    "summary": "Reorder all stages of a pipeline",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ReorderStagesDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/crm/public/{channelId}/leads": {
   "post": {
    "operationId": "CrmPublicController_submit",
    "summary": "Web-to-lead: a channel's website form adds a lead (deal + activity) to a new or exactly matching contact; never changes an existing contact (Public)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "Idempotency-Key",
      "in": "header",
      "description": "Optional client-generated key (8-128 chars, [A-Za-z0-9_-]). A retry with the same key and body replays the first response (Idempotent-Replayed: true); 409 while the first is in flight; 422 if the body differs.",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/WebLeadDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": []
   }
  },
  "/crm/stages/{id}": {
   "patch": {
    "operationId": "CrmStagesController_update",
    "summary": "Rename a stage / change its kind or probability",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateStageDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "CrmStagesController_remove",
    "summary": "Delete an empty stage",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "CRM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer-program/businesses/{businessId}": {
   "get": {
    "operationId": "DeveloperProgramController_status",
    "summary": "Can the business join, its developer account, the fee and Marketplace eligibility",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer program"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer-program/businesses/{businessId}/projects": {
   "get": {
    "operationId": "DeveloperProgramController_listProjects",
    "summary": "The business's projects",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer program"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "DeveloperProgramController_createProject",
    "summary": "Start a project (a draft; active developers only)",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ProjectDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer program"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer-program/businesses/{businessId}/register": {
   "post": {
    "operationId": "DeveloperProgramController_register",
    "summary": "Join (businesses created on Intersink): accepts the terms, charges the annual fee, then waits for review",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RegisterDeveloperDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer program"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer-program/projects/{id}": {
   "get": {
    "operationId": "DeveloperProgramController_getProject",
    "summary": "One project",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer program"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "DeveloperProgramController_updateProject",
    "summary": "Change the request (an approved project then waits for review again)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ProjectDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer program"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer-program/projects/{id}/checkup": {
   "post": {
    "operationId": "DeveloperProgramController_checkup",
    "summary": "Confirm the annual data use checkup (overdue: live keys pause)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CheckupDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer program"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer-program/projects/{id}/submit": {
   "post": {
    "operationId": "DeveloperProgramController_submitProject",
    "summary": "Send the project for review (accepts the API policy)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/SubmitProjectDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer program"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer-program/projects/{id}/usage": {
   "get": {
    "operationId": "DeveloperProgramController_usage",
    "summary": "This month's API requests and the free allowance",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer program"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer-program/scopes": {
   "get": {
    "operationId": "DeveloperProgramController_scopes",
    "summary": "Scopes a project can ask for, with what each allows",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer program"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer/channels/{channelId}/api": {
   "get": {
    "operationId": "ChannelApiController_status",
    "summary": "Is the API enabled, can live keys be used (business verified), and the scopes the installed apps open",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer/channels/{channelId}/api-keys": {
   "get": {
    "operationId": "ApiKeysController_list",
    "summary": "List the channel's API keys (metadata only)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "ApiKeysController_create",
    "summary": "Create an API key. The secret `key` is returned only once.",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateApiKeyDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer/channels/{channelId}/api-keys/{id}": {
   "patch": {
    "operationId": "ApiKeysController_update",
    "summary": "Rename / change scopes, IP allow-list or expiry",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateApiKeyDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "ApiKeysController_revoke",
    "summary": "Revoke an API key (immediate, irreversible)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer/channels/{channelId}/api-keys/{id}/rotate": {
   "post": {
    "operationId": "ApiKeysController_rotate",
    "summary": "Issue a replacement key (same settings); the old one is revoked now or after grace_seconds",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RotateApiKeyDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer/channels/{channelId}/api/app-keys": {
   "post": {
    "operationId": "ChannelApiController_createAppKey",
    "summary": "Create a publishable app key (X-App-Key) for the channel's own mobile or web app. It is returned once; it names the channel and meters usage, and grants nothing by itself",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateAppKeyDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer/channels/{channelId}/api/app-keys/{keyId}": {
   "get": {
    "operationId": "ChannelApiController_revealAppKey",
    "summary": "Show a publishable app key again (channel managers; audited). Secret keys are never shown again.",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "keyId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer/channels/{channelId}/api/disable": {
   "post": {
    "operationId": "ChannelApiController_disable",
    "summary": "Disable the channel's API: its keys stop at once",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer/channels/{channelId}/api/enable": {
   "post": {
    "operationId": "ChannelApiController_enable",
    "summary": "Enable the channel's API (businesses created on Intersink)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer/channels/{channelId}/audit": {
   "get": {
    "operationId": "DeveloperController_auditLog",
    "summary": "Audit log of API key and webhook changes (newest first)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "default": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "default": 50,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer/channels/{channelId}/webhooks": {
   "get": {
    "operationId": "WebhooksController_list",
    "summary": "List the channel's webhook endpoints",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "WebhooksController_create",
    "summary": "Register an https endpoint. The signing `secret` is returned only here and on rotation.",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateWebhookDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer/channels/{channelId}/webhooks/{id}": {
   "get": {
    "operationId": "WebhooksController_get",
    "summary": "One webhook endpoint",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "WebhooksController_update",
    "summary": "Change URL / events, or enable / disable",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateWebhookDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "WebhooksController_remove",
    "summary": "Delete an endpoint (and its delivery log)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer/channels/{channelId}/webhooks/{id}/deliveries": {
   "get": {
    "operationId": "WebhooksController_deliveries",
    "summary": "Delivery log of an endpoint (newest first, paged)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "pending",
        "succeeded",
        "failed"
       ],
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "default": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "default": 20,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer/channels/{channelId}/webhooks/{id}/deliveries/{deliveryId}": {
   "get": {
    "operationId": "WebhooksController_delivery",
    "summary": "One delivery with its payload and response body",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "deliveryId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer/channels/{channelId}/webhooks/{id}/deliveries/{deliveryId}/redeliver": {
   "post": {
    "operationId": "WebhooksController_redeliver",
    "summary": "Send a past delivery's event again, now (same event id)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "deliveryId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer/channels/{channelId}/webhooks/{id}/rotate-secret": {
   "post": {
    "operationId": "WebhooksController_rotateSecret",
    "summary": "New signing secret (old one optionally kept for a grace period)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RotateWebhookSecretDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer/channels/{channelId}/webhooks/{id}/test": {
   "post": {
    "operationId": "WebhooksController_ping",
    "summary": "Send a webhook.ping event now and return the result",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/developer/event-types": {
   "get": {
    "operationId": "DeveloperController_eventTypes",
    "summary": "Event types a webhook endpoint can subscribe to",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": []
   }
  },
  "/developer/scopes": {
   "get": {
    "operationId": "DeveloperController_scopes",
    "summary": "Scopes an API key can be granted",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": []
   }
  },
  "/discover/listings": {
   "get": {
    "operationId": "DiscoverController_listings",
    "summary": "Marketplace listings near a point: posts with type \"listing\" (price in fee). Also q, min_price, max_price. Query: latitude, longitude, min_km (default 0), max_km (default 1), cursor, limit. Returns { items, ring: { minKm, maxKm }, cursor }, nearest first. Items carry distance_km, never coordinates.",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Discover"
    ],
    "security": []
   }
  },
  "/discover/posts": {
   "get": {
    "operationId": "DiscoverController_posts",
    "summary": "Posts near a point, one ring at a time. Query: latitude, longitude, min_km (default 0), max_km (default 1), cursor, limit. Returns { items, ring: { minKm, maxKm }, cursor }, nearest first. Items carry distance_km, never coordinates.",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Discover"
    ],
    "security": []
   }
  },
  "/discover/profiles": {
   "get": {
    "operationId": "DiscoverController_profiles",
    "summary": "People near a point (their home area). Query: latitude, longitude, min_km (default 0), max_km (default 1), cursor, limit. Returns { items, ring: { minKm, maxKm }, cursor }, nearest first. Items carry distance_km, never coordinates.",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Discover"
    ],
    "security": []
   }
  },
  "/discover/stories": {
   "get": {
    "operationId": "DiscoverController_stories",
    "summary": "Stories near a point. Query: latitude, longitude, min_km (default 0), max_km (default 1), cursor, limit. Returns { items, ring: { minKm, maxKm }, cursor }, nearest first. Items carry distance_km, never coordinates.",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Discover"
    ],
    "security": []
   }
  },
  "/donations/campaign/{campaignId}": {
   "get": {
    "operationId": "DonationsController_getCampaignDonation",
    "summary": "Get total donation balance and records for a campaign",
    "parameters": [
     {
      "name": "campaignId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Donations"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/donations/campaign/{campaignId}/collection_history": {
   "get": {
    "operationId": "DonationsController_getWithdrawalHistory",
    "summary": "Get withdrawal history for a campaign",
    "parameters": [
     {
      "name": "campaignId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Donations"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/donations/campaign/{campaignId}/withdraw": {
   "post": {
    "operationId": "DonationsController_withdrawDonation",
    "summary": "Withdraw funds from a campaign's collection",
    "parameters": [
     {
      "name": "campaignId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "Idempotency-Key",
      "in": "header",
      "description": "Optional client-generated key (8-128 chars, [A-Za-z0-9_-]). A retry with the same key and body replays the first response (Idempotent-Replayed: true); 409 while the first is in flight; 422 if the body differs.",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/WithdrawDonationDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Donations"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/donations/me": {
   "get": {
    "operationId": "DonationsController_getMyDonations",
    "summary": "Fetch all donations made by the active profile",
    "parameters": [
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Donations"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/drive/channels/{channelId}/files": {
   "get": {
    "operationId": "TeamDriveController_list",
    "summary": "The channel's team files, newest first",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Drive · Team"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "TeamDriveController_upload",
    "summary": "Upload a team file (multipart: source_type=team, then file)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Drive · Team"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/drive/channels/{channelId}/files/{id}": {
   "delete": {
    "operationId": "TeamDriveController_remove",
    "summary": "Delete a team file",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Drive · Team"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/drive/files": {
   "get": {
    "operationId": "FilesController_list",
    "summary": "",
    "description": "All the caller's files (no filter = every source), paginated.",
    "parameters": [
     {
      "name": "folder_id",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "profile_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "source_type",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "file_category",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/drive/files/quota": {
   "get": {
    "operationId": "FilesController_quota",
    "summary": "",
    "description": "The caller's storage use and limit (bytes, plus human sizes).",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/drive/files/upload": {
   "post": {
    "operationId": "FilesController_upload",
    "summary": "",
    "description": "POST /drive/files/upload, multipart/form-data: a `file` part + optional text\nfields (source_type, folder_id, filename) sent BEFORE the file. The backend\nstreams the bytes to R2; size + category are derived server-side.",
    "parameters": [],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/drive/files/{id}": {
   "get": {
    "operationId": "FilesController_getOne",
    "summary": "",
    "description": "One file's metadata + serving URL (+ size / size_human). id = INTEGER.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   },
   "patch": {
    "operationId": "FilesController_update",
    "summary": "",
    "description": "Rename a file. id = INTEGER.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateFileDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   },
   "delete": {
    "operationId": "FilesController_remove",
    "summary": "",
    "description": "Delete a file (rebuilt R2 path + record + storage decrement). id = INTEGER.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/drive/folders": {
   "post": {
    "operationId": "FoldersController_create",
    "summary": "",
    "description": "Create a folder (no R2 write).",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateFolderDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   },
   "get": {
    "operationId": "FoldersController_list",
    "summary": "",
    "description": "Folders at a level (root by default, or under ?parent_folder_id=).\n Optional ?profile_id= narrows to one of the caller's profiles.",
    "parameters": [
     {
      "name": "parent_folder_id",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "profile_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/drive/folders/{id}": {
   "get": {
    "operationId": "FoldersController_contents",
    "summary": "",
    "description": "A folder + its contents (subfolders + files, each with a serving URL).",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   },
   "patch": {
    "operationId": "FoldersController_update",
    "summary": "",
    "description": "Rename and/or move a folder (parent_folder_id:null → root; cycle-guarded).",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateFolderDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   },
   "delete": {
    "operationId": "FoldersController_remove",
    "summary": "",
    "description": "Delete a folder and CASCADE (subtree records; files when linking exists).",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/drive/folders/{id}/properties": {
   "get": {
    "operationId": "FoldersController_properties",
    "summary": "",
    "description": "Folder properties: on-demand recursive total_size / file_count / folder_count.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/drive/profile/cover": {
   "post": {
    "operationId": "ProfileMediaController_setCover",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/SetProfileMediaDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   },
   "delete": {
    "operationId": "ProfileMediaController_removeCover",
    "parameters": [
     {
      "name": "profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/drive/profile/pfp": {
   "post": {
    "operationId": "ProfileMediaController_setPfp",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/SetProfileMediaDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   },
   "delete": {
    "operationId": "ProfileMediaController_removePfp",
    "parameters": [
     {
      "name": "profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/drive/shares": {
   "post": {
    "operationId": "DriveSharesController_create",
    "summary": "Share: { target_type: file|sync_file|asset, target_id, expires_in (s) | expires_at, max_downloads?, password?, label? } → token once",
    "parameters": [],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Drive sync"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "DriveSharesController_list",
    "summary": "Your shared links (?target_id)",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Drive sync"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/drive/shares/open/{token}": {
   "post": {
    "operationId": "DriveSharesController_open",
    "summary": "Open a shared link (anyone with it): { password? } → signed URLs",
    "parameters": [
     {
      "name": "token",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Drive sync"
    ],
    "security": []
   }
  },
  "/drive/shares/{id}": {
   "delete": {
    "operationId": "DriveSharesController_revoke",
    "summary": "Revoke a link now",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Drive sync"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/drive/sync/v1/blocks/check": {
   "post": {
    "operationId": "DriveSyncController_check",
    "summary": "Which of these blocks the server lacks: { blocks: [id…] } → { missing } (≤ 2000)",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Drive sync"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/drive/sync/v1/blocks/urls": {
   "post": {
    "operationId": "DriveSyncController_urls",
    "summary": "Signed download links for blocks you hold: { blocks: [id…] } (≤ 2000)",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Drive sync"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/drive/sync/v1/blocks/{id}": {
   "put": {
    "operationId": "DriveSyncController_put",
    "summary": "Store one block (application/octet-stream, ≤ 16 MiB). Plain: id = SHA-256 of the bytes. Encrypted: X-Block-Encrypted: 1 and X-Block-Sha256 of the ciphertext.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Drive sync"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/drive/sync/v1/changes": {
   "get": {
    "operationId": "DriveSyncController_changes",
    "summary": "Changes after ?cursor (0 = from the start), oldest first: { changes, cursor, has_more }",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Drive sync"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/drive/sync/v1/files": {
   "get": {
    "operationId": "DriveSyncController_list",
    "summary": "Current files (?prefix=/folder/, ?limit, ?offset)",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Drive sync"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/drive/sync/v1/files/commit": {
   "post": {
    "operationId": "DriveSyncController_commit",
    "summary": "Commit a version: { path, base_version (0 = new), blocks, size?, content_hash?, encrypted?, enc_header?, client_mtime? }; 409 on a conflict",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Drive sync"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/drive/sync/v1/files/delete": {
   "post": {
    "operationId": "DriveSyncController_remove",
    "summary": "Delete: { path, base_version }",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Drive sync"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/drive/sync/v1/files/move": {
   "post": {
    "operationId": "DriveSyncController_move",
    "summary": "Move or rename: { from, to, base_version }",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Drive sync"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/drive/sync/v1/files/{id}": {
   "get": {
    "operationId": "DriveSyncController_get",
    "summary": "One file with its block list",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Drive sync"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/drive/sync/v1/files/{id}/diff": {
   "post": {
    "operationId": "DriveSyncController_diff",
    "summary": "The file's block list and the blocks you lack: { have: [block ids you hold] }",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Drive sync"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/drive/sync/v1/files/{id}/restore": {
   "post": {
    "operationId": "DriveSyncController_restore",
    "summary": "Restore a kept version as the newest one: { version }",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Drive sync"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/drive/sync/v1/files/{id}/versions": {
   "get": {
    "operationId": "DriveSyncController_versions",
    "summary": "Kept versions (the last 20)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Drive sync"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/blobs": {
   "post": {
    "operationId": "E2eeController_createBlob",
    "summary": "Start an encrypted blob upload",
    "description": "Single PUT (default): { id, upload_url, expires, delete_token, status }. With resumable: true a multipart upload: { id, upload_token, delete_token, status, size, part_size, parts, expires, max_parallel }; then POST /e2ee/blobs/:id/parts and /complete. Errors: 400 BLOB_SIZE_INVALID, IDEMPOTENCY_KEY_INVALID, RESUMABLE_DISABLED; 409 IDEMPOTENCY_CONFLICT, BACKUP_IN_PROGRESS; 413 BLOB_TOO_LARGE (details.max_bytes); 429 RATE_LIMITED, UPLOAD_BUDGET_EXCEEDED (details.resets_at), TOO_MANY_PENDING_UPLOADS; 503 STORAGE_UNAVAILABLE; 507 MEDIA_STORAGE_FULL.",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "Idempotency-Key",
      "in": "header",
      "description": "A UUID per upload; a replay with the same body answers 200 with the same blob",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateBlobDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/BlobCreatedDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "E2eeController_latestBlob",
    "summary": "The account's backups",
    "description": "?purpose=backup&latest=1 → the current backup { id, size, created, completed } or null (only a finished backup is ever the latest). ?purpose=backup → every backup of the account, newest first, each with its delete_token.",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "purpose",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "latest",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Without latest: the account's backups. With latest=1: one backup or null.",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "$ref": "#/components/schemas/BackupDto"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/blobs/{id}": {
   "get": {
    "operationId": "E2eeController_blobUrl",
    "summary": "Download link for a finished blob",
    "description": "{ id, url, expires, size, accept_ranges }. The URL takes Range (206 / 416) and If-Range; when it expires (403) ask again and resume at the same byte. Errors: 404 BLOB_NOT_FOUND; 409 BLOB_NOT_READY (Retry-After); 429 RATE_LIMITED; 503 STORAGE_UNAVAILABLE.",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/BlobLinkDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "E2eeController_deleteBlob",
    "summary": "Delete a blob (sender's delete for everyone, or one's own backup)",
    "description": "Removes the object, the row and the edge copy. Idempotent: a valid token for a blob already gone answers ok. Errors: 404 BLOB_NOT_FOUND (wrong token, someone else's backup); 429 RATE_LIMITED; 503 STORAGE_UNAVAILABLE.",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "X-Delete-Token",
      "in": "header",
      "description": "delete_token from POST /e2ee/blobs",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/BlobOkDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/blobs/{id}/abort": {
   "post": {
    "operationId": "E2eeController_abortBlob",
    "summary": "Resumable blob upload: give up and drop the stored parts",
    "description": "Errors: 404 UPLOAD_NOT_FOUND; 409 BLOB_ALREADY_READY (use DELETE).",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/BlobUploadDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/BlobOkDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/blobs/{id}/complete": {
   "post": {
    "operationId": "E2eeController_completeBlob",
    "summary": "Finish a blob upload",
    "description": "Resumable: checks every part is stored at its exact size, then joins them. Single PUT: checks the object arrived. Safe to repeat: a ready blob answers the same body. Errors: 404 UPLOAD_NOT_FOUND; 409 BLOB_PARTS_INCOMPLETE (details: missing, wrong_size, unexpected), BLOB_NOT_UPLOADED, BLOB_SIZE_MISMATCH; 410 UPLOAD_EXPIRED.",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/BlobCompleteDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/BlobReadyDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/blobs/{id}/parts": {
   "post": {
    "operationId": "E2eeController_blobParts",
    "summary": "Resumable blob upload: part URLs and the parts already stored",
    "description": "{ upload_token, parts: [1, 2, ...] (at most 100), ttl_s?, md5? }. PUT each part to its url with the headers given and exactly `size` bytes; a 403 from storage means the URL expired: ask again. parts: [] after a restart answers what storage holds (`uploaded`). Errors: 400 BLOB_PARTS_INVALID; 404 UPLOAD_NOT_FOUND (wrong id or token); 410 UPLOAD_EXPIRED; 429 RATE_LIMITED.",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/BlobPartsDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/BlobPartsResultDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/calls/{call_id}/cancel": {
   "post": {
    "operationId": "E2eeController_cancelCall",
    "summary": "Stop the ring: the caller hung up, or the callee answered or declined on one device (the others stop)",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "call_id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CancelCallDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/calls/{call_id}/ring": {
   "post": {
    "operationId": "E2eeController_ringCall",
    "summary": "Ring the callee's phones for a call (APNs VoIP / FCM high priority; call id and expiry only)",
    "description": "The call itself goes end to end encrypted as relay messages; this only rings. The push says nothing about the caller: the app shows who is calling from the decrypted call offer. Only a caller with the callee's access_key (unidentified-access key) rings, and only when neither has blocked the other; otherwise the answer is the same and nothing rings. Re-sending the same call id to the same callee rings again. Limits (429): 10 rings a minute and 60 an hour per caller, 3 in 2 minutes to the same person. Into one callee at most 6 a minute and 30 an hour ring; past that nothing rings, with the same answer. 409 CALL_ID_IN_USE: another caller or callee holds this id. 503: the block check failed, nothing rang.",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "call_id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RingCallDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/certificate": {
   "get": {
    "operationId": "E2eeController_certificate",
    "summary": "A 24-hour sealed-sender certificate for this device",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/channels/{channelId}/push": {
   "get": {
    "operationId": "E2eeAdminController_getPush",
    "summary": "Which push credentials are set (never the secrets)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "put": {
    "operationId": "E2eeAdminController_setPush",
    "summary": "Set APNs / FCM credentials and the wake alert text (\"\" clears)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PushCredentialsDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/devices": {
   "post": {
    "operationId": "E2eeController_register",
    "summary": "Register this device (first = 1; others need link_token). With no bearer: a device linked from the phone (bound link_token + provisioning_address) is registered and signed in",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "in": "header",
      "description": "channel id (required without a bearer token)",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RegisterDeviceDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": []
   },
   "get": {
    "operationId": "E2eeController_devices",
    "summary": "My devices",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/devices/link-token": {
   "post": {
    "operationId": "E2eeController_linkToken",
    "summary": "A single-use 10-minute token to link a new device (device 1 only); optionally bound to the new device's provisioning address",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/LinkTokenDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/devices/{device_id}": {
   "delete": {
    "operationId": "E2eeController_removeDevice",
    "summary": "Remove a device with its queue and keys",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "device_id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/devices/{device_id}/key": {
   "put": {
    "operationId": "E2eeController_setDeviceKey",
    "summary": "Add a device key to a device from before device keys (linked session of that device, or a sign-in within 10 minutes), or replace it (device token of the current key)",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "device_id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/SetDeviceKeyDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/devices/{device_id}/push": {
   "put": {
    "operationId": "E2eeController_setPush",
    "summary": "Set this device's push token (apns / apns_voip / fcm)",
    "description": "Optional `route_tag` (16 to 32 base64url characters, random, made by the client per account and device): every push to this device then carries it as `rt` (APNs alert, background and VoIP payloads, FCM data), so an app with several accounts on one phone routes the push to the right one. Left out, the stored tag stays. It is cleared with the device's push tokens and never logged.",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "device_id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PutPushDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "E2eeController_deletePush",
    "summary": "Remove this device's push token (apns / apns_voip / fcm), e.g. on sign-out or when calls are turned off",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "device_id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "platform",
      "required": true,
      "in": "query",
      "description": "Which token to remove",
      "schema": {
       "enum": [
        "apns",
        "apns_voip",
        "fcm"
       ],
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/devices/{device_id}/token": {
   "post": {
    "operationId": "E2eeController_deviceToken",
    "summary": "Prove this device with its device key (signed ts + single-use nonce) → a device token for this session",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "device_id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/DeviceProofDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/directory/lookup": {
   "post": {
    "operationId": "E2eeController_lookup",
    "summary": "Username → account id (30/hour; 404 when not discoverable)",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/DirectoryLookupDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/gateway/deliveries": {
   "get": {
    "operationId": "E2eeAdminController_deliveries",
    "summary": "",
    "description": "Gateway: Server-Sent Events of this channel's deliveries (`data:` = the\nsame JSON as the Redis `e2ee:deliver` channel).",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/gateway/live": {
   "put": {
    "operationId": "E2eeAdminController_live",
    "summary": "Gateway: report devices whose client proved it is there ({ devices }, each lasts 40 s); devices that disconnected go in { gone }",
    "description": "Report a device only when its client itself sent something since the last report (an app frame or a WebSocket pong it answered), never because its socket is merely open: a suspended app keeps its socket open for minutes. Report every 25 s. A call skips its push only on a report at most 35 s old.",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/GatewayLiveDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/keys": {
   "put": {
    "operationId": "E2eeController_putKeys",
    "summary": "Upload pre-keys (one-time keys replace the unused ones)",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PutKeysDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/keys/count": {
   "get": {
    "operationId": "E2eeController_keyCount",
    "summary": "Unused one-time keys of this device (replenish under 20)",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/keys/{account_id}/{device_id}": {
   "get": {
    "operationId": "E2eeController_bundle",
    "summary": "Pre-key bundle(s); consumes one-time keys (bearer or uak)",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "account_id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "device_id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "unidentified-access-key",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": []
   }
  },
  "/e2ee/messages": {
   "get": {
    "operationId": "E2eeController_fetch",
    "summary": "Queued envelopes of this device, oldest first",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/messages/{account_id}": {
   "put": {
    "operationId": "E2eeController_send",
    "summary": "Send envelopes to every device of an account (bearer or sealed sender)",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "account_id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "unidentified-access-key",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/SendMessagesDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": []
   }
  },
  "/e2ee/messages/{guid}": {
   "delete": {
    "operationId": "E2eeController_ack",
    "summary": "Acknowledge (delete) an envelope; 404 when already gone",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "guid",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/profile": {
   "put": {
    "operationId": "E2eeController_putProfile",
    "summary": "Store an encrypted profile version and the access key",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PutProfileDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/e2ee/profile/{account_id}/{version}": {
   "get": {
    "operationId": "E2eeController_getProfile",
    "summary": "An encrypted profile version (bearer or uak)",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "account_id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "version",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "unidentified-access-key",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": []
   }
  },
  "/e2ee/provisioning": {
   "post": {
    "operationId": "E2eeProvisioningController_create",
    "summary": "New device: a one-use provisioning address (10 minutes) to show as a QR",
    "parameters": [
     {
      "name": "x-ref",
      "in": "header",
      "description": "channel id",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": []
   }
  },
  "/e2ee/provisioning/{address}": {
   "put": {
    "operationId": "E2eeProvisioningController_put",
    "summary": "Primary device: deliver the sealed provisioning message (once; the address is then burned)",
    "parameters": [
     {
      "name": "address",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ProvisioningPutDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ]
   },
   "get": {
    "operationId": "E2eeProvisioningController_poll",
    "summary": "New device, long-poll fallback: waits up to ?timeout= s (default 25, max 55) → { body } or { body: null, expires }",
    "parameters": [
     {
      "name": "address",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "timeout",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": []
   }
  },
  "/e2ee/provisioning/{address}/stream": {
   "get": {
    "operationId": "E2eeProvisioningController_stream",
    "summary": "New device: SSE; one `provisioning.message` event { body }, then the stream ends",
    "parameters": [
     {
      "name": "address",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": []
   }
  },
  "/e2ee/username/discoverable": {
   "put": {
    "operationId": "E2eeController_discoverable",
    "summary": "Can others find me by username?",
    "parameters": [
     {
      "name": "x-device-token",
      "in": "header",
      "description": "device token (POST /e2ee/devices/:id/token); required for a device that has a device key",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-device-id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/DiscoverableDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "E2EE relay"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/emails/send": {
   "post": {
    "operationId": "EmailController_send",
    "summary": "Send an email via SES (admin-gated by x-admin-key)",
    "description": "Send an email via SES. Admin-gated by the same shared secret as broadcasts\n(x-admin-key) so it can't be abused for spam; fails closed when unset.\nEach recipient receives an individual message.",
    "parameters": [
     {
      "name": "x-admin-key",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/SendEmailDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Email"
    ],
    "security": []
   }
  },
  "/events": {
   "post": {
    "operationId": "EventsController_create",
    "summary": "Create an event (multipart; first image = cover)",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateEventDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Events"
    ]
   },
   "get": {
    "operationId": "EventsController_list",
    "summary": "List events (public)",
    "parameters": [
     {
      "name": "user_profile_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "city",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "category",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "tags",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "from",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "to",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "is_free",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "price_min",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "price_max",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "sort",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "include_past",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "featured",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Events"
    ],
    "security": []
   }
  },
  "/events/categories": {
   "get": {
    "operationId": "EventsController_categories",
    "summary": "Event categories",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Events"
    ],
    "security": []
   }
  },
  "/events/my": {
   "get": {
    "operationId": "EventsController_my",
    "summary": "My events (includes drafts)",
    "parameters": [
     {
      "name": "status",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Events"
    ]
   }
  },
  "/events/trending": {
   "get": {
    "operationId": "EventsController_trending",
    "summary": "Trending events (engagement-ranked, public)",
    "parameters": [
     {
      "name": "user_profile_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "city",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "category",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "tags",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "from",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "to",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "is_free",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "price_min",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "price_max",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "sort",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "include_past",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "featured",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Events"
    ],
    "security": []
   }
  },
  "/events/{idOrSlug}": {
   "get": {
    "operationId": "EventsController_one",
    "summary": "One event by id or slug (public)",
    "parameters": [
     {
      "name": "idOrSlug",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Events"
    ]
   }
  },
  "/events/{id}": {
   "patch": {
    "operationId": "EventsController_update",
    "summary": "Update an event (owner only)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateEventDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Events"
    ]
   },
   "delete": {
    "operationId": "EventsController_remove",
    "summary": "Delete an event (owner only, soft)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Events"
    ]
   }
  },
  "/events/{id}/attendees": {
   "get": {
    "operationId": "EventsController_attendees",
    "summary": "RSVP counts (going, interested) and yours; the event's owner also gets the names",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Events"
    ],
    "security": []
   }
  },
  "/events/{id}/invites": {
   "post": {
    "operationId": "EventsController_invite",
    "summary": "Invite profiles of the event's channel: { profile_ids: string[] } (max 50; the host, or anyone going). Each person is invited once.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Events"
    ]
   }
  },
  "/events/{id}/rsvp": {
   "put": {
    "operationId": "EventsController_rsvp",
    "summary": "Reply to an event: { status: \"going\" | \"interested\" }",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Events"
    ]
   },
   "delete": {
    "operationId": "EventsController_unrsvp",
    "summary": "Take back your reply to an event",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Events"
    ]
   }
  },
  "/events/{id}/view": {
   "post": {
    "operationId": "EventsController_view",
    "summary": "Record a view (deduped per profile / 24h)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Events"
    ],
    "security": []
   }
  },
  "/faq": {
   "get": {
    "operationId": "FaqController_getFaqs",
    "summary": "Get FAQs (Public)",
    "parameters": [
     {
      "name": "x-ref",
      "in": "header",
      "description": "Channel id",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "FAQ"
    ],
    "security": []
   }
  },
  "/faq/groups": {
   "get": {
    "operationId": "FaqController_getGroups",
    "summary": "Get FAQ groups/categories (Public)",
    "parameters": [
     {
      "name": "x-ref",
      "in": "header",
      "description": "Channel id",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "FAQ"
    ],
    "security": []
   }
  },
  "/faq/structured": {
   "get": {
    "operationId": "FaqController_getStructuredFaqs",
    "summary": "Get structured FAQ categories with nested FAQs (Public)",
    "parameters": [
     {
      "name": "x-ref",
      "in": "header",
      "description": "Channel id",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "FAQ"
    ],
    "security": []
   }
  },
  "/features/beta": {
   "get": {
    "operationId": "FeatureFlagsController_betaStatus",
    "summary": "My beta features in a channel (X-App-Key or x-ref, else my channel): what I can try and what I turned on",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Features"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "put": {
    "operationId": "FeatureFlagsController_setBeta",
    "summary": "Turn beta features on or off for me: { enabled } for every beta feature, or { enabled, key } for one",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Features"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/features/channels/{channelId}/flags": {
   "get": {
    "operationId": "FeatureFlagsController_list",
    "summary": "Every flag of the channel (managers), with how many users opted in to beta",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Features"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "FeatureFlagsController_create",
    "summary": "Add a flag: { key, name, description?, state?, include_admins?, include_team?, beta_optin?, user_ids?, rollout_percent?, reason? }",
    "description": "state defaults to internal. Keys are lower case (checkout.new-flow) and never change.",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Features"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/features/channels/{channelId}/flags/{key}": {
   "get": {
    "operationId": "FeatureFlagsController_one",
    "summary": "One flag (managers)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "key",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Features"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "FeatureFlagsController_update",
    "summary": "Change a flag: any field of the create body, plus version (the one you read: a change made meanwhile is refused with 409 FEATURE_FLAG_CHANGED)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "key",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Features"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "FeatureFlagsController_remove",
    "summary": "Delete a flag (a platform default goes back to its default); ?reason=",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "key",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "reason",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Features"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/features/channels/{channelId}/flags/{key}/kill": {
   "post": {
    "operationId": "FeatureFlagsController_kill",
    "summary": "Kill switch: turn the feature off for everyone now, whatever its state: { reason? }",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "key",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Features"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/features/channels/{channelId}/flags/{key}/restore": {
   "post": {
    "operationId": "FeatureFlagsController_restore",
    "summary": "Switch a killed feature back on (its state applies again): { reason? }",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "key",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Features"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/features/channels/{channelId}/history": {
   "get": {
    "operationId": "FeatureFlagsController_history",
    "summary": "Every change to the channel's flags, newest first (?key=, ?limit= up to 100, ?before= next_before of the last page)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "key",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "before",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Features"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/features/channels/{channelId}/preview": {
   "get": {
    "operationId": "FeatureFlagsController_preview",
    "summary": "What one user of the channel gets (managers): ?user_id=",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "user_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Features"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/features/resolve": {
   "get": {
    "operationId": "FeatureFlagsController_resolve",
    "summary": "Public: the caller's resolved feature flags for a channel, in one call",
    "description": "The channel comes from X-App-Key, else the x-ref header, else the signed-in user's channel. Signed in, the flags are resolved for that person (admins and team, listed users, beta opt-in, percentage rollout); signed out, `visitor_id` (your app's own random id, 8 to 64 of A-Z a-z 0-9 _ -) places the visitor in percentage rollouts. Internal flags that are off for the caller are left out. Cache for `ttl` seconds.",
    "parameters": [
     {
      "name": "visitor_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "in": "header",
      "description": "Channel id, when no app key is sent",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "X-App-Key",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "example": {
              "channel_id": "5f0c…",
              "signed_in": true,
              "beta": {
               "all": false,
               "keys": [
                "checkout.new-flow"
               ]
              },
              "flags": {
               "checkout.new-flow": {
                "state": "beta",
                "enabled": true,
                "reason": "opted_in",
                "name": "New checkout",
                "description": null,
                "opt_in": true
               }
              },
              "ttl": 30,
              "generated_at": "2026-10-28T10:00:00.000Z"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Features"
    ],
    "security": []
   }
  },
  "/features/v1/evaluate": {
   "get": {
    "operationId": "FeatureFlagsController_serverEvaluate",
    "summary": "Server: the flags one of your users gets (features:read): ?user_id= or ?visitor_id=",
    "description": "For your own backend, so a route of a feature that isn't GA refuses people who don't have it. Same answer as /features/resolve for that person.",
    "parameters": [
     {
      "name": "user_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "visitor_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Features"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/features/v1/flags": {
   "get": {
    "operationId": "FeatureFlagsController_serverList",
    "summary": "Server: every flag of the key's channel (features:read)",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Features"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/features/v1/flags/{key}": {
   "patch": {
    "operationId": "FeatureFlagsController_serverUpdate",
    "summary": "Server: change a flag (features:write), e.g. promote it from CI. Same body as the managers' route",
    "parameters": [
     {
      "name": "key",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Features"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/features/v1/flags/{key}/kill": {
   "post": {
    "operationId": "FeatureFlagsController_serverKill",
    "summary": "Server: kill switch (features:write), e.g. from an alert: { reason? }",
    "parameters": [
     {
      "name": "key",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Features"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/features/v1/flags/{key}/restore": {
   "post": {
    "operationId": "FeatureFlagsController_serverRestore",
    "summary": "Server: switch a killed feature back on (features:write): { reason? }",
    "parameters": [
     {
      "name": "key",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Features"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/feed": {
   "get": {
    "operationId": "FeedController_getFeed",
    "summary": "Combined trending feed. tab=all is campaign-led: blocks of 5 cycling campaign, event, campaign, job (no real posts); tab=posts|jobs|events|campaigns each returns only that type. Items are { type, data }.",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Feed"
    ],
    "security": []
   }
  },
  "/forms": {
   "post": {
    "operationId": "FormController_submitForm",
    "summary": "Submit a new form / enquiry (Public)",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateFormDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Forms & Enquiries"
    ],
    "security": []
   }
  },
  "/forms/channels/{channelId}/definitions": {
   "get": {
    "operationId": "FormDefinitionsController_list",
    "summary": "The channel's browser form definitions (channel managers)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Forms: browser forms"
    ]
   }
  },
  "/forms/channels/{channelId}/definitions/{formKey}": {
   "get": {
    "operationId": "FormDefinitionsController_get",
    "summary": "One browser form definition (channel managers)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "formKey",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Forms: browser forms"
    ]
   },
   "put": {
    "operationId": "FormDefinitionsController_put",
    "summary": "Create or replace a browser form definition (channel managers)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "formKey",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "The whole definition (docs/public-forms.md): title, status, target, fields, consent, success_message",
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Forms: browser forms"
    ]
   },
   "delete": {
    "operationId": "FormDefinitionsController_remove",
    "summary": "Remove a browser form definition; what it already filed stays (channel managers)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "formKey",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Forms: browser forms"
    ]
   }
  },
  "/forms/my": {
   "get": {
    "operationId": "FormController_getMyForms",
    "summary": "Get my submitted forms",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Forms & Enquiries"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/forms/{id}": {
   "get": {
    "operationId": "FormController_getFormById",
    "summary": "Get form submission details by ID",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Forms & Enquiries"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/forms/{id}/status": {
   "patch": {
    "operationId": "FormController_updateFormStatus",
    "summary": "Update form submission status & log audit comment (Manager)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateFormStatusDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Forms & Enquiries"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/gifs/channels/{channelId}/settings": {
   "get": {
    "operationId": "GifsController_getSettings",
    "summary": "The channel's GIF settings (the API key is never returned, only whether it is set)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "GIFs"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "put": {
    "operationId": "GifsController_setSettings",
    "summary": "Set the channel's Giphy key, on/off and ratings (\"\" clears)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/GifSettingsDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "GIFs"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/gifs/media/{id}/{file}": {
   "get": {
    "operationId": "GifsController_media",
    "summary": "A GIF or MP4 from a proxy_media link (signed for one channel, expires)",
    "description": "Supports one byte range (Range: bytes=a-b), answered 206 with Content-Range, so video players can seek.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "file",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "c",
      "required": true,
      "in": "query",
      "description": "Channel the link was made for, as given in the link",
      "schema": {
       "type": "string",
       "description": "Checked by the server against /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i."
      }
     },
     {
      "name": "e",
      "required": true,
      "in": "query",
      "description": "Expiry (unix seconds), as given in the link",
      "schema": {
       "pattern": "^[0-9]{1,12}$",
       "type": "string"
      }
     },
     {
      "name": "s",
      "required": true,
      "in": "query",
      "description": "Signature, as given in the link",
      "schema": {
       "pattern": "^[A-Za-z0-9_-]{1,64}$",
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "GIFs"
    ],
    "security": []
   }
  },
  "/gifs/search": {
   "get": {
    "operationId": "GifsController_search",
    "summary": "Search GIFs",
    "description": "Results come from Giphy through this server: no address, account or device details reach Giphy. Show \"Powered by GIPHY\" with the results. 60 requests a minute per person.",
    "parameters": [
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "description": "Items per page, 1 to 50 (default 24)",
      "schema": {
       "minimum": 1,
       "maximum": 50,
       "type": "number"
      }
     },
     {
      "name": "offset",
      "required": false,
      "in": "query",
      "description": "Where to start: next_offset of the previous page, up to 499",
      "schema": {
       "minimum": 0,
       "maximum": 499,
       "type": "number"
      }
     },
     {
      "name": "rating",
      "required": false,
      "in": "query",
      "description": "Content rating. Defaults to the channel's rating and never goes above the channel's max_rating.",
      "schema": {
       "enum": [
        "g",
        "pg",
        "pg-13",
        "r"
       ],
       "type": "string"
      }
     },
     {
      "name": "proxy_media",
      "required": false,
      "in": "query",
      "description": "true: image and video links point at this API, so the viewer's device never contacts the GIF provider. Default false (the provider's CDN).",
      "schema": {
       "type": "boolean"
      }
     },
     {
      "name": "q",
      "required": true,
      "in": "query",
      "description": "What to search for (up to 50 characters are used)",
      "schema": {
       "maxLength": 200,
       "type": "string"
      }
     },
     {
      "name": "X-App-Key",
      "in": "header",
      "description": "The channel's publishable app key",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/GifPageDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "GIFs"
    ],
    "security": []
   }
  },
  "/gifs/trending": {
   "get": {
    "operationId": "GifsController_trending",
    "summary": "Trending GIFs",
    "description": "Same privacy and limits as search. Show \"Powered by GIPHY\" with the results.",
    "parameters": [
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "description": "Items per page, 1 to 50 (default 24)",
      "schema": {
       "minimum": 1,
       "maximum": 50,
       "type": "number"
      }
     },
     {
      "name": "offset",
      "required": false,
      "in": "query",
      "description": "Where to start: next_offset of the previous page, up to 499",
      "schema": {
       "minimum": 0,
       "maximum": 499,
       "type": "number"
      }
     },
     {
      "name": "rating",
      "required": false,
      "in": "query",
      "description": "Content rating. Defaults to the channel's rating and never goes above the channel's max_rating.",
      "schema": {
       "enum": [
        "g",
        "pg",
        "pg-13",
        "r"
       ],
       "type": "string"
      }
     },
     {
      "name": "proxy_media",
      "required": false,
      "in": "query",
      "description": "true: image and video links point at this API, so the viewer's device never contacts the GIF provider. Default false (the provider's CDN).",
      "schema": {
       "type": "boolean"
      }
     },
     {
      "name": "X-App-Key",
      "in": "header",
      "description": "The channel's publishable app key",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/GifPageDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "GIFs"
    ],
    "security": []
   }
  },
  "/gifts": {
   "get": {
    "operationId": "GiftsController_list",
    "summary": "",
    "description": "List the catalog (the picker). ?status=&search=&min_price=&max_price=&page=&limit=.",
    "parameters": [
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "published",
        "draft",
        "archived"
       ],
       "type": "string"
      }
     },
     {
      "name": "search",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 150,
       "type": "string"
      }
     },
     {
      "name": "min_price",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 0,
       "type": "number"
      }
     },
     {
      "name": "max_price",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 0,
       "type": "number"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/gifts/{id}": {
   "get": {
    "operationId": "GiftsController_getOne",
    "summary": "",
    "description": "One catalog item + file_url.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/groups": {
   "get": {
    "operationId": "GroupsController_list",
    "summary": "Groups of the channel (?q=, ?mine=1, ?invited=1 for your open invitations, ?page=)",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Groups"
    ],
    "security": []
   },
   "post": {
    "operationId": "GroupsController_create",
    "summary": "Create a group: { title, description?, privacy: public|private, place? }",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Groups"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/groups/{id}": {
   "get": {
    "operationId": "GroupsController_get",
    "summary": "A group, with your membership",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Groups"
    ],
    "security": []
   },
   "patch": {
    "operationId": "GroupsController_update",
    "summary": "Edit a group (owner or admins)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Groups"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "GroupsController_remove",
    "summary": "Delete a group (owner; archived, posts kept)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Groups"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/groups/{id}/invites": {
   "post": {
    "operationId": "GroupsController_invite",
    "summary": "Invite a profile of this channel: { profile_id } (members of a public group; admins of a private one)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Groups"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/groups/{id}/join": {
   "post": {
    "operationId": "GroupsController_join",
    "summary": "Join (public: at once; private: asks the admins) or accept an invitation",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Groups"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/groups/{id}/members": {
   "get": {
    "operationId": "GroupsController_members",
    "summary": "Members (admins may ask ?status=pending|banned|invited)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Groups"
    ],
    "security": []
   }
  },
  "/groups/{id}/members/me": {
   "delete": {
    "operationId": "GroupsController_leave",
    "summary": "Leave a group, cancel a join request or decline an invitation",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Groups"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/groups/{id}/members/{profileId}": {
   "patch": {
    "operationId": "GroupsController_setMember",
    "summary": "Approve, ban or unban ({status}); make admin or member, or hand over ownership ({role})",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "profileId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Groups"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/groups/{id}/posts": {
   "get": {
    "operationId": "GroupsController_feed",
    "summary": "The group's posts, newest first (members only for private groups)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Groups"
    ],
    "security": []
   }
  },
  "/health": {
   "get": {
    "operationId": "HealthController_check",
    "summary": "Health check",
    "description": "Liveness: the process is up. Never touches dependencies.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Health"
    ],
    "security": []
   }
  },
  "/health/ready": {
   "get": {
    "operationId": "HealthController_ready",
    "summary": "Readiness check (Directus reachability)",
    "description": "Readiness: can this instance serve traffic (Directus reachable)? 200 when\nready, 503 when not, with the same envelope either way so probes and humans can\nread it. Reports states only; never URLs or error text. Redis makes the\ninstance unready only when REDIS_REQUIRED is on (multi-instance deploys);\notherwise \"off\" means cross-instance state (realtime, relay mailboxes,\nrate limits) is per instance. Kosh (our own Postgres pool) is checked\ntoo: \"off\" without KOSH_DATABASE_URL, else \"up\" or \"down\". It makes the\ninstance unready only while some module reads from it (pg mode); in\ndirectus and shadow mode Directus answers every request, so a Kosh\noutage only pauses shadow comparisons.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Health"
    ],
    "security": []
   }
  },
  "/highlights": {
   "post": {
    "operationId": "HighlightsController_createHighlight",
    "summary": "Create a new highlight group",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateHighlightDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Highlights"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "HighlightsController_getAllHighlights",
    "summary": "Get all highlights with optional filters",
    "parameters": [
     {
      "name": "sort",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Highlights"
    ],
    "security": []
   }
  },
  "/highlights/media/{mediaId}": {
   "delete": {
    "operationId": "HighlightsController_removeMediaFromHighlight",
    "summary": "Remove a media item from highlight",
    "parameters": [
     {
      "name": "mediaId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Highlights"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "HighlightsController_updateHighlightMedia",
    "summary": "Update media item inside a highlight",
    "parameters": [
     {
      "name": "mediaId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateHighlightMediaDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Highlights"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/highlights/user/{profileId}": {
   "get": {
    "operationId": "HighlightsController_getUserHighlights",
    "summary": "Get all highlights for a user profile",
    "parameters": [
     {
      "name": "profileId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "status",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "sort",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Highlights"
    ],
    "security": []
   }
  },
  "/highlights/{id}": {
   "patch": {
    "operationId": "HighlightsController_updateHighlight",
    "summary": "Update highlight details",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateHighlightDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Highlights"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "HighlightsController_deleteHighlight",
    "summary": "Delete a highlight group",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Highlights"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/highlights/{id}/media": {
   "post": {
    "operationId": "HighlightsController_addMediaToHighlight",
    "summary": "Add a media/story to a highlight",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/AddMediaToHighlightDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Highlights"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "HighlightsController_getHighlightMedia",
    "summary": "Get all media items inside a highlight",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Highlights"
    ],
    "security": []
   }
  },
  "/iam/levels": {
   "get": {
    "operationId": "IamController_levels",
    "summary": "The built-in levels (Owner, Admin, Manager, Editor, Viewer) of a business and a channel, with what each one holds",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "IAM"
    ],
    "security": []
   }
  },
  "/iam/{scope}/{scopeId}/matrix": {
   "get": {
    "operationId": "IamController_getMatrix",
    "summary": "Role × permission matrix",
    "parameters": [
     {
      "name": "scope",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "IAM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "put": {
    "operationId": "IamController_putMatrix",
    "summary": "Replace the permission keys of the listed roles",
    "parameters": [
     {
      "name": "scope",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PutMatrixDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "IAM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/iam/{scope}/{scopeId}/me": {
   "get": {
    "operationId": "IamController_me",
    "summary": "My effective permissions in a business or channel",
    "parameters": [
     {
      "name": "scope",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "scopeId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "IAM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/iam/{scope}/{scopeId}/members/{memberId}/role": {
   "put": {
    "operationId": "IamController_assignRole",
    "summary": "Assign (or clear) a member's role",
    "parameters": [
     {
      "name": "scope",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "memberId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/AssignRoleDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "IAM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/iam/{scope}/{scopeId}/permissions": {
   "get": {
    "operationId": "IamController_catalog",
    "summary": "Permission keys of the scope (core + installed apps)",
    "parameters": [
     {
      "name": "scope",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "IAM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/iam/{scope}/{scopeId}/roles": {
   "get": {
    "operationId": "IamController_listRoles",
    "summary": "List roles of a business or channel",
    "parameters": [
     {
      "name": "scope",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "IAM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "IamController_createRole",
    "summary": "Create a role",
    "parameters": [
     {
      "name": "scope",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateRoleDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "IAM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/iam/{scope}/{scopeId}/roles/{roleId}": {
   "patch": {
    "operationId": "IamController_updateRole",
    "summary": "Rename a role or replace its permissions",
    "parameters": [
     {
      "name": "scope",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "roleId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateRoleDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "IAM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "IamController_archiveRole",
    "summary": "Archive a role (409 while members hold it)",
    "parameters": [
     {
      "name": "scope",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "roleId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "IAM"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/institutions": {
   "post": {
    "operationId": "InstitutionsController_create",
    "summary": "Create a new institution (platform admin)",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateInstitutionDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Institution created successfully.",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "institutions"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "InstitutionsController_findAll",
    "summary": "Get all institutions",
    "parameters": [
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "default": 20,
       "type": "number"
      }
     },
     {
      "name": "offset",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 0,
       "default": 0,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "List of institutions.",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "institutions"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/institutions/types": {
   "get": {
    "operationId": "InstitutionsController_getTypes",
    "summary": "Get all unique institution types",
    "parameters": [],
    "responses": {
     "200": {
      "description": "List of institution types.",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "institutions"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/institutions/{id}": {
   "get": {
    "operationId": "InstitutionsController_findOne",
    "summary": "Get a specific institution by ID",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Institution details.",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "404": {
      "description": "Institution not found."
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "institutions"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "InstitutionsController_update",
    "summary": "Update an institution (platform admin)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateInstitutionDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Institution updated successfully.",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "404": {
      "description": "Institution not found."
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "institutions"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "InstitutionsController_remove",
    "summary": "Delete an institution (platform admin)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Institution deleted successfully.",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "404": {
      "description": "Institution not found."
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "institutions"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/invitations/me": {
   "get": {
    "operationId": "InvitationsController_me",
    "summary": "My pending invitations across businesses and channels, plus ownership transfers offered to me",
    "parameters": [
     {
      "name": "page",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Invites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/invitations/{kind}/{id}/accept": {
   "post": {
    "operationId": "InvitationsController_accept",
    "summary": "Accept one of my invitations (kind = business | channel)",
    "parameters": [
     {
      "name": "kind",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Invites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/invitations/{kind}/{id}/decline": {
   "post": {
    "operationId": "InvitationsController_decline",
    "summary": "Decline one of my invitations (kind = business | channel)",
    "parameters": [
     {
      "name": "kind",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Invites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/invite/accept": {
   "post": {
    "operationId": "InviteController_accept",
    "summary": "Accept an invite as the now-authenticated user",
    "parameters": [],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Invites"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/invite/reject": {
   "post": {
    "operationId": "InviteController_reject",
    "summary": "Decline an invite (no login required)",
    "parameters": [],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Invites"
    ],
    "security": []
   }
  },
  "/invite/resolve": {
   "get": {
    "operationId": "InviteController_resolve",
    "summary": "Decode + validate an invite token",
    "parameters": [
     {
      "name": "token",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Invites"
    ],
    "security": []
   }
  },
  "/job-applications/me": {
   "get": {
    "operationId": "JobApplicationsController_me",
    "summary": "",
    "description": "A4: the caller's own applications.",
    "parameters": [
     {
      "name": "active_profile_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/job-applications/{id}": {
   "patch": {
    "operationId": "JobApplicationsController_updateStatus",
    "summary": "",
    "description": "A3: move an applicant through the pipeline (job poster only).",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateApplicationStatusDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   },
   "delete": {
    "operationId": "JobApplicationsController_withdraw",
    "summary": "",
    "description": "A5: withdraw (the applicant only).",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/job-applications/{id}/history": {
   "get": {
    "operationId": "JobApplicationsController_history",
    "summary": "",
    "description": "A6: the status timeline (the applicant OR the job poster). Before `:id`.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/jobs": {
   "post": {
    "operationId": "JobsController_create",
    "summary": "",
    "description": "J1: create a job (post + job). multipart: title/description/JD image/job fields.\n The REAL client IP (Cloudflare CF-Connecting-IP) is captured here and stored as\n the post's creation IP (set once).",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateJobDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   },
   "get": {
    "operationId": "JobsController_list",
    "summary": "",
    "description": "J2: the job feed (filters + pagination). Public: guests read via x-ref.",
    "parameters": [
     {
      "name": "active_profile_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "user_profile_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "category_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "job_type",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "location_type",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "experience_level",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "min_salary",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 0,
       "type": "number"
      }
     },
     {
      "name": "max_salary",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 0,
       "type": "number"
      }
     },
     {
      "name": "search",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 150,
       "type": "string"
      }
     },
     {
      "name": "hiring_status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "open",
        "closed",
        "paused",
        "filled"
       ],
       "type": "string"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 40,
       "type": "string"
      }
     },
     {
      "name": "archived",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "true",
        "false",
        "1",
        "0"
       ],
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "security": []
   }
  },
  "/jobs/my": {
   "get": {
    "operationId": "JobsController_listMine",
    "summary": "",
    "description": "J2c: the caller's own jobs (every status but archived; ?archived=1 only\n owner-archived, ?archived=0 only live). Static route\n MUST be declared before :id or \"my\" parses as a numeric id (JOBS-4).",
    "parameters": [
     {
      "name": "active_profile_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "user_profile_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "category_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "job_type",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "location_type",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "experience_level",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "min_salary",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 0,
       "type": "number"
      }
     },
     {
      "name": "max_salary",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 0,
       "type": "number"
      }
     },
     {
      "name": "search",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 150,
       "type": "string"
      }
     },
     {
      "name": "hiring_status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "open",
        "closed",
        "paused",
        "filled"
       ],
       "type": "string"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 40,
       "type": "string"
      }
     },
     {
      "name": "archived",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "true",
        "false",
        "1",
        "0"
       ],
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/jobs/public/application-status": {
   "get": {
    "operationId": "JobsPublicController_status",
    "summary": "Status of one public job application, from the emailed link's token (Public)",
    "parameters": [
     {
      "name": "t",
      "required": true,
      "in": "query",
      "schema": {
       "maxLength": 2048,
       "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$",
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Jobs: public applications"
    ],
    "security": []
   }
  },
  "/jobs/public/application-status/page": {
   "get": {
    "operationId": "JobsPublicController_statusPage",
    "summary": "The same status as a small web page (the emailed link opens this) (Public)",
    "parameters": [
     {
      "name": "t",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Jobs: public applications"
    ],
    "security": []
   }
  },
  "/jobs/public/{channelId}/{jobId}/apply": {
   "post": {
    "operationId": "JobsPublicController_submit",
    "summary": "Public job application, step 2: apply without an account. Needs consent; the CV (if any) is checked and scanned; the applicant is emailed a status link. Never changes an existing application (Public)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "jobId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/WebApplyDto"
       }
      }
     }
    },
    "responses": {
     "202": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Jobs: public applications"
    ],
    "security": []
   }
  },
  "/jobs/public/{channelId}/{jobId}/cv-upload": {
   "post": {
    "operationId": "JobsPublicController_cvUpload",
    "summary": "Public job application, step 1: a short-lived signed URL to PUT the CV to (pdf/doc/docx, at most 5 MB; type and size are signed) and the cv_token for step 2 (Public)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "jobId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CvUploadDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Jobs: public applications"
    ],
    "security": []
   }
  },
  "/jobs/trending": {
   "get": {
    "operationId": "JobsController_trending",
    "summary": "",
    "description": "J2b: trending jobs (score = views + applicants×5). Static route before :id.",
    "parameters": [
     {
      "name": "active_profile_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "user_profile_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "category_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "job_type",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "location_type",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "experience_level",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "min_salary",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 0,
       "type": "number"
      }
     },
     {
      "name": "max_salary",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 0,
       "type": "number"
      }
     },
     {
      "name": "search",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 150,
       "type": "string"
      }
     },
     {
      "name": "hiring_status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "open",
        "closed",
        "paused",
        "filled"
       ],
       "type": "string"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 40,
       "type": "string"
      }
     },
     {
      "name": "archived",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "true",
        "false",
        "1",
        "0"
       ],
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "security": []
   }
  },
  "/jobs/web-applications/{applicationId}": {
   "patch": {
    "operationId": "JobWebApplicationsController_setStatus",
    "summary": "Move a website application along (received, reviewing, interview, offer, hired, not_selected); the applicant's status link shows it",
    "parameters": [
     {
      "name": "applicationId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateWebApplicationDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Jobs: public applications"
    ]
   },
   "delete": {
    "operationId": "JobWebApplicationsController_remove",
    "summary": "Erase a website application and its CV (erasure request or spam; channel staff or the poster)",
    "parameters": [
     {
      "name": "applicationId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Jobs: public applications"
    ]
   }
  },
  "/jobs/web-applications/{applicationId}/cv": {
   "get": {
    "operationId": "JobWebApplicationsController_cv",
    "summary": "A 5-minute download link for the application's CV (only a CV the malware scan cleared)",
    "parameters": [
     {
      "name": "applicationId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Jobs: public applications"
    ]
   }
  },
  "/jobs/{id}": {
   "get": {
    "operationId": "JobsController_getOne",
    "summary": "",
    "description": "J3: one job (+ category + applicant_count). Public: guests read via x-ref.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "security": []
   },
   "patch": {
    "operationId": "JobsController_update",
    "summary": "",
    "description": "J4: update (owner only); fields routed to post vs job. multipart `image`.\n `archived: true|false` sets/clears job.archived_at (hidden from public lists).\n The REAL client IP is captured and stored as the post's last_ip (the original\n creation `ip` is never overwritten).",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateJobDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   },
   "delete": {
    "operationId": "JobsController_remove",
    "summary": "",
    "description": "J5: archive the post and the job (owner only).",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/jobs/{id}/applicants": {
   "get": {
    "operationId": "JobsController_applicants",
    "summary": "",
    "description": "A2: the poster's applicant CRM list.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 120,
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/jobs/{id}/apply": {
   "post": {
    "operationId": "JobsController_apply",
    "summary": "",
    "description": "A1: apply to a job. ONE CLICK: no body (the profile is the resume).\n JOBS-10: optional active_profile_id to apply as a specific owned profile.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/jobs/{id}/web-applications": {
   "get": {
    "operationId": "JobWebApplicationsController_list",
    "summary": "Applications sent from the website (no account) for one job, newest first (channel staff or the poster)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "received",
        "reviewing",
        "interview",
        "offer",
        "hired",
        "not_selected"
       ],
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Jobs: public applications"
    ]
   }
  },
  "/listings/interest/mine": {
   "get": {
    "operationId": "ListingsController_mine",
    "summary": "Your own inquiries and offers on this channel (x-ref or X-App-Key)",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Listings"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/listings/interest/{interestId}": {
   "patch": {
    "operationId": "ListingsController_answer",
    "summary": "The seller accepts or declines an offer { status: accepted | declined } or closes an inquiry { status: closed }; the buyer withdraws their own { status: withdrawn }",
    "parameters": [
     {
      "name": "interestId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Listings"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/listings/posts/{id}/sold": {
   "post": {
    "operationId": "ListingsController_sold",
    "summary": "The author marks their listing post sold: it leaves the feeds, open inquiries and offers close and those people are told",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Listings"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/listings/{type}/{id}/inquiries": {
   "post": {
    "operationId": "ListingsController_inquire",
    "summary": "Ask the seller about a listing: { message, active_profile_id? } (500 characters)",
    "parameters": [
     {
      "name": "type",
      "required": true,
      "in": "path",
      "schema": {
       "enum": [
        "posts",
        "products"
       ],
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Listings"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/listings/{type}/{id}/interest": {
   "get": {
    "operationId": "ListingsController_forListing",
    "summary": "A listing's inquiries and offers, for its seller (?status=open|accepted|declined|withdrawn|closed)",
    "parameters": [
     {
      "name": "type",
      "required": true,
      "in": "path",
      "schema": {
       "enum": [
        "posts",
        "products"
       ],
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "status",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Listings"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/listings/{type}/{id}/offers": {
   "post": {
    "operationId": "ListingsController_offer",
    "summary": "Make an offer: { amount, currency?, message?, active_profile_id? }. No currency means the listing's own (else the channel's). One open offer per person and listing; a new amount replaces it.",
    "parameters": [
     {
      "name": "type",
      "required": true,
      "in": "path",
      "schema": {
       "enum": [
        "posts",
        "products"
       ],
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Listings"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/media/channels/{channelId}/assets": {
   "get": {
    "operationId": "MediaManageController_assets",
    "summary": "The channel's own videos (its server key's), newest first (?status, ?limit, ?offset)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/media/channels/{channelId}/jobs": {
   "get": {
    "operationId": "MediaManageController_jobList",
    "summary": "Processing jobs of the channel, newest first (?status, ?limit)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/media/channels/{channelId}/overview": {
   "get": {
    "operationId": "MediaManageController_overview",
    "summary": "Media & storage: limits, storage by kind, this month's use, counts (channel managers)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/media/channels/{channelId}/quota": {
   "put": {
    "operationId": "MediaManageController_setQuota",
    "summary": "Set a channel's media limits (platform only)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/media/channels/{channelId}/usage": {
   "get": {
    "operationId": "MediaManageController_usage",
    "summary": "Daily bytes in, downloads, plays and processing minutes (?days ≤ 90)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "days",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/media/v1/assets": {
   "post": {
    "operationId": "MediaAssetsController_create",
    "summary": "Create a video: { title?, visibility: private|public, source_file_id?, options: { max_height, av1, auto_captions, captions_lang }, passthrough? }",
    "description": "Without source_file_id, upload the source with tus (Upload-Metadata purpose vod_source, asset_id). Processing starts when the file is stored and checked.",
    "parameters": [],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "MediaAssetsController_list",
    "summary": "Your videos, newest first (?status, ?limit, ?offset)",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/media/v1/assets/{id}": {
   "get": {
    "operationId": "MediaAssetsController_get",
    "summary": "One video: status (waiting_upload, queued, processing, ready, failed), progress, renditions, tracks",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "MediaAssetsController_update",
    "summary": "Change title, visibility or passthrough",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "MediaAssetsController_remove",
    "summary": "Delete a video and its renditions (the source file stays until you delete it)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/media/v1/assets/{id}/captions": {
   "post": {
    "operationId": "MediaAssetsController_captions",
    "summary": "Auto captions (speech to text): { lang: \"en\" | null to detect }",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/media/v1/assets/{id}/playback": {
   "get": {
    "operationId": "MediaAssetsController_playback",
    "summary": "Signed playback: HLS (CMAF) and DASH manifests, poster, thumbnails, sprite previews, subtitles (?ttl seconds)",
    "description": "One folder token covers every segment, so players fetch relative URLs straight from the CDN.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "ttl",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/media/v1/assets/{id}/tracks": {
   "get": {
    "operationId": "MediaAssetsController_tracks",
    "summary": "Audio (dub) and subtitle tracks with their status",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/media/v1/assets/{id}/tracks/{trackId}": {
   "delete": {
    "operationId": "MediaAssetsController_removeTrack",
    "summary": "Remove an audio or subtitle track (a new manifest version is published)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "trackId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/media/v1/files": {
   "get": {
    "operationId": "MediaStorageController_list",
    "summary": "Your files, newest first (?limit, ?offset, ?purpose)",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/media/v1/files/claim": {
   "post": {
    "operationId": "MediaStorageController_claim",
    "summary": "Upload skipped: you already stored these bytes ({ sha256, size, filename }) → a new file, 404 if not",
    "description": "Checks only your own storage, never anyone else's.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/media/v1/files/{id}": {
   "get": {
    "operationId": "MediaStorageController_get",
    "summary": "One file: name, type, size, SHA-256, status (scanning | ready | refused)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "MediaStorageController_remove",
    "summary": "Delete a file (its bytes go once nothing else of yours uses them)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/media/v1/files/{id}/url": {
   "get": {
    "operationId": "MediaStorageController_url",
    "summary": "A signed download link (?ttl seconds, 60–86400). Byte ranges work: resume or download in parallel chunks.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "ttl",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/media/v1/public/assets/{id}/playback": {
   "get": {
    "operationId": "MediaAssetsController_publicPlayback",
    "summary": "Playback of a PUBLIC video with the channel's app key (X-App-Key)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": []
   }
  },
  "/media/v1/uploads": {
   "options": {
    "operationId": "MediaStorageController_discover",
    "summary": "tus discovery: version, extensions, checksum algorithms, largest file",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "MediaStorageController_create",
    "summary": "tus: create an upload (Upload-Length, Upload-Metadata: filename, filetype, purpose, sha256, asset_id, lang, label)",
    "description": "creation-with-upload: send the first bytes in the same request (Content-Type: application/offset+octet-stream).",
    "parameters": [],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/media/v1/uploads/{id}": {
   "head": {
    "operationId": "MediaStorageController_head",
    "summary": "tus: where an upload stands (Upload-Offset, Upload-Length)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "MediaStorageController_patch",
    "summary": "tus: append bytes at Upload-Offset (Upload-Checksum: sha256|sha1|md5 <base64> is checked)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "MediaStorageController_terminate",
    "summary": "tus termination: abort an upload and drop its bytes",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "MediaStorageController_status",
    "summary": "An upload as JSON: status, offset, and file_id once it is finished",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Media"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/moderation/check": {
   "post": {
    "operationId": "ModerationController_check",
    "summary": "Moderate text and/or images (returns the verdict)",
    "description": "Test and utility endpoint: run text or images through the moderation chain and\nsee the verdict ({ decision, flagged, provider, categories, score }). It\nspends the org's paid provider quota, so it requires a signed-in user and\nis tightly throttled; provider diagnostics are never returned. The real\nmoderation runs INTERNALLY during content creation, not via this endpoint.",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ModerationCheckDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Moderation"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/network/blocks": {
   "get": {
    "operationId": "NetworkController_blocks",
    "summary": "People you blocked on this channel",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "People network"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "NetworkController_block",
    "summary": "Block someone: { profile_id }. Drops your connection, requests, follows and shares.",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "People network"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/network/blocks/{profileId}": {
   "delete": {
    "operationId": "NetworkController_unblock",
    "summary": "Unblock someone",
    "parameters": [
     {
      "name": "profileId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "People network"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/network/connections": {
   "get": {
    "operationId": "NetworkController_connections",
    "summary": "Your connections, newest first, with online where they allow it (?page=, ?limit= ≤ 100)",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "People network"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/network/connections/{profileId}": {
   "delete": {
    "operationId": "NetworkController_remove",
    "summary": "Remove a connection (they are not told)",
    "parameters": [
     {
      "name": "profileId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "People network"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/network/online": {
   "get": {
    "operationId": "NetworkController_online",
    "summary": "Profile ids of your connections online on this channel now",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "People network"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/network/people/{profileId}": {
   "get": {
    "operationId": "NetworkController_person",
    "summary": "One person of this channel and how you relate (connection, can_request, can_share)",
    "parameters": [
     {
      "name": "profileId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "People network"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/network/requests": {
   "get": {
    "operationId": "NetworkController_requests",
    "summary": "Connection requests: ?direction=incoming (default) | outgoing",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "People network"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "NetworkController_request",
    "summary": "Ask to connect: { profile_id }. Accepts theirs if they already asked you.",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "People network"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/network/requests/{id}": {
   "delete": {
    "operationId": "NetworkController_cancel",
    "summary": "Cancel a request you sent",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "People network"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/network/requests/{id}/accept": {
   "post": {
    "operationId": "NetworkController_accept",
    "summary": "Accept a request sent to you",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "People network"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/network/requests/{id}/decline": {
   "post": {
    "operationId": "NetworkController_decline",
    "summary": "Decline a request sent to you (the sender isn't told)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "People network"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/network/search": {
   "get": {
    "operationId": "NetworkController_search",
    "summary": "Find people of this channel by handle or name prefix (?q=, 2–32 chars; ?limit= ≤ 25)",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "People network"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/network/settings": {
   "get": {
    "operationId": "NetworkController_settings",
    "summary": "Your people-network privacy: findable, show_online, requests_from, shares_from",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "People network"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "NetworkController_updateSettings",
    "summary": "Change your privacy: { findable?: everyone|connections|nobody, show_online?: connections|nobody, requests_from?: everyone|nobody, shares_from?: connections|nobody }",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "People network"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/network/shares": {
   "post": {
    "operationId": "NetworkController_share",
    "summary": "Share a link with connections: { url (https, ≤ 2048), title? (≤ 200), note? (≤ 280), profile_id | profile_ids (≤ 10) }",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "People network"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "NetworkController_shares",
    "summary": "Links shared with you (?box=received, default) or by you (?box=sent); ?unread=1, ?page=",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "People network"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/network/shares/{id}": {
   "delete": {
    "operationId": "NetworkController_deleteShare",
    "summary": "Remove a share from your inbox, or unsend one you sent",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "People network"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/network/shares/{id}/read": {
   "post": {
    "operationId": "NetworkController_read",
    "summary": "Mark a share you received as read",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "People network"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/notes": {
   "get": {
    "operationId": "NotesController_list",
    "summary": "List the signed-in user's notes (search)",
    "parameters": [
     {
      "name": "q",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 200,
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Notes"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "NotesController_create",
    "summary": "Create a note",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateNoteDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Notes"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/notes/{id}": {
   "get": {
    "operationId": "NotesController_getOne",
    "summary": "Get a single note",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Notes"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "NotesController_update",
    "summary": "Edit a note",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateNoteDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Notes"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "NotesController_remove",
    "summary": "Delete a note (returns the deleted note for Undo)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Notes"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/notifications": {
   "get": {
    "operationId": "NotificationsController_getNotifications",
    "summary": "The signed-in account's notifications, newest first",
    "description": "Each row carries the stable `type` and `target` (`{ kind, id, ...ids }`, ids as strings), the same as the SSE `notification.created` event and the push `data`. `security.device_added` rows carry `target.device_id`: the e2ee device id of the device that was added.",
    "parameters": [
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "$ref": "#/components/schemas/NotificationDto"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/notifications/broadcast": {
   "post": {
    "operationId": "NotificationsController_broadcast",
    "parameters": [
     {
      "name": "x-admin-key",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "security": []
   }
  },
  "/notifications/preferences": {
   "get": {
    "operationId": "NotificationsController_getPreferences",
    "summary": "Your notification preferences: flat per-type push switches and `delivery: { <type>: { in_app, push, email } }` for like, comment, repost, donation, follow, campaign, connection, share, mention, group, event, listing and safety",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   },
   "patch": {
    "operationId": "NotificationsController_updatePreferences",
    "summary": "Change preferences: flat `{ <type>: boolean }` (push) and/or `{ delivery: { <type>: { in_app?, push?, email? } } }`. Unknown types, channels or non-boolean values answer 400.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/notifications/push-token": {
   "post": {
    "operationId": "NotificationsController_registerPushToken",
    "parameters": [],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   },
   "delete": {
    "operationId": "NotificationsController_removePushToken",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/notifications/read-all": {
   "patch": {
    "operationId": "NotificationsController_markAllAsRead",
    "parameters": [
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/notifications/unread-count": {
   "get": {
    "operationId": "NotificationsController_getUnreadCount",
    "parameters": [
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/notifications/{id}/read": {
   "patch": {
    "operationId": "NotificationsController_markAsRead",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/openapi.json": {
   "get": {
    "operationId": "OpenApiController_spec",
    "summary": "OpenAPI 3 description of the Kodkila API (v1)",
    "description": "Raw OpenAPI document. `servers` lists https://api-dev.kodkila.com/v1 (development, live) and https://api.kodkila.com/v1 (production, not live yet); paths are relative to them.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Developer"
    ],
    "security": []
   }
  },
  "/orders": {
   "post": {
    "operationId": "OrdersController_create",
    "summary": "Place an order in the token's channel",
    "parameters": [
     {
      "name": "Idempotency-Key",
      "in": "header",
      "description": "Optional client-generated key (8-128 chars, [A-Za-z0-9_-]). A retry with the same key and body replays the first response (Idempotent-Replayed: true); 409 while the first is in flight; 422 if the body differs.",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateOrderDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Orders"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "OrdersController_findMyOrders",
    "summary": "My orders (as buyer), paged",
    "parameters": [
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "pending",
        "processing",
        "shipped",
        "delivered",
        "cancelled"
       ],
       "type": "string"
      }
     },
     {
      "name": "sort",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "date_created",
        "-date_created",
        "total",
        "-total"
       ],
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 10000,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Orders"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/orders/seller": {
   "get": {
    "operationId": "OrdersController_findSellerOrders",
    "summary": "Orders received by a channel I manage / my business",
    "parameters": [
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "pending",
        "processing",
        "shipped",
        "delivered",
        "cancelled"
       ],
       "type": "string"
      }
     },
     {
      "name": "sort",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "date_created",
        "-date_created",
        "total",
        "-total"
       ],
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 10000,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "description": "Seller channel (defaults to the token's channel)",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Orders"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/orders/seller/customers": {
   "get": {
    "operationId": "OrdersController_findSellerCustomers",
    "summary": "Customers of a channel I manage (from its orders)",
    "parameters": [
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "description": "Seller channel (defaults to the token's channel)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "description": "Search name, email or mobile",
      "schema": {
       "maxLength": 100,
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Orders"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/orders/{id}": {
   "get": {
    "operationId": "OrdersController_findOne",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Orders"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/orders/{id}/cancel": {
   "patch": {
    "operationId": "OrdersController_cancel",
    "summary": "Buyer cancels a pending / processing order",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CancelOrderDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Orders"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/orders/{id}/status": {
   "patch": {
    "operationId": "OrdersController_updateStatus",
    "summary": "Seller moves an order along the state machine",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateOrderStatusDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Orders"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/orders/{id}/track": {
   "get": {
    "operationId": "OrdersController_track",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Orders"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/pages": {
   "get": {
    "operationId": "PagesController_getPages",
    "summary": "List a channel's published pages (Public)",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "description": "Channel id",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Pages & Configuration"
    ],
    "security": []
   }
  },
  "/pages/channel/{channelId}": {
   "get": {
    "operationId": "PagesController_getChannelPages",
    "summary": "List a channel's published pages (Public)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Pages & Configuration"
    ],
    "security": []
   }
  },
  "/pages/channel/{channelId}/{slug}": {
   "get": {
    "operationId": "PagesController_getChannelPageBySlug",
    "summary": "Get a channel's published page by exact slug (Public)",
    "description": "Entry flow: channel → pages → slug (e.g. \"index\"). Exact match.",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "slug",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Pages & Configuration"
    ],
    "security": []
   }
  },
  "/pages/{slug}": {
   "get": {
    "operationId": "PagesController_getPageBySlug",
    "summary": "Get a published page by exact slug for the x-ref channel (Public)",
    "parameters": [
     {
      "name": "slug",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "description": "Channel id",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Pages & Configuration"
    ],
    "security": []
   }
  },
  "/payments/create": {
   "post": {
    "operationId": "PaymentsController_create",
    "parameters": [
     {
      "name": "Idempotency-Key",
      "in": "header",
      "description": "Optional client-generated key (8-128 chars, [A-Za-z0-9_-]). A retry with the same key and body replays the first response (Idempotent-Replayed: true); 409 while the first is in flight; 422 if the body differs.",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreatePaymentDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/payments/demo": {
   "get": {
    "operationId": "DemoPaymentsController_info",
    "summary": "Demo payments status + test cards (404 when off)",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Payments (demo)"
    ],
    "security": []
   }
  },
  "/payments/demo/charge": {
   "post": {
    "operationId": "DemoPaymentsController_charge",
    "summary": "Charge a DEMO payment with a test card (4242… success, 4000…0002 decline, 4000002500003155 3-D Secure)",
    "parameters": [
     {
      "name": "Idempotency-Key",
      "in": "header",
      "description": "Optional client-generated key (8-128 chars, [A-Za-z0-9_-]). A retry with the same key and body replays the first response (Idempotent-Replayed: true); 409 while the first is in flight; 422 if the body differs.",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/DemoChargeDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Payments (demo)"
    ]
   }
  },
  "/payments/demo/checkout/{paymentId}": {
   "get": {
    "operationId": "DemoPaymentsController_checkout",
    "summary": "Hosted DEMO checkout page (HTML; no real money)",
    "parameters": [
     {
      "name": "paymentId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "t",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "challenge",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Payments (demo)"
    ],
    "security": []
   }
  },
  "/payments/demo/checkout/{paymentId}/complete": {
   "post": {
    "operationId": "DemoPaymentsController_complete",
    "summary": "Complete a DEMO checkout (form post). Settles via the Stripe webhook path, then redirects (303) to return_url or shows a receipt",
    "parameters": [
     {
      "name": "paymentId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/DemoCompleteDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Payments (demo)"
    ],
    "security": []
   }
  },
  "/payments/my": {
   "get": {
    "operationId": "PaymentsController_getMy",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/payments/verify": {
   "post": {
    "operationId": "PaymentsController_verify",
    "parameters": [
     {
      "name": "Idempotency-Key",
      "in": "header",
      "description": "Optional client-generated key (8-128 chars, [A-Za-z0-9_-]). A retry with the same key and body replays the first response (Idempotent-Replayed: true); 409 while the first is in flight; 422 if the body differs.",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/VerifyPaymentDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/payments/webhook/razorpay": {
   "post": {
    "operationId": "PaymentsController_razorpayWebhook",
    "parameters": [
     {
      "name": "x-razorpay-signature",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "security": []
   }
  },
  "/payments/webhook/stripe": {
   "post": {
    "operationId": "PaymentsController_stripeWebhook",
    "parameters": [
     {
      "name": "stripe-signature",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "security": []
   }
  },
  "/payments/{id}": {
   "get": {
    "operationId": "PaymentsController_getOne",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/platform/company": {
   "get": {
    "operationId": "PlatformController_company",
    "summary": "Seller / company details (legal name, number, registered office)",
    "description": "The legal entity that operates the platform (public registry data).",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Platform"
    ],
    "security": []
   }
  },
  "/post-gifts": {
   "post": {
    "operationId": "PostGiftsController_send",
    "summary": "",
    "description": "Send a catalog gift on a post (NEW row every time).",
    "parameters": [
     {
      "name": "Idempotency-Key",
      "in": "header",
      "description": "Optional client-generated key (8-128 chars, [A-Za-z0-9_-]). A retry with the same key and body replays the first response (Idempotent-Replayed: true); 409 while the first is in flight; 422 if the body differs.",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/SendPostGiftDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/post-gifts/post/{postId}": {
   "get": {
    "operationId": "PostGiftsController_listByPost",
    "summary": "",
    "description": "All gifts sent on a post (detailed, each with catalog detail).",
    "parameters": [
     {
      "name": "postId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/post-gifts/post/{postId}/summary": {
   "get": {
    "operationId": "PostGiftsController_postSummary",
    "summary": "",
    "description": "A post's gift total and count (the feed bridge; no rows embedded).",
    "parameters": [
     {
      "name": "postId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/post-gifts/received": {
   "get": {
    "operationId": "PostGiftsController_received",
    "summary": "",
    "description": "Gifts I received (+ total received).",
    "parameters": [
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/post-gifts/sent": {
   "get": {
    "operationId": "PostGiftsController_sent",
    "summary": "",
    "description": "Gifts I sent.",
    "parameters": [
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/post-gifts/{id}": {
   "get": {
    "operationId": "PostGiftsController_getOne",
    "summary": "",
    "description": "One transaction (sender or recipient).",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/posts": {
   "post": {
    "operationId": "PostsController_createPost",
    "summary": "Create a new post",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreatePostDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/posts/comment/{id}": {
   "patch": {
    "operationId": "PostsController_updateComment",
    "summary": "Update my comment",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "PostsController_deleteComment",
    "summary": "Delete my comment",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/posts/comment/{id}/like": {
   "post": {
    "operationId": "PostsController_toggleCommentLike",
    "summary": "Like or Unlike a comment",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/posts/comments/my": {
   "get": {
    "operationId": "PostsController_getMyComments",
    "summary": "Fetch all comments written by me",
    "parameters": [
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/posts/following": {
   "get": {
    "operationId": "PostsController_getFollowingPosts",
    "summary": "Get posts feed only from followed profiles",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/posts/likes/my": {
   "get": {
    "operationId": "PostsController_getMyLikedPosts",
    "summary": "Fetch all posts liked by me",
    "parameters": [
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "include",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/posts/my": {
   "get": {
    "operationId": "PostsController_findAllMyPosts",
    "summary": "Fetch all my posts",
    "parameters": [
     {
      "name": "page",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/posts/my/{id}": {
   "get": {
    "operationId": "PostsController_findOneMyPost",
    "summary": "Fetch a single post of mine",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/posts/profile/{profileId}": {
   "get": {
    "operationId": "PostsController_getProfileFeed",
    "summary": "Get a profile's combined feed: its own posts + reposts (with attribution)",
    "parameters": [
     {
      "name": "profileId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": []
   }
  },
  "/posts/reposts/my": {
   "get": {
    "operationId": "PostsController_getMyRepostedPosts",
    "summary": "Fetch all posts reposted by me",
    "parameters": [
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/posts/saves/my": {
   "get": {
    "operationId": "PostsController_getMySavedPosts",
    "summary": "Fetch all posts saved by me",
    "parameters": [
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "include",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/posts/trending": {
   "get": {
    "operationId": "PostsController_getTrendingPosts",
    "summary": "Get trending posts feed based on views, comments, and likes",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": []
   }
  },
  "/posts/{id}": {
   "patch": {
    "operationId": "PostsController_updatePost",
    "summary": "Update my post",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdatePostDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "PostsController_deletePost",
    "summary": "Delete my post",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "PostsController_getPublicPost",
    "summary": "One public post of the channel (x-ref / X-App-Key), with media, counts and the viewer's like",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": []
   }
  },
  "/posts/{id}/comments": {
   "post": {
    "operationId": "PostsController_addComment",
    "summary": "Add a comment or reply to a post",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "PostsController_getComments",
    "summary": "Fetch comments and replies for a post",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": []
   }
  },
  "/posts/{id}/dislike": {
   "post": {
    "operationId": "PostsController_toggleDislike",
    "summary": "Dislike or Un-dislike a post",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/posts/{id}/donate": {
   "post": {
    "operationId": "PostsController_donate",
    "summary": "Make a donation on a post",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "Idempotency-Key",
      "in": "header",
      "description": "Optional client-generated key (8-128 chars, [A-Za-z0-9_-]). A retry with the same key and body replays the first response (Idempotent-Replayed: true); 409 while the first is in flight; 422 if the body differs.",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/DonateDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/posts/{id}/donations": {
   "get": {
    "operationId": "PostsController_getDonations",
    "summary": "Get all donations for a post",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": []
   }
  },
  "/posts/{id}/files": {
   "post": {
    "operationId": "PostsController_attachFile",
    "summary": "Attach a file to a post",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/posts/{id}/files/bulk": {
   "post": {
    "operationId": "PostsController_attachFilesBulk",
    "summary": "Attach multiple files to a post in bulk",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/posts/{id}/files/{file_id}": {
   "delete": {
    "operationId": "PostsController_removeFile",
    "summary": "Remove a file from a post",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "file_id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/posts/{id}/like": {
   "post": {
    "operationId": "PostsController_toggleLike",
    "summary": "Like or Unlike a post",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/posts/{id}/likes": {
   "get": {
    "operationId": "PostsController_getPostLikes",
    "summary": "Profiles who liked a post + total count (drawer)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": []
   }
  },
  "/posts/{id}/repost": {
   "post": {
    "operationId": "PostsController_toggleRepost",
    "summary": "Repost, quote-repost, or unrepost a post",
    "description": "No comment = plain repost/unrepost toggle. A non-empty `comment` makes it a quote repost (adds/updates the quote text; never toggles off). The quote is trimmed, max 280 characters, and moderated (400 when not approved). Response: { reposted, quoted, comment }.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/posts/{id}/reposts": {
   "get": {
    "operationId": "PostsController_getPostReposts",
    "summary": "Profiles who reposted a post + total count (drawer)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": []
   }
  },
  "/posts/{id}/save": {
   "post": {
    "operationId": "PostsController_toggleSave",
    "summary": "Save or Unsave a post",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/posts/{id}/share": {
   "post": {
    "operationId": "PostsController_toggleShare",
    "summary": "Share or Unshare a post",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/posts/{id}/shares": {
   "get": {
    "operationId": "PostsController_getPostShares",
    "summary": "Profiles who shared a post + total share count",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": []
   }
  },
  "/posts/{id}/view": {
   "post": {
    "operationId": "PostsController_recordView",
    "summary": "Record a post view (deduplicated per viewer)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Posts"
    ],
    "security": []
   }
  },
  "/presence/publish": {
   "post": {
    "operationId": "PresenceController_publish",
    "summary": "",
    "description": "Share your state, or send an event, to the rooms of one of your connections.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/presence/stream": {
   "get": {
    "operationId": "PresenceController_stream",
    "summary": "",
    "description": "Join presence rooms and receive everyone else's state and events as SSE:\n`presence.hello` (your connection id), `presence.state`, `presence.event`,\n`presence.leave`. `?rooms=channel:<id>,business:<id>,inbox:<id>`; each must\nbe yours; `inbox:` rooms are listen-only (no publishes, nobody heard).",
    "parameters": [
     {
      "name": "rooms",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/products": {
   "get": {
    "operationId": "ProductsController_findAll",
    "summary": "Published products of a channel (paged)",
    "parameters": [
     {
      "name": "q",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 100,
       "type": "string"
      }
     },
     {
      "name": "type",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 100,
       "type": "string"
      }
     },
     {
      "name": "sort",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "date_created",
        "-date_created",
        "name",
        "-name"
       ],
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 10000,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Products"
    ],
    "security": []
   },
   "post": {
    "operationId": "ProductsController_create",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateProductDto"
       }
      },
      "multipart/form-data": {
       "schema": {
        "$ref": "#/components/schemas/CreateProductDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Products"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/products/manage": {
   "get": {
    "operationId": "ProductsController_manage",
    "summary": "All products of a channel the caller manages",
    "parameters": [
     {
      "name": "q",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 100,
       "type": "string"
      }
     },
     {
      "name": "type",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 100,
       "type": "string"
      }
     },
     {
      "name": "sort",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "date_created",
        "-date_created",
        "name",
        "-name"
       ],
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 10000,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "description": "Defaults to the token's channel",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "draft",
        "published",
        "sold",
        "archived",
        "under_review",
        "rejected"
       ],
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Products"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/products/search": {
   "get": {
    "operationId": "ProductsController_search",
    "summary": "Search published products of a channel",
    "description": "Kept for older clients; same as GET /products?q=…",
    "parameters": [
     {
      "name": "q",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 100,
       "type": "string"
      }
     },
     {
      "name": "type",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 100,
       "type": "string"
      }
     },
     {
      "name": "sort",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "date_created",
        "-date_created",
        "name",
        "-name"
       ],
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 10000,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Products"
    ],
    "security": []
   }
  },
  "/products/slug/{slug}": {
   "get": {
    "operationId": "ProductsController_findBySlug",
    "parameters": [
     {
      "name": "slug",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Products"
    ],
    "security": []
   }
  },
  "/products/trending": {
   "get": {
    "operationId": "ProductsController_getTrending",
    "summary": "Newest 4 published products of a channel",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Products"
    ],
    "security": []
   }
  },
  "/products/{id}": {
   "get": {
    "operationId": "ProductsController_findOne",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Products"
    ],
    "security": []
   },
   "patch": {
    "operationId": "ProductsController_update",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateProductDto"
       }
      },
      "multipart/form-data": {
       "schema": {
        "$ref": "#/components/schemas/UpdateProductDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Products"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "ProductsController_remove",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Products"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/products/{id}/images": {
   "post": {
    "operationId": "ProductsController_addImages",
    "summary": "Add up to 10 pictures to a product's gallery (multipart field `images`)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Products"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/products/{id}/images/order": {
   "patch": {
    "operationId": "ProductsController_reorderImages",
    "summary": "Reorder a product's gallery: { order: [imageId, …] }",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Products"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/products/{id}/images/{imageId}": {
   "delete": {
    "operationId": "ProductsController_removeImage",
    "summary": "Remove one picture from a product's gallery",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "imageId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Products"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/profiles": {
   "get": {
    "operationId": "ProfilesController_getAll",
    "summary": "Every profile of the signed-in user, across all channels",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Profiles"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/profiles/data/{ns}": {
   "get": {
    "operationId": "ProfileDataController_getMany",
    "summary": "One namespace for many profiles of this channel (e.g. every player in a room)",
    "description": "profile_ids: comma-separated, at most 100. Signed-in users get the namespaces shared with the channel; the channel's servers (secret key, profile_data:read) get all.",
    "parameters": [
     {
      "name": "ns",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "profile_ids",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Profile data"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/profiles/me/data": {
   "get": {
    "operationId": "ProfileDataController_listMine",
    "summary": "The app data namespaces on your profile in this channel (no documents)",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Profile data"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/profiles/me/data/{ns}": {
   "get": {
    "operationId": "ProfileDataController_getMine",
    "summary": "One app data namespace on your profile in this channel",
    "description": "A namespace that does not exist yet answers version 0 with data null. The ETag header is the version.",
    "parameters": [
     {
      "name": "ns",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Profile data"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "put": {
    "operationId": "ProfileDataController_putMine",
    "summary": "Replace one app data namespace on your profile (conditional write)",
    "description": "Body {\"data\": {…}, \"visibility\"?: \"private\"|\"channel\", \"version\"?: n}. Send the version you replace as If-Match: \"n\" (or body version); 0 / If-None-Match: * creates. 409 on a version conflict, 428 without a version, 413 over 32 KB per namespace or 128 KB per profile.",
    "parameters": [
     {
      "name": "ns",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "if-match",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "if-none-match",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "If-None-Match",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "If-Match",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "required": [
         "data"
        ],
        "properties": {
         "data": {
          "type": "object",
          "additionalProperties": true
         },
         "visibility": {
          "type": "string",
          "enum": [
           "private",
           "channel"
          ]
         },
         "version": {
          "type": "integer",
          "minimum": 0
         }
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Profile data"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "ProfileDataController_deleteMine",
    "summary": "Delete one app data namespace on your profile (If-Match: its version)",
    "parameters": [
     {
      "name": "ns",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "if-match",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "If-Match",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Profile data"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/profiles/{id}": {
   "get": {
    "operationId": "ProfilesController_getOne",
    "summary": "One profile, for its page",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Profiles"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "ProfilesController_update",
    "summary": "Edit an owned per-channel profile's display name",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateProfileDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Profiles"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/profiles/{profileId}/data": {
   "get": {
    "operationId": "ProfileDataController_listOf",
    "summary": "The namespaces of a profile of this channel you may read (no documents)",
    "parameters": [
     {
      "name": "profileId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Profile data"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/profiles/{profileId}/data/{ns}": {
   "get": {
    "operationId": "ProfileDataController_getOf",
    "summary": "One namespace of another profile of this channel (shared ones only)",
    "description": "Signed-in users of the same channel read namespaces with visibility \"channel\"; the channel's servers (secret key, profile_data:read) read all. Never across channels.",
    "parameters": [
     {
      "name": "profileId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "ns",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Profile data"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/public/business/{id}": {
   "get": {
    "operationId": "PublicBusinessController_getPublicProfile",
    "summary": "Public API: Get selected business details only (No token required)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Selected business details returned",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Public APIs"
    ],
    "security": []
   }
  },
  "/public/forms/{formKey}": {
   "get": {
    "operationId": "PublicFormsController_describe",
    "summary": "A browser form's public definition: fields, consent wording and version, success message, the Turnstile site key and CV limits (Public, app key)",
    "parameters": [
     {
      "name": "X-App-Key",
      "in": "header",
      "description": "The channel's publishable app key (kk_app_live_…). Never a server key.",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "formKey",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Forms: browser forms"
    ],
    "security": []
   }
  },
  "/public/forms/{formKey}/cv-upload": {
   "post": {
    "operationId": "PublicFormsController_cvUpload",
    "summary": "Application forms: a 10-minute signed URL to PUT the CV to (PDF or .docx, type and size signed) and the cv_token to send as the file field's value (Public, app key)",
    "parameters": [
     {
      "name": "X-App-Key",
      "in": "header",
      "description": "The channel's publishable app key (kk_app_live_…). Never a server key.",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "formKey",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PublicFormCvUploadDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Forms: browser forms"
    ],
    "security": []
   }
  },
  "/public/forms/{formKey}/submit": {
   "post": {
    "operationId": "PublicFormsController_submit",
    "summary": "Send a browser form straight from the page: Turnstile, origin, honeypot, field schema and consent are checked, then it files a CRM lead or a job application. Same answer whether or not the address is known (Public, app key)",
    "parameters": [
     {
      "name": "X-App-Key",
      "in": "header",
      "description": "The channel's publishable app key (kk_app_live_…). Never a server key.",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "formKey",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/PublicFormSubmitDto"
       }
      }
     }
    },
    "responses": {
     "202": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Forms: browser forms"
    ],
    "security": []
   }
  },
  "/read-marks/{list}": {
   "get": {
    "operationId": "ReadMarksController_state",
    "summary": "When I read each of these records (null = unread)",
    "description": "Pass the ids of the rows on screen. Ids that are not records of this list in the channel are left out.",
    "parameters": [
     {
      "name": "list",
      "required": true,
      "in": "path",
      "description": "crm.contacts (leads), crm.deals, orders",
      "schema": {
       "enum": [
        "crm.contacts",
        "crm.deals",
        "orders"
       ],
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "description": "The channel; the session's channel when left out",
      "schema": {
       "format": "uuid",
       "type": "string"
      }
     },
     {
      "name": "ids",
      "required": true,
      "in": "query",
      "description": "Record ids, comma separated (at most 200)",
      "schema": {
       "pattern": "^[A-Za-z0-9_-]{1,64}$",
       "example": "id1,id2",
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/ReadMarksStateDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Read marks"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/read-marks/{list}/counts": {
   "get": {
    "operationId": "ReadMarksController_counts",
    "summary": "How many records of the list I have and have not read",
    "parameters": [
     {
      "name": "list",
      "required": true,
      "in": "path",
      "description": "crm.contacts (leads), crm.deals, orders",
      "schema": {
       "enum": [
        "crm.contacts",
        "crm.deals",
        "orders"
       ],
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "description": "The channel; the session's channel when left out",
      "schema": {
       "format": "uuid",
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/ReadMarksCountsDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Read marks"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/read-marks/{list}/read": {
   "post": {
    "operationId": "ReadMarksController_read",
    "summary": "Mark records read (opening a record does this)",
    "parameters": [
     {
      "name": "list",
      "required": true,
      "in": "path",
      "description": "crm.contacts (leads), crm.deals, orders",
      "schema": {
       "enum": [
        "crm.contacts",
        "crm.deals",
        "orders"
       ],
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ReadMarksIdsDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/ReadMarksChangeDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Read marks"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/read-marks/{list}/read-all": {
   "post": {
    "operationId": "ReadMarksController_readAll",
    "summary": "Mark every record of the list read",
    "description": "Up to 5000 records per call; `more: true` means call again.",
    "parameters": [
     {
      "name": "list",
      "required": true,
      "in": "path",
      "description": "crm.contacts (leads), crm.deals, orders",
      "schema": {
       "enum": [
        "crm.contacts",
        "crm.deals",
        "orders"
       ],
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ReadMarksChannelDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/ReadMarksChangeDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Read marks"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/read-marks/{list}/unread": {
   "post": {
    "operationId": "ReadMarksController_unread",
    "summary": "Mark records unread again",
    "parameters": [
     {
      "name": "list",
      "required": true,
      "in": "path",
      "description": "crm.contacts (leads), crm.deals, orders",
      "schema": {
       "enum": [
        "crm.contacts",
        "crm.deals",
        "orders"
       ],
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ReadMarksIdsDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "$ref": "#/components/schemas/ReadMarksChangeDto"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Read marks"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/realtime/alive": {
   "post": {
    "operationId": "RealtimeController_alive",
    "summary": "",
    "description": "Client keepalive for a device stream: send it every 25 s while the app is\nin the foreground (with `x-device-id` or `?device_id=`). An open stream\nalone does not make a device \"online\": a suspended app or a dead network\nkeeps the server's socket open (and the server's own pings never count),\nso the device counts as online only while these keep coming: each one\nlasts ALIVE_TTL_MS (40 s, E2EE_ALIVE_TTL_MS), and a call needs one at\nmost CALL_ALIVE_MS (35 s) old. Wake pushes apply as soon as they stop.",
    "parameters": [
     {
      "name": "device_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "device_token",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "204": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/realtime/stream": {
   "get": {
    "operationId": "RealtimeController_stream",
    "summary": "",
    "description": "Server-Sent Events stream of the caller's realtime events.\n\nWritten by hand on the raw response instead of Nest's @Sse(): @Sse cannot\nsend comment heartbeats and stamps an auto-increment `id:` on every\nmessage, which would break Last-Event-ID replay. Auth is the normal\nJwtAuthGuard (access_token cookie for EventSource, or Bearer). The guard,\nincluding the device-fingerprint and session checks, runs on connect\nand again on every reconnect (streams are recycled after maxStreamMs).",
    "parameters": [
     {
      "name": "last_event_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "device_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "device_token",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/records/channels/{channelId}/{app}/{entity}": {
   "get": {
    "operationId": "RecordsController_list",
    "summary": "List records (newest first; q searches every field)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "app",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entity",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "default": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "default": 20,
       "type": "number"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "description": "Search in the title/name",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "description": "Exact status value (e.g. Confirmed)",
      "schema": {
       "maxLength": 60,
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Records"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "RecordsController_create",
    "summary": "Create a record",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "app",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entity",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RecordInputDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Records"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/records/channels/{channelId}/{app}/{entity}/{id}": {
   "get": {
    "operationId": "RecordsController_get",
    "summary": "One record",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "app",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entity",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Records"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "RecordsController_update",
    "summary": "Update a record (merge)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "app",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entity",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RecordInputDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Records"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "RecordsController_remove",
    "summary": "Delete a record",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "app",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "entity",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Records"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/releases": {
   "get": {
    "operationId": "ReleasesController_list",
    "summary": "Published releases, newest first (?platform=&track=&limit=)",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Releases"
    ],
    "security": []
   }
  },
  "/releases/channels/{channelId}": {
   "get": {
    "operationId": "ReleasesController_all",
    "summary": "Every release of the channel, drafts and withdrawn included",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Releases"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "ReleasesController_create",
    "summary": "Add a release { version, platform, arch?, track?, title?, notes?, download_url, size?, sha256?, min_os?, signature?, signature_key_id?, publish? }",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Releases"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/releases/channels/{channelId}/signing": {
   "get": {
    "operationId": "ReleasesController_signing",
    "summary": "Release signing: policy (require_signature, download_hosts) and every key, revoked included",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Releases"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/releases/channels/{channelId}/signing/keys": {
   "post": {
    "operationId": "ReleasesController_addKey",
    "summary": "Register a signing public key { public_key (base64 of 32 bytes, or PEM), name? } (a person, recent sign-in)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Releases"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/releases/channels/{channelId}/signing/keys/{keyId}/revoke": {
   "post": {
    "operationId": "ReleasesController_revokeKey",
    "summary": "Revoke a signing key at once: its signatures stop being served or accepted (a person)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "keyId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Releases"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/releases/channels/{channelId}/signing/policy": {
   "put": {
    "operationId": "ReleasesController_setPolicy",
    "summary": "Release policy { require_signature?, download_hosts? [dl.example.com, *.example.com], no IP addresses } (a person, recent sign-in); answers unsigned_published and off_list_published with examples",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Releases"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/releases/channels/{channelId}/{id}": {
   "patch": {
    "operationId": "ReleasesController_update",
    "summary": "Edit a release (not once withdrawn); a published one takes only title, notes and a new signature",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Releases"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/releases/channels/{channelId}/{id}/publish": {
   "post": {
    "operationId": "ReleasesController_publish",
    "summary": "Publish: updaters and the website see it at once",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Releases"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/releases/channels/{channelId}/{id}/withdraw": {
   "post": {
    "operationId": "ReleasesController_withdraw",
    "summary": "Withdraw a bad release: updaters fall back to the previous one",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Releases"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/releases/latest": {
   "get": {
    "operationId": "ReleasesController_latest",
    "summary": "Latest published release: ?platform=mac|windows|linux|android|ios|web&arch=&track=stable|beta|nightly",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Releases"
    ],
    "security": []
   }
  },
  "/releases/sign.mjs": {
   "get": {
    "operationId": "ReleasesController_signTool",
    "summary": "The offline signing tool (node kodkila-release-sign.mjs keygen | sign | verify)",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Releases"
    ],
    "security": []
   }
  },
  "/releases/signing-keys": {
   "get": {
    "operationId": "ReleasesController_signingKeys",
    "summary": "The channel's active release signing keys (Ed25519) and whether signatures are required. Updaters should pin keys, not fetch them.",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Releases"
    ],
    "security": []
   }
  },
  "/reminders": {
   "get": {
    "operationId": "RemindersController_list",
    "summary": "List the signed-in user's reminders (tab/search)",
    "parameters": [
     {
      "name": "tab",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "upcoming",
        "overdue",
        "done",
        "all"
       ],
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 200,
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Reminders"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "RemindersController_create",
    "summary": "Add a reminder",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateReminderDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Reminders"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/reminders/summary": {
   "get": {
    "operationId": "RemindersController_summary",
    "summary": "Counts for the Upcoming/Overdue/Done tabs",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Reminders"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/reminders/{id}": {
   "get": {
    "operationId": "RemindersController_getOne",
    "summary": "Get a single reminder",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Reminders"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "RemindersController_update",
    "summary": "Edit a reminder / mark it done / un-mark it",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateReminderDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Reminders"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "RemindersController_remove",
    "summary": "Delete a reminder (returns the deleted reminder)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Reminders"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/reminders/{id}/snooze": {
   "post": {
    "operationId": "RemindersController_snooze",
    "summary": "Snooze a reminder to a later time",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/SnoozeReminderDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Reminders"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/reports": {
   "post": {
    "operationId": "ReportsController_submitReport",
    "summary": "Submit a new report",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateReportDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Reports"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/reports/my": {
   "get": {
    "operationId": "ReportsController_getMyReports",
    "summary": "Get all reports submitted by the active profile",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Reports"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/reports/reasons": {
   "get": {
    "operationId": "ReportsController_getReasons",
    "summary": "Get all reporting reasons",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Reports"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/reports/{id}": {
   "patch": {
    "operationId": "ReportsController_updateReportStatus",
    "summary": "Update report status (Admin/Moderator)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-admin-key",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateReportDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Reports"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/safety/announcements/{id}/end": {
   "post": {
    "operationId": "SafetyController_endAnnouncement",
    "summary": "Take a banner down",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trust & safety"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/safety/cases/{id}/appeal": {
   "post": {
    "operationId": "SafetyController_appeal",
    "summary": "Appeal a decision (once)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/AppealDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trust & safety"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/safety/cases/{id}/appeal-decision": {
   "post": {
    "operationId": "SafetyController_appealDecision",
    "summary": "Uphold or reverse an appealed decision",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/AppealDecisionDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trust & safety"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/safety/cases/{id}/decision": {
   "post": {
    "operationId": "SafetyController_decide",
    "summary": "Warn, suspend or dismiss an open case",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/DecisionDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trust & safety"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/safety/cases/{id}/escalate": {
   "post": {
    "operationId": "SafetyController_escalate",
    "summary": "Hand an open case to the channel above",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trust & safety"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/safety/cases/{id}/lift": {
   "post": {
    "operationId": "SafetyController_lift",
    "summary": "Lift a suspension or withdraw a warning",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ReasonDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trust & safety"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/safety/channels/{channelId}/announcements": {
   "get": {
    "operationId": "SafetyController_announcements",
    "summary": "The channel's announcements",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trust & safety"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "SafetyController_announce",
    "summary": "Show a banner (optionally on every channel below too)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/AnnouncementDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trust & safety"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/safety/channels/{channelId}/announcements/live": {
   "get": {
    "operationId": "SafetyController_live",
    "summary": "Banners for the channel's people (its own and cascading ones from above)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trust & safety"
    ],
    "security": []
   }
  },
  "/safety/channels/{channelId}/api-keys/pause": {
   "post": {
    "operationId": "SafetyController_pauseKeys",
    "summary": "Pause or resume every API key of this channel or one below it",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/KeysPauseDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trust & safety"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/safety/channels/{channelId}/cases": {
   "get": {
    "operationId": "SafetyController_cases",
    "summary": "The channel's cases (default: open and appealed)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "open",
        "actioned",
        "dismissed",
        "appealed",
        "closed"
       ],
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trust & safety"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "SafetyController_direct",
    "summary": "Warn or suspend something below the channel directly",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/DirectActionDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trust & safety"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/safety/channels/{channelId}/legal-requests": {
   "get": {
    "operationId": "SafetyController_legalList",
    "summary": "Legal and data requests (default: open), by due date",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "open",
        "in_progress",
        "completed",
        "refused"
       ],
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trust & safety"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "SafetyController_legalRecord",
    "summary": "Record a request that arrived another way",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/LegalRequestDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trust & safety"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/safety/channels/{channelId}/legal-requests/public": {
   "post": {
    "operationId": "SafetyController_legalPublic",
    "summary": "Send a legal or data request to a channel (anyone; returns a reference)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/LegalRequestDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trust & safety"
    ],
    "security": []
   }
  },
  "/safety/legal-requests/{id}": {
   "patch": {
    "operationId": "SafetyController_legalUpdate",
    "summary": "Move a request along and record the answer",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/LegalUpdateDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trust & safety"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/safety/notices": {
   "get": {
    "operationId": "SafetyController_notices",
    "summary": "Decisions about me, or a business or channel I own (?type=&id=)",
    "parameters": [
     {
      "name": "type",
      "required": true,
      "in": "query",
      "schema": {
       "enum": [
        "account",
        "profile",
        "business",
        "channel"
       ],
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trust & safety"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/safety/reports": {
   "post": {
    "operationId": "SafetyController_report",
    "summary": "Report an account, business or channel",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ReportDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trust & safety"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/search": {
   "get": {
    "operationId": "SearchController_search",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "security": []
   },
   "post": {
    "operationId": "SearchController_saveSearch",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateSearchDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/search/channels/{channelId}/alerts": {
   "get": {
    "operationId": "SearchManageController_alerts",
    "summary": "Latency and refusal alerts for the channel's search (?days=, at most 90)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "days",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/search/channels/{channelId}/indexes": {
   "get": {
    "operationId": "SearchManageController_indexes",
    "summary": "Platform content indexed for the channel and the channel's own indexes, with document counts",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/search/channels/{channelId}/overview": {
   "get": {
    "operationId": "SearchManageController_overview",
    "summary": "Search status, quotas, storage and this month's usage (channel managers)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/search/channels/{channelId}/quota": {
   "put": {
    "operationId": "SearchManageController_setQuota",
    "summary": "Set a channel's search quotas (platform only)",
    "description": "storage_gb, docs, indices, qps, suggest_qps, concurrent, bulk_mb_per_min, bulk_actions_per_sec, slow_ms, enabled, note. null returns a value to the platform default.",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/search/channels/{channelId}/slow-log": {
   "get": {
    "operationId": "SearchManageController_slowLog",
    "summary": "The channel's slowest recent search requests, newest first (?limit=, at most 200; what was searched for is not kept)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/search/channels/{channelId}/synonyms": {
   "get": {
    "operationId": "SearchManageController_synonyms",
    "summary": "The channel's synonym rules",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "SearchManageController_create",
    "summary": "Add a rule: { kind: equivalent, terms } or { kind: oneway, inputs, terms }",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/search/channels/{channelId}/synonyms/preview": {
   "get": {
    "operationId": "SearchManageController_preview",
    "summary": "What the channel's synonym rules turn a query into (?q=)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/search/channels/{channelId}/synonyms/{id}": {
   "patch": {
    "operationId": "SearchManageController_update",
    "summary": "Change a rule (the same body as adding one, plus enabled)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "SearchManageController_remove",
    "summary": "Delete a rule",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/search/channels/{channelId}/usage": {
   "get": {
    "operationId": "SearchManageController_usage",
    "summary": "Daily searches, suggests, writes, bulk bytes, refusals, slow requests and p50/p95 latency (?days=, at most 90)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "days",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/search/history": {
   "get": {
    "operationId": "SearchController_getSearchHistory",
    "parameters": [
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 50,
       "type": "number"
      }
     },
     {
      "name": "active_profile_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "scope",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   },
   "delete": {
    "operationId": "SearchController_deleteSearchHistory",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/DeleteSearchHistoryDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/search/keywords/{id}": {
   "patch": {
    "operationId": "SearchController_setKeywordStatus",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/search/suggestions": {
   "get": {
    "operationId": "SearchController_getSuggestions",
    "parameters": [
     {
      "name": "q",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "security": []
   }
  },
  "/search/trending": {
   "get": {
    "operationId": "SearchController_getTrending",
    "parameters": [
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 50,
       "type": "number"
      }
     },
     {
      "name": "active_profile_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "scope",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "security": []
   }
  },
  "/search/v1/bulk": {
   "post": {
    "operationId": "SearchApiController_bulk",
    "summary": "Bulk ingest: OpenSearch NDJSON (application/x-ndjson) with logical _index names",
    "description": "index, create, update (doc, doc_as_upsert; no scripts) and delete. Up to 8 MB and 2000 actions. Answer: OpenSearch's bulk response.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/search/v1/health": {
   "get": {
    "operationId": "SearchApiController_health",
    "summary": "The search engine as this channel sees it: { status: green | yellow | red }",
    "description": "At most 10 calls a second per channel (then 429); the status is at most 2 seconds old.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": []
   }
  },
  "/search/v1/indices": {
   "get": {
    "operationId": "SearchApiController_list",
    "summary": "The channel's own indexes with document counts and sizes",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": []
   }
  },
  "/search/v1/indices/{name}": {
   "get": {
    "operationId": "SearchApiController_get",
    "summary": "One index: { name, exists, docs, size_bytes, schema_version, migration? }",
    "parameters": [
     {
      "name": "name",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": []
   },
   "put": {
    "operationId": "SearchApiController_put",
    "summary": "Create or change an index from { schema_version, settings, mappings, sizing, access? }",
    "description": "Same schema_version: additive (new fields only). Higher: a new generation is built and reindexed in the background, then swapped in atomically (progress in `migration`). Shards and replicas are the platform's choice from `sizing`.",
    "parameters": [
     {
      "name": "name",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "SearchApiController_remove",
    "summary": "Delete an index (unreachable at once, kept 7 days, then dropped)",
    "parameters": [
     {
      "name": "name",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/search/v1/indices/{name}/count": {
   "post": {
    "operationId": "SearchApiController_count",
    "summary": "Count documents matching { query? }",
    "parameters": [
     {
      "name": "name",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": []
   }
  },
  "/search/v1/indices/{name}/delete_by_query": {
   "post": {
    "operationId": "SearchApiController_deleteByQuery",
    "summary": "Delete documents matching filter clauses (term, terms, range, ids, exists, bool); big deletes answer { task }",
    "parameters": [
     {
      "name": "name",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/search/v1/indices/{name}/mget": {
   "post": {
    "operationId": "SearchApiController_mget",
    "summary": "Documents by id: { ids: [...] } (at most 1000)",
    "parameters": [
     {
      "name": "name",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": []
   }
  },
  "/search/v1/indices/{name}/refresh": {
   "post": {
    "operationId": "SearchApiController_refresh",
    "summary": "Make recent writes searchable now (at most once a second)",
    "parameters": [
     {
      "name": "name",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/search/v1/indices/{name}/search": {
   "post": {
    "operationId": "SearchApiController_search",
    "summary": "Search with a checked subset of the OpenSearch query DSL; answer: OpenSearch's search response",
    "description": "No scripts, regexp, leading wildcards or query_string; from+size ≤ max_result_window, search_after for deep paging; aggregations bounded. See docs/search.md.",
    "parameters": [
     {
      "name": "name",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": []
   }
  },
  "/search/v1/indices/{name}/suggest": {
   "post": {
    "operationId": "SearchApiController_suggest",
    "summary": "Completion suggester: { suggest: { s: { prefix, completion: { field, size ≤ 20 } } } }",
    "parameters": [
     {
      "name": "name",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": []
   }
  },
  "/search/v1/slowlog": {
   "get": {
    "operationId": "SearchApiController_slowlog",
    "summary": "This channel's slowest recent requests (?limit=, at most 200), newest first",
    "description": "Requests at or above the channel's slow threshold (quotas.slowMs). The query is kept with what was searched for taken out: field and clause names stay, typed values become \"?\".",
    "parameters": [
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/search/v1/tasks/{id}": {
   "get": {
    "operationId": "SearchApiController_task",
    "summary": "Progress of a big delete_by_query",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/search/v1/usage": {
   "get": {
    "operationId": "SearchApiController_usage",
    "summary": "This channel's search storage, documents, requests this month, latency (last 24 hours), alerts and quotas",
    "description": "latency.search and latency.suggest give count, p50_ms, p95_ms and p99_ms of end-to-end time through the API; alerts lists the last 7 days.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Search"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/server": {
   "get": {
    "operationId": "ServerController_getServerInfo",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "security": []
   }
  },
  "/server/visitor": {
   "post": {
    "operationId": "ServerController_trackVisit",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/TrackVisitDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "security": []
   }
  },
  "/social/channels/{channelId}/groups": {
   "get": {
    "operationId": "SocialModerationController_groups",
    "summary": "The channel's community groups",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 120,
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Social moderation"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/social/channels/{channelId}/groups/{id}/hide": {
   "post": {
    "operationId": "SocialModerationController_hideGroup",
    "summary": "Hide a group from the channel (reversible)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ModerationReasonDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Social moderation"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/social/channels/{channelId}/groups/{id}/restore": {
   "post": {
    "operationId": "SocialModerationController_restoreGroup",
    "summary": "Show a hidden group again",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Social moderation"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/social/channels/{channelId}/overview": {
   "get": {
    "operationId": "SocialModerationController_overview",
    "summary": "Counts: posts, hidden posts, stories, profiles, open reports",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Social moderation"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/social/channels/{channelId}/posts": {
   "get": {
    "operationId": "SocialModerationController_posts",
    "summary": "The channel's posts, newest first",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     },
     {
      "name": "state",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "visible",
        "hidden",
        "all"
       ],
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 120,
       "type": "string"
      }
     },
     {
      "name": "type",
      "required": false,
      "in": "query",
      "description": "Only this post type, e.g. listing",
      "schema": {
       "maxLength": 40,
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Social moderation"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/social/channels/{channelId}/posts/{id}/hide": {
   "post": {
    "operationId": "SocialModerationController_hidePost",
    "summary": "Hide a post from every feed (reversible)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ModerationReasonDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Social moderation"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/social/channels/{channelId}/posts/{id}/restore": {
   "post": {
    "operationId": "SocialModerationController_restorePost",
    "summary": "Show a hidden post again",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ModerationReasonDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Social moderation"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/social/channels/{channelId}/profiles": {
   "get": {
    "operationId": "SocialModerationController_profiles",
    "summary": "Profiles on the channel; suspend through Trust & safety",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 120,
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Social moderation"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/social/channels/{channelId}/reports": {
   "get": {
    "operationId": "SocialModerationController_reports",
    "summary": "Reports people made on the channel",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     },
     {
      "name": "state",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "open",
        "closed"
       ],
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Social moderation"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/social/channels/{channelId}/reports/{id}/resolve": {
   "post": {
    "operationId": "SocialModerationController_resolveReport",
    "summary": "Close a report as resolved or dismissed",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ResolveReportDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Social moderation"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/social/channels/{channelId}/stories": {
   "get": {
    "operationId": "SocialModerationController_stories",
    "summary": "The channel's live stories",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Social moderation"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/social/channels/{channelId}/stories/{id}/remove": {
   "post": {
    "operationId": "SocialModerationController_removeStory",
    "summary": "Take a story down",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ModerationReasonDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Social moderation"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/stories": {
   "post": {
    "operationId": "StoriesController_createStory",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateStoryDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   },
   "get": {
    "operationId": "StoriesController_getFeed",
    "parameters": [
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "active_profile_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "latitude",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "longitude",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "security": []
   }
  },
  "/stories/comment/{commentId}": {
   "delete": {
    "operationId": "StoriesController_deleteComment",
    "parameters": [
     {
      "name": "commentId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/stories/my": {
   "get": {
    "operationId": "StoriesController_getMyStories",
    "parameters": [
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "active_profile_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "latitude",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "longitude",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/stories/{id}": {
   "delete": {
    "operationId": "StoriesController_deleteStory",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/stories/{id}/comments": {
   "post": {
    "operationId": "StoriesController_addComment",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateStoryCommentDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   },
   "get": {
    "operationId": "StoriesController_getComments",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "security": []
   }
  },
  "/stories/{id}/like": {
   "post": {
    "operationId": "StoriesController_toggleLike",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/stories/{id}/share": {
   "post": {
    "operationId": "StoriesController_toggleShare",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/stories/{id}/view": {
   "post": {
    "operationId": "StoriesController_recordView",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/subscription-plans": {
   "post": {
    "operationId": "SubscriptionPlansController_create",
    "summary": "",
    "description": "Create a plan (title + price required; owner from JWT).",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreatePlanDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   },
   "get": {
    "operationId": "SubscriptionPlansController_list",
    "summary": "",
    "description": "The caller's own plans (optional ?status=, paginated).",
    "parameters": [
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "published",
        "draft",
        "archived"
       ],
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/subscription-plans/creator/{profileId}": {
   "get": {
    "operationId": "SubscriptionPlansController_listByCreator",
    "summary": "",
    "description": "PUBLIC: a creator's AVAILABLE plans (for fans). profileId = user_profile UUID.",
    "parameters": [
     {
      "name": "profileId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/subscription-plans/{id}": {
   "get": {
    "operationId": "SubscriptionPlansController_getOne",
    "summary": "",
    "description": "A single plan (owner-scoped). id = INTEGER.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   },
   "patch": {
    "operationId": "SubscriptionPlansController_update",
    "summary": "",
    "description": "Update any subset of fields (status:false = hide). Owner only. id = INTEGER.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdatePlanDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   },
   "put": {
    "operationId": "SubscriptionPlansController_replace",
    "summary": "",
    "description": "PUT alias for update. id = INTEGER.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdatePlanDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   },
   "delete": {
    "operationId": "SubscriptionPlansController_remove",
    "summary": "",
    "description": "Hard-delete a plan (owner only). id = INTEGER.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/subscriptions": {
   "post": {
    "operationId": "SubscriptionsController_subscribe",
    "summary": "",
    "description": "Subscribe (creates the single row OR reactivates/reuses it). A paid plan\n needs `payment_id` of the caller's successful, unused payment for the\n plan price (402 otherwise; 409 when already used).",
    "parameters": [
     {
      "name": "Idempotency-Key",
      "in": "header",
      "description": "Optional client-generated key (8-128 chars, [A-Za-z0-9_-]). A retry with the same key and body replays the first response (Idempotent-Replayed: true); 409 while the first is in flight; 422 if the body differs.",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/SubscribeDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/subscriptions/check": {
   "get": {
    "operationId": "SubscriptionsController_check",
    "summary": "",
    "description": "Am I subscribed to a creator? ?creator_user_id=<uuid>.",
    "parameters": [
     {
      "name": "creator_user_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/subscriptions/me": {
   "get": {
    "operationId": "SubscriptionsController_me",
    "summary": "",
    "description": "The caller's single subscription (+ plan), or null.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/subscriptions/subscribers": {
   "get": {
    "operationId": "SubscriptionsController_subscribers",
    "summary": "",
    "description": "My subscribers (as a creator).",
    "parameters": [
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/subscriptions/{id}": {
   "get": {
    "operationId": "SubscriptionsController_getOne",
    "summary": "",
    "description": "One subscription (subscriber or creator).",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/subscriptions/{id}/cancel": {
   "patch": {
    "operationId": "SubscriptionsController_cancel",
    "summary": "",
    "description": "Cancel (Option A): immediate status → archived; access remains until period_end.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/subscriptions/{id}/change-plan": {
   "patch": {
    "operationId": "SubscriptionsController_changePlan",
    "summary": "",
    "description": "Change plan (upgrade or downgrade). Mutates plan_id on the SAME row. When\n the proration amount is > 0 it needs `payment_id` for exactly that amount.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "Idempotency-Key",
      "in": "header",
      "description": "Optional client-generated key (8-128 chars, [A-Za-z0-9_-]). A retry with the same key and body replays the first response (Idempotent-Replayed: true); 409 while the first is in flight; 422 if the body differs.",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ChangePlanDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/subscriptions/{id}/change-plan-preview": {
   "get": {
    "operationId": "SubscriptionsController_preview",
    "summary": "",
    "description": "Proration preview for a plan change (read-only; matches change-plan).",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "new_plan_id",
      "required": true,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/subscriptions/{id}/history": {
   "get": {
    "operationId": "SubscriptionsController_history",
    "summary": "",
    "description": "The subscription's event timeline.",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    }
   }
  },
  "/support/channels/{channelId}/tickets": {
   "get": {
    "operationId": "SupportStaffController_list",
    "summary": "List the channel's tickets (?status=&priority=&assigned_to=me|none|<id>)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 10000,
       "default": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 50,
       "default": 20,
       "type": "number"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "open",
        "pending",
        "resolved",
        "closed"
       ],
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "description": "Customer: only this channel",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "priority",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "low",
        "normal",
        "high",
        "urgent"
       ],
       "type": "string"
      }
     },
     {
      "name": "assigned_to",
      "required": false,
      "in": "query",
      "description": "Assignee user id, or 'me' / 'none'",
      "schema": {
       "maxLength": 36,
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Support"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/support/channels/{channelId}/tickets/{id}": {
   "get": {
    "operationId": "SupportStaffController_get",
    "summary": "Get a ticket with the full thread (incl. notes)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Support"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "SupportStaffController_update",
    "summary": "Change status / priority / assignee",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/StaffUpdateTicketDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Support"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/support/channels/{channelId}/tickets/{id}/messages": {
   "post": {
    "operationId": "SupportStaffController_reply",
    "summary": "Reply (or add an internal note) as staff",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/StaffReplyDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Support"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/support/tickets": {
   "post": {
    "operationId": "SupportController_create",
    "summary": "Open a ticket with a channel",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateTicketDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Support"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "SupportController_list",
    "summary": "List my tickets (?channel_id=&status=&page=&limit≤50)",
    "parameters": [
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 10000,
       "default": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 50,
       "default": 20,
       "type": "number"
      }
     },
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "open",
        "pending",
        "resolved",
        "closed"
       ],
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "description": "Customer: only this channel",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Support"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/support/tickets/{id}": {
   "get": {
    "operationId": "SupportController_get",
    "summary": "Get one of my tickets with its thread",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Support"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/support/tickets/{id}/close": {
   "post": {
    "operationId": "SupportController_close",
    "summary": "Close my ticket",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Support"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/support/tickets/{id}/messages": {
   "post": {
    "operationId": "SupportController_reply",
    "summary": "Reply on my ticket (reopens pending/resolved)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ReplyDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Support"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/support/tickets/{id}/reopen": {
   "post": {
    "operationId": "SupportController_reopen",
    "summary": "Reopen my resolved/closed ticket",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Support"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/tasks": {
   "get": {
    "operationId": "TasksController_list",
    "summary": "List the signed-in user's tasks (filter/search)",
    "parameters": [
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "open",
        "done",
        "all"
       ],
       "type": "string"
      }
     },
     {
      "name": "due",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "overdue",
        "today",
        "upcoming",
        "none"
       ],
       "type": "string"
      }
     },
     {
      "name": "q",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 200,
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "sort",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "due_date",
        "created_at",
        "priority"
       ],
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Tasks"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "TasksController_create",
    "summary": "Create a task",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateTaskDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Tasks"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/tasks/summary": {
   "get": {
    "operationId": "TasksController_summary",
    "summary": "Task counts for the tiles and sidebar badge",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Tasks"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/tasks/{id}": {
   "get": {
    "operationId": "TasksController_getOne",
    "summary": "Get a single task",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Tasks"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "TasksController_update",
    "summary": "Edit a task / tick it off / un-tick it",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateTaskDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Tasks"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "TasksController_remove",
    "summary": "Delete a task (returns the deleted task for Undo)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Tasks"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/trademarks": {
   "post": {
    "operationId": "TrademarksController_createTrademark",
    "summary": "Create A Trademark",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateTrademarkDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Trademark created successfully",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trademarks"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/trademarks/business/{businessId}": {
   "get": {
    "operationId": "TrademarksController_fetchMyTrademarks",
    "summary": "Fetch All Trademarks for a specific business",
    "parameters": [
     {
      "name": "businessId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "List of trademarks returned",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trademarks"
    ],
    "security": []
   }
  },
  "/trademarks/update/{id}": {
   "post": {
    "operationId": "TrademarksController_updateTrademark",
    "summary": "Update A Trademark",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateTrademarkDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Trademark updated successfully",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trademarks"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/trademarks/{id}": {
   "delete": {
    "operationId": "TrademarksController_deleteTrademark",
    "summary": "Delete A Trademark (business owner only)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Trademark deleted",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trademarks"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "TrademarksController_fetchSingleTrademark",
    "summary": "Fetch Single Trademark",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Trademark details returned",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Trademarks"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/updates/assets/{channelId}/{hash}": {
   "get": {
    "operationId": "AppUpdatesController_asset",
    "summary": "One update asset: a redirect to a short-lived signed link",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hash",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "App updates"
    ],
    "security": []
   }
  },
  "/updates/channels/{channelId}": {
   "get": {
    "operationId": "AppUpdatesController_list",
    "summary": "The channel's updates with devices per update and this month's device count (?platform=&branch=&runtime_version=)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "App updates"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "AppUpdatesController_publish",
    "summary": "Publish an update { platform, runtime_version, branch?, message?, launch_asset, assets[], extra?, rollout_percent? }",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "App updates"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/updates/channels/{channelId}/certificate": {
   "get": {
    "operationId": "AppUpdatesController_certificate",
    "summary": "The code-signing certificate the app embeds (updates.codeSigningCertificate)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "App updates"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/updates/channels/{channelId}/embedded": {
   "post": {
    "operationId": "AppUpdatesController_embedded",
    "summary": "Send apps back to their store build: { platform, runtime_version, branch? }",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "App updates"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/updates/channels/{channelId}/uploads": {
   "post": {
    "operationId": "AppUpdatesController_uploads",
    "summary": "Which files are missing: { files: [{ hash, size, contentType }] } → presigned PUTs",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "App updates"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/updates/channels/{channelId}/{id}": {
   "patch": {
    "operationId": "AppUpdatesController_rollout",
    "summary": "Change the rollout: { rollout_percent } (0 pauses it)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "App updates"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/updates/channels/{channelId}/{id}/republish": {
   "post": {
    "operationId": "AppUpdatesController_republish",
    "summary": "Roll back: publish this older update again as the newest",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "App updates"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/updates/cli.mjs": {
   "get": {
    "operationId": "AppUpdatesController_cli",
    "summary": "The publish CLI (node kodkila-updates.mjs publish …)",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "App updates"
    ],
    "security": []
   }
  },
  "/updates/{channelId}/manifest": {
   "get": {
    "operationId": "AppUpdatesController_manifest",
    "summary": "Expo Updates protocol v1: the signed manifest or directive for this app (headers expo-platform, expo-runtime-version, expo-channel-name…)",
    "parameters": [
     {
      "name": "channelId",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "App updates"
    ],
    "security": []
   }
  },
  "/user": {
   "get": {
    "operationId": "UsersController_findAll",
    "summary": "Get channel user profiles (tenant-scoped, paginated)",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/user/categories": {
   "get": {
    "operationId": "UsersController_getUserCategories",
    "summary": "Get list of User Categories",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": []
   }
  },
  "/user/category": {
   "get": {
    "operationId": "UsersController_getUserCategories_2",
    "summary": "Get list of User Categories",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": []
   }
  },
  "/user/check-username/{username}": {
   "get": {
    "operationId": "UsersController_checkUsername",
    "summary": "Check if a username is available in the channel (x-ref, else the session's); same answer as GET /usernames/availability",
    "parameters": [
     {
      "name": "username",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": []
   }
  },
  "/user/kyc": {
   "post": {
    "operationId": "UsersController_createKyc",
    "summary": "Create User KYC",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateKycDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/user/profile": {
   "delete": {
    "operationId": "UsersController_deleteProfile",
    "summary": "Delete user profile and account (moves to trash)",
    "parameters": [
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/user/profile/blocked": {
   "get": {
    "operationId": "UsersController_getBlockedProfiles",
    "summary": "Get all blocked profiles for the active profile",
    "parameters": [
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/user/profile/create": {
   "post": {
    "operationId": "UsersController_createProfile",
    "summary": "Create a new user profile",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateProfileDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/user/profile/{id}": {
   "post": {
    "operationId": "UsersController_checkUsernameWithId",
    "summary": "Check if a username is available for a specific profile ID",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CheckUsernameDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": []
   }
  },
  "/user/profiledetail": {
   "post": {
    "operationId": "UsersController_upsertProfileDetail",
    "summary": "Add or Update User Profile Detail (Upsert)",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpsertProfileDetailDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/user/profileprivacy": {
   "post": {
    "operationId": "UsersController_upsertProfilePrivacy",
    "summary": "Add or update user profile privacy settings",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpsertProfilePrivacyDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/user/profiles": {
   "get": {
    "operationId": "UsersController_findMyProfiles",
    "summary": "Get profiles belonging to the currently logged-in user",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/user/{id}": {
   "get": {
    "operationId": "UsersController_findOne",
    "summary": "Get a specific user profile by ID",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": []
   },
   "patch": {
    "operationId": "UsersController_update",
    "summary": "Update a specific user profile by ID",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateUserDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/user/{id}/block": {
   "post": {
    "operationId": "UsersController_blockProfile",
    "summary": "Block a user profile",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/user/{id}/donations": {
   "get": {
    "operationId": "UsersController_getProfileDonations",
    "summary": "Get a profile's public donations (paged, with total)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": []
   }
  },
  "/user/{id}/follow": {
   "post": {
    "operationId": "UsersController_followProfile",
    "summary": "Follow a user profile",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/user/{id}/followers": {
   "get": {
    "operationId": "UsersController_getFollowers",
    "summary": "Get list of followers for a profile",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "ids_only",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": []
   }
  },
  "/user/{id}/following": {
   "get": {
    "operationId": "UsersController_getFollowing",
    "summary": "Get list of profiles this profile is following",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "ids_only",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": []
   }
  },
  "/user/{id}/unblock": {
   "post": {
    "operationId": "UsersController_unblockProfile",
    "summary": "Unblock a user profile",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/user/{id}/unfollow": {
   "post": {
    "operationId": "UsersController_unfollowProfile",
    "summary": "Unfollow a user profile",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/useraddress": {
   "post": {
    "operationId": "MyAddressController_createAddress",
    "summary": "Create My Address",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateMyAddressDto"
       }
      },
      "multipart/form-data": {
       "schema": {
        "$ref": "#/components/schemas/CreateMyAddressDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Personal address created",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "User Address"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "get": {
    "operationId": "MyAddressController_fetchAllAddresses",
    "summary": "Fetch All My Addresses",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "User Address"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/useraddress/delete/{id}": {
   "post": {
    "operationId": "MyAddressController_deleteAddress",
    "summary": "Delete My Address",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "User Address"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/useraddress/update/{id}": {
   "post": {
    "operationId": "MyAddressController_updateAddress",
    "summary": "Update My Address",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateMyAddressDto"
       }
      },
      "multipart/form-data": {
       "schema": {
        "$ref": "#/components/schemas/UpdateMyAddressDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "User Address"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/useraddress/{id}": {
   "get": {
    "operationId": "MyAddressController_fetchAddress",
    "summary": "Fetch One Of My Addresses",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "User Address"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/usernames/availability": {
   "get": {
    "operationId": "UsernamesController_availability",
    "summary": "Public: can this username be taken in the channel? { available, code?, rule?, message }",
    "description": "code: INVALID_USERNAME (with rule), USERNAME_RESERVED, USERNAME_TAKEN (also a name held after a rename) or USERNAME_TOO_SIMILAR (looks like a taken name). When a name is not available, suggestions lists up to three free plain names near it (never with a .NN ending). Signed in, your own held names count as available to you. 30 per minute and 300 per day per network.",
    "parameters": [
     {
      "name": "username",
      "required": true,
      "in": "query",
      "description": "The name to check (trimmed and lowercased first)",
      "schema": {
       "maxLength": 64,
       "type": "string"
      }
     },
     {
      "name": "shape",
      "required": false,
      "in": "query",
      "description": "plain (asha.rao) or opaque (for auth.opaque sign-ups: asha, or the older asha.07). Default: opaque when the name ends in a dot and two digits",
      "schema": {
       "enum": [
        "plain",
        "opaque"
       ],
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "in": "header",
      "description": "Channel id, when no app key is sent",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Usernames"
    ],
    "security": []
   }
  },
  "/usernames/me": {
   "get": {
    "operationId": "UsernamesController_me",
    "summary": "My username: whether I can change it now, when next, my held old names, the rules",
    "description": "rename_prompt is set when one rename without the cooldown is open: reason suffix_taken (the .NN migration could not drop the ending) or digits_not_allowed (the channel turned digits off and the current name has some). The new name must follow the channel's rules.",
    "parameters": [
     {
      "name": "profile_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Usernames"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/usernames/me/drop-suffix": {
   "post": {
    "operationId": "UsernamesController_dropSuffix",
    "summary": "Drop the old .NN ending from my username when the plain name is free (apps of auth.opaque channels call this once)",
    "description": "Send your current username. If it ends in a dot and two digits and the name without them is free for you, it becomes your username (for 30 days the old one still works for sign-in, mentions and the relay directory lookup) and outcome is renamed. If the plain name is taken, outcome is collision and GET /usernames/me shows rename_prompt with one free rename. outcome kept: there was no ending (recorded, so suffix_check stops asking). Errors: 400 USERNAME_MISMATCH (not your current username).",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/DropSuffixDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Usernames"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/usernames/policy": {
   "get": {
    "operationId": "UsernamesController_policy",
    "summary": "Public: the channel's username rules (length, characters, rename cooldown, hold period)",
    "parameters": [
     {
      "name": "x-ref",
      "in": "header",
      "description": "Channel id, when no app key is sent",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Usernames"
    ],
    "security": []
   }
  },
  "/usernames/rename": {
   "post": {
    "operationId": "UsernamesController_rename",
    "summary": "Change my username (policy, look-alikes, cooldown); the old name is held for me for the channel's hold period",
    "description": "Errors: 400 INVALID_USERNAME (with rule, e.g. no_digits) / USERNAME_RESERVED / USERNAME_UNCHANGED, 409 USERNAME_TAKEN / USERNAME_TOO_SIMILAR, 429 USERNAME_COOLDOWN (next_change_at, retry_after). An auth.opaque account keeps signing in with its password under the new name.",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RenameUsernameDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Usernames"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users": {
   "get": {
    "operationId": "UsersController_findAll_2",
    "summary": "Get channel user profiles (tenant-scoped, paginated)",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users/categories": {
   "get": {
    "operationId": "UsersController_getUserCategories_3",
    "summary": "Get list of User Categories",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": []
   }
  },
  "/users/category": {
   "get": {
    "operationId": "UsersController_getUserCategories_4",
    "summary": "Get list of User Categories",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "array",
             "items": {
              "type": "object"
             }
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": []
   }
  },
  "/users/check-username/{username}": {
   "get": {
    "operationId": "UsersController_checkUsername_2",
    "summary": "Check if a username is available in the channel (x-ref, else the session's); same answer as GET /usernames/availability",
    "parameters": [
     {
      "name": "username",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": []
   }
  },
  "/users/kyc": {
   "post": {
    "operationId": "UsersController_createKyc_2",
    "summary": "Create User KYC",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateKycDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users/me/consent": {
   "get": {
    "operationId": "ConsentController_get",
    "summary": "My current consent per kind (terms, privacy, marketing), the versions in force and what still needs accepting",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Account"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "ConsentController_record",
    "summary": "Record consent decisions (sign-up checkboxes, the marketing switch). Only changes are written.",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RecordConsentDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Account"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users/me/consent/history": {
   "get": {
    "operationId": "ConsentController_history",
    "summary": "Every consent decision on my account, newest first (paged, max 100)",
    "parameters": [
     {
      "name": "kind",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "terms",
        "privacy",
        "marketing"
       ],
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 1000,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "maximum": 100,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Account"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users/me/data-requests": {
   "get": {
    "operationId": "AccountController_listDataRequests",
    "summary": "My UK GDPR data requests (paged, max 50)",
    "parameters": [
     {
      "name": "status",
      "required": false,
      "in": "query",
      "schema": {
       "enum": [
        "pending",
        "in_progress",
        "completed",
        "rejected",
        "cancelled"
       ],
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Account"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "AccountController_createDataRequest",
    "summary": "Request a copy of my data (export), erasure (delete) or a correction (rectify)",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateDataRequestDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Account"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users/me/data-requests/{id}": {
   "get": {
    "operationId": "AccountController_getDataRequest",
    "summary": "One of my data requests",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Account"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users/me/data-requests/{id}/cancel": {
   "post": {
    "operationId": "AccountController_cancelDataRequest",
    "summary": "Cancel a pending data request",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Account"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users/me/preferences": {
   "get": {
    "operationId": "AccountController_getPreferences",
    "summary": "Language, timezone, UI switches, security alerts and recovery email",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Account"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "AccountController_updatePreferences",
    "summary": "Update preferences (every field optional)",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdatePreferencesDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Account"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users/me/preferences/languages": {
   "get": {
    "operationId": "AccountController_languages",
    "summary": "Languages that can be chosen in preferences",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Account"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users/me/preferences/recovery-email": {
   "post": {
    "operationId": "AccountController_requestRecoveryEmail",
    "summary": "Set a recovery email; a 6-digit code is sent to it",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RecoveryEmailDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Account"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "AccountController_removeRecoveryEmail",
    "summary": "Remove the recovery email",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Account"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users/me/preferences/recovery-email/verify": {
   "post": {
    "operationId": "AccountController_verifyRecoveryEmail",
    "summary": "Confirm the recovery email with the code",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/VerifyRecoveryEmailDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Account"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users/me/workspace": {
   "get": {
    "operationId": "WorkspaceController_get",
    "summary": "Panel bootstrap: account, profile, my businesses (role + billing standing) and their channels with installed app keys",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Account"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users/profile": {
   "delete": {
    "operationId": "UsersController_deleteProfile_2",
    "summary": "Delete user profile and account (moves to trash)",
    "parameters": [
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users/profile/blocked": {
   "get": {
    "operationId": "UsersController_getBlockedProfiles_2",
    "summary": "Get all blocked profiles for the active profile",
    "parameters": [
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users/profile/create": {
   "post": {
    "operationId": "UsersController_createProfile_2",
    "summary": "Create a new user profile",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateProfileDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users/profile/{id}": {
   "post": {
    "operationId": "UsersController_checkUsernameWithId_2",
    "summary": "Check if a username is available for a specific profile ID",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CheckUsernameDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": []
   }
  },
  "/users/profiledetail": {
   "post": {
    "operationId": "UsersController_upsertProfileDetail_2",
    "summary": "Add or Update User Profile Detail (Upsert)",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpsertProfileDetailDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users/profileprivacy": {
   "post": {
    "operationId": "UsersController_upsertProfilePrivacy_2",
    "summary": "Add or update user profile privacy settings",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpsertProfilePrivacyDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users/profiles": {
   "get": {
    "operationId": "UsersController_findMyProfiles_2",
    "summary": "Get profiles belonging to the currently logged-in user",
    "parameters": [],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users/{id}": {
   "get": {
    "operationId": "UsersController_findOne_2",
    "summary": "Get a specific user profile by ID",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active_profile_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": []
   },
   "patch": {
    "operationId": "UsersController_update_2",
    "summary": "Update a specific user profile by ID",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateUserDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users/{id}/block": {
   "post": {
    "operationId": "UsersController_blockProfile_2",
    "summary": "Block a user profile",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users/{id}/donations": {
   "get": {
    "operationId": "UsersController_getProfileDonations_2",
    "summary": "Get a profile's public donations (paged, with total)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": []
   }
  },
  "/users/{id}/follow": {
   "post": {
    "operationId": "UsersController_followProfile_2",
    "summary": "Follow a user profile",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users/{id}/followers": {
   "get": {
    "operationId": "UsersController_getFollowers_2",
    "summary": "Get list of followers for a profile",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "ids_only",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": []
   }
  },
  "/users/{id}/following": {
   "get": {
    "operationId": "UsersController_getFollowing_2",
    "summary": "Get list of profiles this profile is following",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "ids_only",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          },
          {
           "type": "object",
           "properties": {
            "data": {
             "type": "object"
            }
           }
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": []
   }
  },
  "/users/{id}/unblock": {
   "post": {
    "operationId": "UsersController_unblockProfile_2",
    "summary": "Unblock a user profile",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/users/{id}/unfollow": {
   "post": {
    "operationId": "UsersController_unfollowProfile_2",
    "summary": "Unfollow a user profile",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Users Directory"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/vault/items": {
   "get": {
    "operationId": "VaultController_list",
    "summary": "My vault items: metadata only, never the password (paged)",
    "parameters": [
     {
      "name": "q",
      "required": false,
      "in": "query",
      "schema": {
       "maxLength": 200,
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "required": false,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "page",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     },
     {
      "name": "limit",
      "required": false,
      "in": "query",
      "schema": {
       "minimum": 1,
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Vault"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "VaultController_create",
    "summary": "Save a password (encrypted at rest)",
    "parameters": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateVaultItemDto"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Vault"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/vault/items/{id}": {
   "get": {
    "operationId": "VaultController_getOne",
    "summary": "One vault item's metadata (no password)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Vault"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "VaultController_update",
    "summary": "Edit a vault item (a new password is re-encrypted)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateVaultItemDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Vault"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "VaultController_remove",
    "summary": "Delete a vault item",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Vault"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/vault/items/{id}/reveal": {
   "post": {
    "operationId": "VaultController_reveal",
    "summary": "Return the decrypted password (10/min, written to the security log)",
    "parameters": [
     {
      "name": "id",
      "required": true,
      "in": "path",
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Vault"
    ],
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/visitor/stats": {
   "get": {
    "operationId": "VisitorController_stats",
    "summary": "Visitor report for a channel (managers)",
    "description": "Site visits for a channel I manage: totals, by day, sources, places, devices, pages.",
    "parameters": [
     {
      "name": "channel_id",
      "required": true,
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "days",
      "required": false,
      "in": "query",
      "schema": {
       "default": 30,
       "enum": [
        7,
        30,
        90
       ],
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Visitor Tracking"
    ]
   }
  },
  "/visitor/track": {
   "post": {
    "operationId": "VisitorController_trackVisitor",
    "summary": "Track a new or returning anonymous visitor",
    "parameters": [
     {
      "name": "x-ref",
      "required": false,
      "in": "header",
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateVisitorDto"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Visitor tracked successfully",
      "content": {
       "application/json": {
        "schema": {
         "allOf": [
          {
           "$ref": "#/components/schemas/SuccessEnvelope"
          }
         ]
        }
       }
      }
     },
     "default": {
      "description": "Error (GlobalExceptionFilter)",
      "content": {
       "application/json": {
        "schema": {
         "oneOf": [
          {
           "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
           "$ref": "#/components/schemas/AppErrorEnvelope"
          }
         ]
        }
       }
      }
     }
    },
    "tags": [
     "Visitor Tracking"
    ],
    "security": []
   }
  }
 },
 "info": {
  "title": "Kodkila API",
  "description": "Kodkila Business OS API. JSON responses are wrapped in `SuccessEnvelope` (payload in `data`); errors use `ErrorEnvelope` / `AppErrorEnvelope`. Branch on `errorCode`: a 401 means refresh the session only for UNAUTHENTICATED or TOKEN_INVALID; wrong passwords, codes and passkeys answer INVALID_CREDENTIALS / INVALID_CODE / CODE_EXPIRED (401) or TOO_MANY_ATTEMPTS (429), see `AuthErrorCode`.",
  "version": "1.0",
  "contact": {},
  "x-source": "svayam-workplace/kodkila ca50da8"
 },
 "tags": [],
 "servers": [
  {
   "url": "https://api.intersink.com/v1",
   "description": "The API host that answers today (development)"
  }
 ],
 "components": {
  "securitySchemes": {
   "bearer": {
    "scheme": "bearer",
    "bearerFormat": "JWT",
    "type": "http"
   },
   "access_token": {
    "type": "apiKey",
    "in": "cookie",
    "name": "access_token",
    "description": "HttpOnly access token cookie (set by /api/auth/login and the other sign-in routes; 15 minutes)"
   }
  },
  "schemas": {
   "SuccessEnvelope": {
    "type": "object",
    "description": "Every non-raw JSON response is wrapped by TransformInterceptor. The operation's payload is in `data`.",
    "required": [
     "success",
     "statusCode",
     "message",
     "data",
     "timestamp"
    ],
    "properties": {
     "success": {
      "type": "boolean",
      "enum": [
       true
      ]
     },
     "statusCode": {
      "type": "integer",
      "example": 200
     },
     "message": {
      "type": "string",
      "example": "Success"
     },
     "data": {},
     "timestamp": {
      "type": "string",
      "format": "date-time"
     }
    }
   },
   "ErrorEnvelope": {
    "type": "object",
    "description": "HttpException / unhandled error body produced by GlobalExceptionFilter. 4xx payload extras (e.g. retryAfterSeconds) are spread into the body.",
    "required": [
     "success",
     "statusCode",
     "message",
     "timestamp",
     "path"
    ],
    "additionalProperties": true,
    "properties": {
     "success": {
      "type": "boolean",
      "enum": [
       false
      ]
     },
     "statusCode": {
      "type": "integer",
      "example": 400
     },
     "message": {
      "type": "string",
      "example": "Invalid input"
     },
     "errorCode": {
      "type": "string",
      "example": "INVALID_CODE",
      "description": "Stable machine code; branch on this, never on `message`. A 401 means an ended session ONLY when it is UNAUTHENTICATED or TOKEN_INVALID (see AuthErrorCode)."
     },
     "errors": {
      "type": "array",
      "nullable": true,
      "items": {
       "type": "string"
      },
      "description": "class-validator messages when validation failed"
     },
     "timestamp": {
      "type": "string",
      "format": "date-time"
     },
     "path": {
      "type": "string",
      "example": "/api/auth/login"
     },
     "requestId": {
      "type": "string",
      "description": "Correlation id, when the server sets one"
     }
    }
   },
   "AuthErrorCode": {
    "type": "string",
    "description": "Auth error contract (docs/api-routes.md, \"Auth errors\").\n- UNAUTHENTICATED (401), TOKEN_INVALID (401): no session or it expired. Refresh once, then sign in again. These are the ONLY codes that mean refresh.\n- INVALID_CREDENTIALS (401): password, passkey, sign-in token or sealed-sender key is not right. Same message for an unknown account. Do not refresh.\n- INVALID_CODE (401): email/SMS code, authenticator code or recovery code is not right (body may carry failedAttempts, lockoutThreshold). Do not refresh.\n- CODE_EXPIRED (401): the code, challenge or sign-in step expired or was used. Ask for a new code or start again. Do not refresh.\n- TOO_MANY_ATTEMPTS (429): locked after wrong tries. retryAfterSeconds (also retry_after and the Retry-After header) says when, when waiting is the way out.\n- STEP_UP_REQUIRED (401): confirm it's you (POST /auth/step-up), then resend. STEP_UP_FAILED (401): that confirmation was wrong. Do not refresh.\n- INSTALL_MISMATCH (401): an app session bound to one install (X-Install-Id) was used without that header or from another install. Sign in again; refreshing won't help.",
    "enum": [
     "UNAUTHENTICATED",
     "TOKEN_INVALID",
     "INVALID_CREDENTIALS",
     "INVALID_CODE",
     "CODE_EXPIRED",
     "TOO_MANY_ATTEMPTS",
     "STEP_UP_REQUIRED",
     "STEP_UP_FAILED",
     "INSTALL_MISMATCH"
    ]
   },
   "AppErrorEnvelope": {
    "type": "object",
    "description": "AppException body (typed error code) produced by GlobalExceptionFilter.",
    "required": [
     "success",
     "statusCode",
     "error"
    ],
    "properties": {
     "success": {
      "type": "boolean",
      "enum": [
       false
      ]
     },
     "statusCode": {
      "type": "integer",
      "example": 409
     },
     "error": {
      "type": "object",
      "required": [
       "code",
       "message"
      ],
      "properties": {
       "code": {
        "type": "string",
        "example": "ALREADY_SUBSCRIBED"
       },
       "message": {
        "type": "string"
       }
      }
     }
    }
   },
   "UpdateFileDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 255
     },
     "folder_id": {
      "type": "number",
      "nullable": true,
      "minimum": 1
     }
    }
   },
   "CreateFolderDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 120
     },
     "parent_folder_id": {
      "type": "number",
      "minimum": 1
     }
    },
    "required": [
     "name"
    ]
   },
   "UpdateFolderDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 120
     },
     "parent_folder_id": {
      "type": "number",
      "nullable": true,
      "minimum": 1
     }
    }
   },
   "SetProfileMediaDto": {
    "type": "object",
    "properties": {
     "profile_id": {
      "type": "string"
     },
     "file_id": {
      "type": "number",
      "description": "Id of a file the caller already uploaded (file.id is an INTEGER).",
      "minimum": 1
     }
    },
    "required": [
     "profile_id",
     "file_id"
    ]
   },
   "ModerationCheckDto": {
    "type": "object",
    "properties": {}
   },
   "RequestOtpDto": {
    "type": "object",
    "properties": {
     "email": {
      "type": "string",
      "example": "user@example.com"
     },
     "channel_id": {
      "type": "string",
      "example": "REF-A1"
     },
     "delivery": {
      "type": "string",
      "description": "How to deliver the OTP. Defaults to \"email\". \"sms\"/\"whatsapp\" (worldwide via\nTwilio) are only for existing accounts and always go to the mobile stored\non the account. SMS/WhatsApp are for account security only.",
      "enum": [
       "email",
       "sms",
       "whatsapp"
      ],
      "example": "sms"
     },
     "mobile": {
      "type": "string",
      "example": "+919876543210",
      "description": "Ignored for OTP delivery: SMS/WhatsApp always go to the account's stored mobile."
     },
     "captcha": {
      "type": "string",
      "maxLength": 2048,
      "description": "Cloudflare Turnstile token, when the channel turns the check on (GET /auth/sign-in-options)"
     }
    },
    "required": [
     "email"
    ]
   },
   "RequestOtpResultDto": {
    "type": "object",
    "properties": {
     "message": {
      "type": "string",
      "example": "If this address can sign in here, a code is on its way."
     },
     "email": {
      "type": "string",
      "example": "user@example.com"
     },
     "delivery": {
      "type": "string",
      "enum": [
       "email",
       "sms",
       "whatsapp"
      ]
     },
     "retryAfterSeconds": {
      "type": "number",
      "example": 30,
      "description": "Seconds until another code can be asked for (30 after the first, 60 after the second, then 120). Show it as a countdown on Resend."
     },
     "expiresInSeconds": {
      "type": "number",
      "example": 900,
      "description": "How long this code works. Every code sent stays valid until its own expiry."
     },
     "codeLength": {
      "type": "number",
      "example": 6
     }
    },
    "required": [
     "message",
     "email",
     "delivery",
     "retryAfterSeconds",
     "expiresInSeconds",
     "codeLength"
    ]
   },
   "LoginOtpDto": {
    "type": "object",
    "properties": {
     "email": {
      "type": "string",
      "example": "user@example.com"
     },
     "otp": {
      "type": "string",
      "minLength": 6,
      "example": "123456"
     },
     "device_id": {
      "type": "string",
      "example": "iphone_15_pro"
     },
     "channel_id": {
      "type": "string",
      "example": "REF-A1"
     },
     "restore_account": {
      "type": "boolean",
      "description": "Restore a closed account during its 30-day grace window. Without it, signing in to a closed account answers 403 ACCOUNT_CLOSED."
     }
    },
    "required": [
     "email",
     "otp"
    ]
   },
   "UpdateProfileDto": {
    "type": "object",
    "properties": {
     "firstname": {
      "type": "string",
      "maxLength": 255
     },
     "lastname": {
      "type": "string",
      "maxLength": 255
     },
     "username": {
      "type": "string",
      "maxLength": 255
     }
    }
   },
   "LoginUserDto": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid",
      "example": "8d1f6a7e-2b3c-4d5e-9f01-23456789abcd"
     },
     "email": {
      "type": "string",
      "nullable": true,
      "example": "user@example.com",
      "description": "null for an account made with a username only"
     }
    },
    "required": [
     "id",
     "email"
    ]
   },
   "LoginTokensDto": {
    "type": "object",
    "properties": {
     "access_token": {
      "type": "string",
      "description": "JWT for `Authorization: Bearer`, valid 15 minutes. Signed in with X-Install-Id, it works only with that same header (any network, any user agent).",
      "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI4ZDFmNmE3ZSJ9.c2lnbmF0dXJl"
     },
     "refresh_token": {
      "type": "string",
      "description": "Opaque, single use: trade it at POST /auth/refresh-app for a new pair (30 days at most from sign-in). Bound to the install when signed in with X-Install-Id (it then starts with `ib1.`). Keep it in the device's secure storage.",
      "example": "ib1.5e8f3c2a9b7d4e6f1a0c8b2d4e6f8a1c3e5b7d9f1a3c5e7b9d1f3a5c7e9b1d3f.4c1d9e8b7a6f5e4d3c2b1a0f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d"
     },
     "user": {
      "$ref": "#/components/schemas/LoginUserDto"
     },
     "message": {
      "type": "string",
      "example": "Login successful"
     }
    },
    "required": [
     "access_token",
     "refresh_token",
     "user",
     "message"
    ]
   },
   "MfaRequiredDto": {
    "type": "object",
    "properties": {
     "mfa_required": {
      "type": "number",
      "enum": [
       true
      ],
      "example": true
     },
     "methods": {
      "type": "array",
      "example": [
       "totp",
       "otp"
      ],
      "description": "Second steps this account can finish with, in the order to offer them",
      "items": {
       "type": "string",
       "enum": [
        "totp",
        "passkey",
        "otp"
       ]
      }
     },
     "primary": {
      "type": "string",
      "nullable": true,
      "example": "totp",
      "description": "The one to show first"
     },
     "pending_token": {
      "type": "string",
      "description": "Short-lived (5 minutes), single use, useless as an access token. Send it to /auth/mfa/totp, /auth/mfa/otp or /auth/mfa/passkey/*. Started with X-Install-Id, it finishes only from that install.",
      "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwdXJwb3NlIjoibWZhIn0.c2lnbmF0dXJl"
     },
     "email": {
      "type": "string",
      "nullable": true,
      "example": "user@example.com"
     },
     "email_hint": {
      "type": "string",
      "example": "u***@example.com",
      "description": "Where an e-mailed code went, when `otp` is a method"
     },
     "recovery_codes": {
      "type": "boolean",
      "example": true,
      "description": "The authenticator's saved recovery codes are an option"
     },
     "passkey_elsewhere": {
      "example": [
       "example.com"
      ],
      "description": "Sites where this account's 2-step passkeys work, when none works here",
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "message": {
      "type": "string",
      "example": "First factor verified. Complete the second step."
     }
    },
    "required": [
     "mfa_required",
     "methods",
     "primary",
     "pending_token",
     "email",
     "recovery_codes",
     "message"
    ]
   },
   "GoogleLoginDto": {
    "type": "object",
    "properties": {
     "id_token": {
      "type": "string",
      "example": "eyJhbGciOi...",
      "description": "The Google ID token obtained by the client from Google Sign-In"
     },
     "channel_id": {
      "type": "string",
      "example": "REF-A1"
     },
     "device_id": {
      "type": "string",
      "example": "iphone_15_pro"
     }
    },
    "required": [
     "id_token"
    ]
   },
   "AppleLoginDto": {
    "type": "object",
    "properties": {
     "identity_token": {
      "type": "string",
      "example": "eyJraWQiOi...",
      "description": "The Apple identity token from Sign in with Apple"
     },
     "channel_id": {
      "type": "string",
      "example": "REF-A1"
     },
     "device_id": {
      "type": "string",
      "example": "iphone_15_pro"
     }
    },
    "required": [
     "identity_token"
    ]
   },
   "LoginPasswordDto": {
    "type": "object",
    "properties": {
     "email": {
      "type": "string",
      "example": "user@example.com",
      "description": "Email or `username` (one of the two is required)"
     },
     "username": {
      "type": "string",
      "description": "Sign in with the username of the account's profile in this channel.",
      "pattern": "^[A-Za-z0-9._]{3,30}$",
      "example": "riya_716"
     },
     "password": {
      "type": "string",
      "example": "MyS3cret!"
     },
     "device_id": {
      "type": "string",
      "example": "iphone_15_pro"
     },
     "channel_id": {
      "type": "string",
      "example": "REF-A1"
     },
     "captcha": {
      "type": "string",
      "maxLength": 2048,
      "description": "Cloudflare Turnstile token, when the channel turns the check on (GET /auth/sign-in-options)"
     }
    },
    "required": [
     "password"
    ]
   },
   "ResetPasswordDto": {
    "type": "object",
    "properties": {
     "email": {
      "type": "string",
      "example": "user@example.com"
     },
     "otp": {
      "type": "string",
      "minLength": 6,
      "example": "123456"
     },
     "new_password": {
      "type": "string",
      "example": "MyNewS3cret!"
     },
     "channel_id": {
      "type": "string",
      "example": "REF-A1"
     }
    },
    "required": [
     "email",
     "otp",
     "new_password"
    ]
   },
   "TwoFactorDto": {
    "type": "object",
    "properties": {
     "enabled": {
      "type": "boolean",
      "example": true,
      "description": "Enable or disable 2FA"
     }
    },
    "required": [
     "enabled"
    ]
   },
   "AuthMethodsDto": {
    "type": "object",
    "properties": {
     "email": {
      "type": "string",
      "example": "user@example.com"
     },
     "channel_id": {
      "type": "string",
      "example": "REF-A1"
     }
    },
    "required": [
     "email"
    ]
   },
   "EnableTotpDto": {
    "type": "object",
    "properties": {
     "code": {
      "type": "string",
      "example": "123456",
      "description": "Code from authenticator app"
     }
    },
    "required": [
     "code"
    ]
   },
   "RegenerateRecoveryCodesDto": {
    "type": "object",
    "properties": {
     "code": {
      "type": "string",
      "maxLength": 32,
      "example": "123456",
      "description": "Current authenticator code (or an unused recovery code)"
     }
    },
    "required": [
     "code"
    ]
   },
   "StepUpDto": {
    "type": "object",
    "properties": {
     "method": {
      "type": "string",
      "enum": [
       "passkey",
       "totp",
       "password",
       "email"
      ]
     },
     "code": {
      "type": "string",
      "maxLength": 32,
      "description": "Authenticator, recovery or e-mailed code"
     },
     "password": {
      "type": "string",
      "maxLength": 256
     },
     "response": {
      "type": "object",
      "description": "The passkey assertion (WebAuthn response JSON)"
     }
    },
    "required": [
     "method"
    ]
   },
   "LoginTotpDto": {
    "type": "object",
    "properties": {
     "email": {
      "type": "string",
      "example": "user@example.com"
     },
     "code": {
      "type": "string",
      "example": "123456",
      "description": "Authenticator or backup code"
     },
     "device_id": {
      "type": "string",
      "example": "iphone_15_pro"
     },
     "channel_id": {
      "type": "string",
      "example": "REF-A1"
     },
     "captcha": {
      "type": "string",
      "maxLength": 2048,
      "description": "Cloudflare Turnstile token (channels with auth.captcha=turnstile; see GET /auth/sign-in-options)"
     }
    },
    "required": [
     "email",
     "code"
    ]
   },
   "MfaTotpDto": {
    "type": "object",
    "properties": {
     "pending_token": {
      "type": "string",
      "description": "The pending-login token from the first factor"
     },
     "code": {
      "type": "string",
      "example": "123456",
      "description": "Authenticator or backup code"
     }
    },
    "required": [
     "pending_token",
     "code"
    ]
   },
   "MfaOtpDto": {
    "type": "object",
    "properties": {
     "pending_token": {
      "type": "string",
      "description": "The pending-login token from the first factor"
     },
     "otp": {
      "type": "string",
      "example": "123456",
      "description": "The emailed OTP"
     }
    },
    "required": [
     "pending_token",
     "otp"
    ]
   },
   "MfaPendingDto": {
    "type": "object",
    "properties": {
     "pending_token": {
      "type": "string",
      "description": "The pending-login token from the first factor"
     }
    },
    "required": [
     "pending_token"
    ]
   },
   "MfaPasskeyVerifyDto": {
    "type": "object",
    "properties": {
     "pending_token": {
      "type": "string",
      "description": "The pending-login token from the first factor"
     },
     "response": {
      "type": "object",
      "description": "The WebAuthn assertion response"
     }
    },
    "required": [
     "pending_token",
     "response"
    ]
   },
   "PasskeyRegisterVerifyDto": {
    "type": "object",
    "properties": {
     "response": {
      "type": "object",
      "description": "Attestation response from the authenticator"
     },
     "device_name": {
      "type": "string",
      "example": "iPhone 15"
     }
    },
    "required": [
     "response"
    ]
   },
   "PasskeyLoginOptionsDto": {
    "type": "object",
    "properties": {
     "email": {
      "type": "string",
      "example": "user@example.com",
      "description": "Omit for a discoverable (usernameless) passkey sign-in"
     },
     "channel_id": {
      "type": "string",
      "example": "REF-A1"
     }
    }
   },
   "PasskeyLoginVerifyDto": {
    "type": "object",
    "properties": {
     "email": {
      "type": "string",
      "example": "user@example.com"
     },
     "challenge_id": {
      "type": "string",
      "description": "From passkey/login/options when no e-mail was given"
     },
     "response": {
      "type": "object",
      "description": "Assertion response from the authenticator"
     },
     "device_id": {
      "type": "string",
      "example": "iphone_15_pro"
     },
     "channel_id": {
      "type": "string",
      "example": "REF-A1"
     }
    },
    "required": [
     "response"
    ]
   },
   "RefreshTokenDto": {
    "type": "object",
    "properties": {
     "refresh_token": {
      "type": "string"
     }
    },
    "required": [
     "refresh_token"
    ]
   },
   "RefreshResultDto": {
    "type": "object",
    "properties": {
     "access_token": {
      "type": "string",
      "description": "New access token (15 minutes)",
      "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI4ZDFmNmE3ZSJ9.c2lnbmF0dXJl"
     },
     "refresh_token": {
      "type": "string",
      "description": "New refresh token: the one sent is spent (a repeat within 30 seconds returns this same pair)",
      "example": "ib1.5e8f3c2a9b7d4e6f1a0c8b2d4e6f8a1c3e5b7d9f1a3c5e7b9d1f3a5c7e9b1d3f.0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e"
     }
    },
    "required": [
     "access_token",
     "refresh_token"
    ]
   },
   "SwitchProfileDto": {
    "type": "object",
    "properties": {
     "profile_id": {
      "type": "string",
      "example": "8b98f219-c120-4a8e-a9b0-4b2a8d1a1b1b"
     },
     "business_id": {
      "type": "string",
      "example": "5f3d06b8-3d46-4b0c-aae2-b443b2ea9973"
     },
     "channel_id": {
      "type": "string",
      "example": "42f5bb84-b9d6-41b9-b837-e9bba90ff03b"
     },
     "refresh_token": {
      "type": "string"
     }
    }
   },
   "LogoutAllDto": {
    "type": "object",
    "properties": {
     "linked_devices": {
      "type": "boolean",
      "description": "Also remove every linked end-to-end-encrypted device of the account (except this session's own device). Default false."
     },
     "e2ee_devices": {
      "type": "boolean",
      "description": "Same as linked_devices."
     }
    }
   },
   "OpaqueRegisterStartDto": {
    "type": "object",
    "properties": {
     "username": {
      "type": "string",
      "maxLength": 64,
      "example": "asha",
      "description": "3–32 chars of [a-z0-9_.] with a letter (asha). The older form with '.' and a 2-digit discriminator (asha.07) is still accepted. Normalised to lowercase."
     },
     "registration_request": {
      "type": "string",
      "maxLength": 256,
      "pattern": "^[A-Za-z0-9_-]+$",
      "description": "OPAQUE RegistrationRequest (base64url). Call once for the password and once for the recovery key."
     }
    },
    "required": [
     "username",
     "registration_request"
    ]
   },
   "OpaquePowDto": {
    "type": "object",
    "properties": {
     "salt": {
      "type": "string",
      "maxLength": 64
     },
     "bits": {
      "type": "number"
     },
     "exp": {
      "type": "number",
      "description": "ms since epoch"
     },
     "sig": {
      "type": "string",
      "maxLength": 128
     },
     "nonce": {
      "type": "string",
      "maxLength": 64,
      "description": "1–64 chars of [A-Za-z0-9_-]"
     }
    },
    "required": [
     "salt",
     "bits",
     "exp",
     "sig",
     "nonce"
    ]
   },
   "OpaqueDeviceDto": {
    "type": "object",
    "properties": {
     "device_id": {
      "type": "string",
      "maxLength": 255,
      "example": "iphone-1"
     }
    }
   },
   "OpaqueRegisterFinishDto": {
    "type": "object",
    "properties": {
     "username": {
      "type": "string",
      "maxLength": 64,
      "example": "asha.07"
     },
     "registration_record": {
      "type": "string",
      "maxLength": 512,
      "pattern": "^[A-Za-z0-9_-]+$",
      "description": "OPAQUE RegistrationRecord for the password"
     },
     "recovery_record": {
      "type": "string",
      "maxLength": 512,
      "pattern": "^[A-Za-z0-9_-]+$",
      "description": "OPAQUE RegistrationRecord for the recovery key (mandatory)"
     },
     "pow": {
      "$ref": "#/components/schemas/OpaquePowDto"
     },
     "captcha": {
      "type": "string",
      "maxLength": 2048,
      "description": "Cloudflare Turnstile token (channels with auth.captcha=turnstile)"
     },
     "device": {
      "$ref": "#/components/schemas/OpaqueDeviceDto"
     },
     "email": {
      "type": "string",
      "maxLength": 254,
      "description": "Optional email (recovery only). Needs `email_otp` from POST /auth/request-otp. Required when the channel keeps auth.email_required on. A `.test` address is accepted only on the dev API while QA mode is in effect (its code is read from the test inbox): the account is then tagged as a QA account, counts against the shared QA quota instead of SIGNUP_LIMIT and is purged after 7 days (docs/qa-mode.md). Elsewhere it is refused: 400 QA_EMAIL_REFUSED, or 503 QA_STORE_NOT_READY while QA mode waits for its tables."
     },
     "email_otp": {
      "type": "string",
      "pattern": "^[0-9]{6}$",
      "example": "123456"
     }
    },
    "required": [
     "username",
     "registration_record",
     "recovery_record",
     "pow"
    ]
   },
   "OpaqueLoginStartDto": {
    "type": "object",
    "properties": {
     "username": {
      "type": "string",
      "maxLength": 64,
      "example": "asha.07"
     },
     "start_login_request": {
      "type": "string",
      "maxLength": 512,
      "pattern": "^[A-Za-z0-9_-]+$",
      "description": "OPAQUE KE1 / startLoginRequest (base64url)"
     },
     "credential": {
      "type": "string",
      "enum": [
       "password",
       "recovery"
      ]
     },
     "captcha": {
      "type": "string",
      "maxLength": 2048,
      "description": "Cloudflare Turnstile token (channels with auth.captcha=turnstile; see GET /auth/sign-in-options)"
     }
    },
    "required": [
     "username",
     "start_login_request",
     "credential"
    ]
   },
   "OpaqueLoginFinishDto": {
    "type": "object",
    "properties": {
     "login_id": {
      "type": "string",
      "maxLength": 64,
      "pattern": "^[A-Za-z0-9_-]+$"
     },
     "finish_login_request": {
      "type": "string",
      "maxLength": 256,
      "pattern": "^[A-Za-z0-9_-]+$",
      "description": "OPAQUE KE3 / finishLoginRequest (base64url)"
     },
     "device_id": {
      "type": "string",
      "maxLength": 255,
      "example": "iphone-1"
     }
    },
    "required": [
     "login_id",
     "finish_login_request"
    ]
   },
   "OpaqueCredentialStartDto": {
    "type": "object",
    "properties": {
     "credential": {
      "type": "string",
      "enum": [
       "password",
       "recovery"
      ]
     },
     "registration_request": {
      "type": "string",
      "maxLength": 256,
      "pattern": "^[A-Za-z0-9_-]+$"
     }
    },
    "required": [
     "credential",
     "registration_request"
    ]
   },
   "OpaqueCredentialFinishDto": {
    "type": "object",
    "properties": {
     "credential": {
      "type": "string",
      "enum": [
       "password",
       "recovery"
      ]
     },
     "registration_record": {
      "type": "string",
      "maxLength": 512,
      "pattern": "^[A-Za-z0-9_-]+$"
     }
    },
    "required": [
     "credential",
     "registration_record"
    ]
   },
   "OpaqueStepUpStartDto": {
    "type": "object",
    "properties": {
     "start_login_request": {
      "type": "string",
      "maxLength": 512,
      "pattern": "^[A-Za-z0-9_-]+$",
      "description": "OPAQUE KE1 / startLoginRequest (base64url)"
     },
     "credential": {
      "type": "string",
      "enum": [
       "password",
       "recovery"
      ],
      "default": "password"
     }
    },
    "required": [
     "start_login_request"
    ]
   },
   "OpaqueStepUpFinishDto": {
    "type": "object",
    "properties": {
     "login_id": {
      "type": "string",
      "maxLength": 64,
      "pattern": "^[A-Za-z0-9_-]+$",
      "description": "login_id from /auth/step-up/opaque/start"
     },
     "finish_login_request": {
      "type": "string",
      "maxLength": 256,
      "pattern": "^[A-Za-z0-9_-]+$",
      "description": "OPAQUE KE3 / finishLoginRequest (base64url)"
     }
    },
    "required": [
     "login_id",
     "finish_login_request"
    ]
   },
   "OpaqueStepUpSecondFactorDto": {
    "type": "object",
    "properties": {
     "method": {
      "type": "string",
      "enum": [
       "totp",
       "passkey",
       "email"
      ],
      "description": "One of the `methods` the finish step answered. email: the code from POST /auth/step-up/email. passkey: the assertion for POST /auth/step-up/passkey/options."
     },
     "code": {
      "type": "string",
      "maxLength": 32,
      "description": "Authenticator code, recovery code or e-mailed code"
     },
     "response": {
      "type": "object",
      "description": "The passkey assertion (WebAuthn response JSON)"
     }
    },
    "required": [
     "method"
    ]
   },
   "CreateRoleDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 60,
      "example": "Sales"
     },
     "description": {
      "type": "string",
      "maxLength": 255,
      "example": "Leads, contacts, orders and tickets"
     },
     "permissions": {
      "example": [
       "channel.view",
       "apps.view"
      ],
      "description": "Permission keys (see GET /iam/:scope/:scopeId/permissions)",
      "type": "array",
      "items": {
       "type": "string",
       "pattern": "^[a-z0-9-]+(\\.[a-z0-9-]+){1,3}$"
      }
     }
    },
    "required": [
     "title"
    ]
   },
   "UpdateRoleDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 60,
      "example": "Sales"
     },
     "description": {
      "type": "string",
      "maxLength": 255,
      "example": "Leads, contacts, orders and tickets"
     },
     "permissions": {
      "example": [
       "channel.view",
       "apps.view"
      ],
      "description": "Permission keys (see GET /iam/:scope/:scopeId/permissions)",
      "type": "array",
      "items": {
       "type": "string",
       "pattern": "^[a-z0-9-]+(\\.[a-z0-9-]+){1,3}$"
      }
     }
    }
   },
   "MatrixRowDto": {
    "type": "object",
    "properties": {
     "role_id": {
      "type": "string"
     },
     "permissions": {
      "type": "array",
      "items": {
       "type": "string",
       "pattern": "^[a-z0-9-]+(\\.[a-z0-9-]+){1,3}$"
      }
     }
    },
    "required": [
     "role_id",
     "permissions"
    ]
   },
   "PutMatrixDto": {
    "type": "object",
    "properties": {
     "roles": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/MatrixRowDto"
      }
     }
    },
    "required": [
     "roles"
    ]
   },
   "AssignRoleDto": {
    "type": "object",
    "properties": {
     "role_id": {
      "type": "string",
      "nullable": true,
      "description": "Role to assign; null clears it (the legacy permission level applies again)"
     }
    }
   },
   "NotificationRouteDto": {
    "type": "object",
    "properties": {
     "screen": {
      "type": "string",
      "example": "security"
     },
     "id": {
      "type": "string",
      "example": ""
     }
    },
    "required": [
     "screen",
     "id"
    ]
   },
   "NotificationTargetDto": {
    "type": "object",
    "properties": {
     "kind": {
      "type": "string",
      "example": "post",
      "description": "What the notification is about: `post`, `comment`, `story`, `profile`, `group`, `event`, `listing`, `report`, `account` (new-place sign-in alert), or an older kind's `screen` such as `security` (other security alerts, including `security.device_added`). Some kinds add more string ids next to the ones listed here (interest_id, outcome, source, decision, content_kind, action)."
     },
     "id": {
      "type": "string",
      "nullable": true,
      "example": "42"
     },
     "post_id": {
      "type": "string",
      "nullable": true,
      "description": "Comment targets: the post the comment is on."
     },
     "device_id": {
      "type": "string",
      "example": "2",
      "description": "`security.device_added` only: the e2ee device id (1 to 127, as a decimal string) of the device that was just added, so that device can tell its own alert from one about another device."
     },
     "listing_kind": {
      "type": "string",
      "enum": [
       "post",
       "product"
      ],
      "description": "Listing targets."
     }
    },
    "required": [
     "kind",
     "id"
    ]
   },
   "NotificationActorDto": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string"
     },
     "name": {
      "type": "string",
      "nullable": true
     },
     "avatar": {
      "type": "string",
      "nullable": true
     },
     "image_url": {
      "type": "string",
      "nullable": true
     }
    },
    "required": [
     "id",
     "name",
     "avatar",
     "image_url"
    ]
   },
   "NotificationDto": {
    "type": "object",
    "properties": {
     "id": {
      "oneOf": [
       {
        "type": "integer"
       },
       {
        "type": "string"
       }
      ]
     },
     "type": {
      "type": "string",
      "example": "security.device_added",
      "description": "The kind. New kinds are only added; a kind is never renamed."
     },
     "title": {
      "type": "string",
      "example": "New device added"
     },
     "message": {
      "type": "string",
      "example": "A new device was added: Firefox on macOS."
     },
     "read": {
      "type": "boolean"
     },
     "post_id": {
      "oneOf": [
       {
        "type": "integer"
       },
       {
        "type": "string"
       }
      ],
      "nullable": true
     },
     "campaign_id": {
      "oneOf": [
       {
        "type": "integer"
       },
       {
        "type": "string"
       }
      ],
      "nullable": true
     },
     "event_id": {
      "oneOf": [
       {
        "type": "integer"
       },
       {
        "type": "string"
       }
      ],
      "nullable": true
     },
     "thumbnail_url": {
      "type": "string",
      "nullable": true
     },
     "comment_id": {
      "oneOf": [
       {
        "type": "integer"
       },
       {
        "type": "string"
       }
      ],
      "nullable": true
     },
     "route": {
      "$ref": "#/components/schemas/NotificationRouteDto"
     },
     "target": {
      "$ref": "#/components/schemas/NotificationTargetDto"
     },
     "recipient_profile_id": {
      "type": "string"
     },
     "created_at": {
      "type": "string",
      "format": "date-time"
     },
     "actor": {
      "nullable": true,
      "allOf": [
       {
        "$ref": "#/components/schemas/NotificationActorDto"
       }
      ]
     }
    },
    "required": [
     "id",
     "type",
     "title",
     "message",
     "read",
     "post_id",
     "campaign_id",
     "event_id",
     "thumbnail_url",
     "comment_id",
     "route",
     "target",
     "recipient_profile_id",
     "created_at",
     "actor"
    ]
   },
   "CreateEmailTemplateDto": {
    "type": "object",
    "properties": {
     "category": {
      "type": "string",
      "nullable": true,
      "maxLength": 60,
      "example": "Transactional"
     },
     "body_text": {
      "type": "string",
      "nullable": true,
      "maxLength": 50000,
      "description": "Plain-text alternative body ({{var}} placeholders)"
     },
     "variables": {
      "nullable": true,
      "example": [
       "channel",
       "order_id"
      ],
      "description": "Documented variables (informational; used by preview)",
      "type": "array",
      "items": {
       "type": "string",
       "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*(?:\\.[a-zA-Z_][a-zA-Z0-9_]*){0,3}$"
      }
     },
     "key": {
      "type": "string",
      "maxLength": 80,
      "pattern": "^[a-z0-9]+(?:[-_.][a-z0-9]+)*$",
      "example": "order-confirmation",
      "description": "Unique per channel"
     },
     "name": {
      "type": "string",
      "maxLength": 120,
      "example": "Order confirmation"
     },
     "subject": {
      "type": "string",
      "maxLength": 255,
      "example": "Your order {{order_id}} is confirmed"
     },
     "body_html": {
      "type": "string",
      "maxLength": 100000,
      "description": "HTML body. Sanitized server-side; {{var}} is HTML-escaped"
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published"
      ],
      "default": "draft"
     }
    },
    "required": [
     "key",
     "name",
     "subject",
     "body_html"
    ]
   },
   "UpdateEmailTemplateDto": {
    "type": "object",
    "properties": {
     "category": {
      "type": "string",
      "nullable": true,
      "maxLength": 60,
      "example": "Transactional"
     },
     "body_text": {
      "type": "string",
      "nullable": true,
      "maxLength": 50000,
      "description": "Plain-text alternative body ({{var}} placeholders)"
     },
     "variables": {
      "nullable": true,
      "example": [
       "channel",
       "order_id"
      ],
      "description": "Documented variables (informational; used by preview)",
      "type": "array",
      "items": {
       "type": "string",
       "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*(?:\\.[a-zA-Z_][a-zA-Z0-9_]*){0,3}$"
      }
     },
     "key": {
      "type": "string",
      "maxLength": 80,
      "pattern": "^[a-z0-9]+(?:[-_.][a-z0-9]+)*$",
      "example": "order-confirmation"
     },
     "name": {
      "type": "string",
      "maxLength": 120
     },
     "subject": {
      "type": "string",
      "maxLength": 255
     },
     "body_html": {
      "type": "string",
      "maxLength": 100000
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published",
       "archived"
      ]
     }
    }
   },
   "PreviewEmailTemplateDto": {
    "type": "object",
    "properties": {
     "variables": {
      "type": "object",
      "example": {
       "channel": "Dailybasket",
       "order_id": "A-1001"
      },
      "description": "Sample values (max 16 KB). {{x}} is escaped in HTML."
     }
    }
   },
   "CreateBillingAccountDto": {
    "type": "object",
    "properties": {
     "business_id": {
      "type": "string",
      "description": "Business that pays (you must own it)"
     },
     "country_code": {
      "type": "string",
      "enum": [
       "GB",
       "US"
      ],
      "description": "Billing country. Sets the currency for good: GB → GBP, US → USD."
     },
     "billing_email": {
      "type": "string",
      "maxLength": 254,
      "example": "accounts@example.com"
     },
     "billing_name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200,
      "description": "Name on invoices (defaults to the legal name)"
     },
     "billing_address": {
      "type": "object",
      "example": {
       "line1": "1 High St",
       "city": "London",
       "postal_code": "EC1V 2NX",
       "country": "GB"
      }
     },
     "vat_number": {
      "type": "string",
      "pattern": "^[A-Z]{2}[A-Z0-9]{2,30}$",
      "example": "GB123456789"
     }
    },
    "required": [
     "business_id",
     "country_code",
     "billing_email"
    ]
   },
   "UpdateBillingAccountDto": {
    "type": "object",
    "properties": {
     "billing_name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
     },
     "billing_email": {
      "type": "string",
      "maxLength": 254
     },
     "billing_address": {
      "type": "object"
     },
     "vat_number": {
      "type": "string",
      "nullable": true,
      "pattern": "^[A-Z]{2}[A-Z0-9]{2,30}$"
     }
    }
   },
   "PayInvoiceDto": {
    "type": "object",
    "properties": {
     "payment_id": {
      "type": "string",
      "description": "A successful /payments payment for exactly the amount due, with metadata.invoice_id"
     }
    },
    "required": [
     "payment_id"
    ]
   },
   "CreateCreditApplicationDto": {
    "type": "object",
    "properties": {
     "program_key": {
      "type": "string",
      "pattern": "^[a-z][a-z0-9_]{1,39}$",
      "example": "startup",
      "description": "A programme key from GET /billing/credit-programs"
     },
     "answers": {
      "type": "object",
      "example": {
       "org": "Contoso Labs",
       "site": "https://alpha.example",
       "email": "founders@alpha.example",
       "use": "CRM for 6 people"
      },
      "description": "The applicant's answers (flat object of short strings, max 8 KB)"
     }
    },
    "required": [
     "program_key",
     "answers"
    ]
   },
   "UpdateCreditApplicationDto": {
    "type": "object",
    "properties": {
     "answers": {
      "type": "object",
      "description": "Revised answers (only while more_info)"
     }
    },
    "required": [
     "answers"
    ]
   },
   "ReviewCreditApplicationDto": {
    "type": "object",
    "properties": {
     "decision": {
      "type": "string",
      "enum": [
       "approved",
       "rejected",
       "more_info"
      ]
     },
     "note": {
      "type": "string",
      "maxLength": 1000,
      "description": "Shown to the applicant (required for rejected / more_info)"
     },
     "amount_minor": {
      "type": "number",
      "minimum": 100,
      "maximum": 100000,
      "description": "Override the grant (minor units, account currency). Up to the public cap (15000 = £150 / $150); up to 100000 (£1,000 / $1,000) only with above_public_cap."
     },
     "above_public_cap": {
      "type": "boolean",
      "description": "Grant more than the public cap. Only an owner or admin of the platform business, after a fresh step-up, and with override_reason."
     },
     "override_reason": {
      "type": "string",
      "maxLength": 200,
      "description": "Internal reason for an above-cap grant (required with above_public_cap). Kept in the platform audit trail; never shown to the applicant."
     }
    },
    "required": [
     "decision"
    ]
   },
   "CreateAppDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 255,
      "example": "Analytics Pro"
     },
     "sub_description": {
      "type": "string",
      "example": "Powerful analytics for your channel"
     },
     "description": {
      "type": "string"
     },
     "image": {
      "type": "string",
      "description": "directus_files id for the app icon"
     },
     "cover": {
      "type": "string",
      "description": "directus_files id for the cover image"
     },
     "price": {
      "type": "string",
      "pattern": "^\\d{1,9}(\\.\\d{1,2})?$",
      "example": "499.00"
     },
     "currency": {
      "type": "string",
      "pattern": "^[A-Z]{3}$",
      "example": "INR"
     },
     "service": {
      "type": "string"
     }
    },
    "required": [
     "name"
    ]
   },
   "CreateChannelAppDto": {
    "type": "object",
    "properties": {
     "app_id": {
      "type": "string",
      "description": "Id of the app to link to the channel"
     },
     "channel_id": {
      "type": "string",
      "description": "Channel to install into. Defaults to the channel in your token; you must manage it."
     },
     "plan_id": {
      "type": "string",
      "description": "Plan to buy (GET /billing/plans). Required for apps sold on plans; billed daily to the channel's business."
     }
    },
    "required": [
     "app_id"
    ]
   },
   "AppReviewDto": {
    "type": "object",
    "properties": {
     "rating": {
      "type": "number",
      "minimum": 1,
      "maximum": 5
     },
     "title": {
      "type": "string",
      "maxLength": 120
     },
     "text": {
      "type": "string",
      "maxLength": 2000
     }
    },
    "required": [
     "rating"
    ]
   },
   "AppAccessDto": {
    "type": "object",
    "properties": {
     "role_ids": {
      "description": "Channel roles that may use the app. Roles not listed lose access.",
      "type": "array",
      "items": {
       "type": "string"
      }
     }
    },
    "required": [
     "role_ids"
    ]
   },
   "AppInputDto": {
    "type": "object",
    "properties": {
     "package_name": {
      "type": "string",
      "minLength": 3,
      "maxLength": 120,
      "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$",
      "example": "com.example.orders",
      "description": "Reverse-DNS package name, unique in the Store (required to create)"
     },
     "key": {
      "type": "string",
      "pattern": "^[a-z][a-z0-9-]{1,38}$",
      "example": "orders",
      "description": "Stable key (a-z, 0-9, -). The platform's own apps only; others get one."
     },
     "name": {
      "type": "string",
      "minLength": 2,
      "maxLength": 80,
      "example": "Multivendor"
     },
     "description": {
      "type": "string",
      "minLength": 0,
      "maxLength": 500
     },
     "category": {
      "type": "string",
      "minLength": 0,
      "maxLength": 60,
      "example": "Commerce"
     },
     "icon": {
      "type": "string",
      "minLength": 0,
      "maxLength": 40,
      "example": "cart"
     },
     "color": {
      "type": "string",
      "pattern": "^#[0-9a-fA-F]{6}$",
      "example": "#16A34A"
     },
     "capabilities": {
      "example": [
       "zip.catalog",
       "zip.sales"
      ],
      "description": "Capability keys (GET /app-builder/capabilities)",
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "price_gbp_minor": {
      "type": "number",
      "minimum": 0,
      "example": 2499,
      "description": "Monthly GBP price in pence; 0 = free"
     },
     "price_usd_minor": {
      "type": "number",
      "minimum": 0,
      "example": 2999,
      "description": "Monthly USD price in cents; 0 = free"
     },
     "homepage_url": {
      "type": "string"
     },
     "webhook_url": {
      "type": "string"
     },
     "availability": {
      "type": "string",
      "enum": [
       "available",
       "beta",
       "coming_soon"
      ],
      "description": "The platform's own apps only; ignored for others"
     }
    }
   },
   "ProjectDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "minLength": 2,
      "maxLength": 80,
      "example": "Warehouse sync"
     },
     "description": {
      "type": "string",
      "minLength": 0,
      "maxLength": 1000,
      "description": "One or two sentences about it"
     },
     "use_case": {
      "type": "string",
      "minLength": 0,
      "maxLength": 5000,
      "description": "What you build with the API and for whom (the review reads it)"
     },
     "project_url": {
      "type": "string",
      "example": "https://acme.example"
     },
     "privacy_url": {
      "type": "string",
      "example": "https://acme.example/privacy"
     },
     "contact_name": {
      "type": "string",
      "minLength": 0,
      "maxLength": 120
     },
     "contact_phone": {
      "type": "string",
      "minLength": 0,
      "maxLength": 40,
      "description": "A number the review team can call"
     },
     "domains": {
      "example": [
       "acme.example",
       "*.acme.example"
      ],
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "scopes": {
      "type": "array",
      "enum": [
       "products:read",
       "products:write",
       "orders:read",
       "orders:write",
       "customers:read",
       "crm:read",
       "crm:write",
       "e2ee:gateway",
       "channel:config:read",
       "releases:write",
       "updates:write",
       "profile_data:read",
       "search:read",
       "search:write",
       "search:admin",
       "media:read",
       "media:write",
       "features:read",
       "features:write",
       "jobs:apply"
      ],
      "items": {
       "type": "string",
       "enum": [
        "products:read",
        "products:write",
        "orders:read",
        "orders:write",
        "customers:read",
        "crm:read",
        "crm:write",
        "e2ee:gateway",
        "channel:config:read",
        "releases:write",
        "updates:write",
        "profile_data:read",
        "search:read",
        "search:write",
        "search:admin",
        "media:read",
        "media:write",
        "features:read",
        "features:write",
        "jobs:apply"
       ]
      }
     },
     "channel_ids": {
      "description": "Channels of your own business it works on",
      "type": "array",
      "items": {
       "type": "string"
      }
     }
    }
   },
   "SubmitProjectDto": {
    "type": "object",
    "properties": {
     "accept_terms": {
      "type": "boolean",
      "description": "Accepts the API policy and developer terms"
     }
    },
    "required": [
     "accept_terms"
    ]
   },
   "CheckupDto": {
    "type": "object",
    "properties": {
     "accept_terms": {
      "type": "boolean",
      "description": "Accepts the current API policy"
     },
     "still_accurate": {
      "type": "boolean",
      "description": "The project still does what was approved"
     },
     "use_case": {
      "type": "string",
      "minLength": 0,
      "maxLength": 5000,
      "description": "An updated description of what it does"
     }
    },
    "required": [
     "accept_terms",
     "still_accurate"
    ]
   },
   "ProjectDecisionDto": {
    "type": "object",
    "properties": {
     "decision": {
      "type": "string",
      "enum": [
       "approved",
       "changes_requested",
       "rejected",
       "suspended"
      ]
     },
     "reason": {
      "type": "string",
      "minLength": 0,
      "maxLength": 1000,
      "description": "Shown to the developer (required unless approving)"
     },
     "scopes": {
      "description": "Approve only these of the requested scopes",
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "domains": {
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "channel_ids": {
      "type": "array",
      "items": {
       "type": "string"
      }
     }
    },
    "required": [
     "decision"
    ]
   },
   "ProjectNotesDto": {
    "type": "object",
    "properties": {
     "notes": {
      "type": "string",
      "minLength": 0,
      "maxLength": 10000,
      "description": "The review team's notes (never shown to the developer)"
     }
    },
    "required": [
     "notes"
    ]
   },
   "RegisterDeveloperDto": {
    "type": "object",
    "properties": {
     "display_name": {
      "type": "string",
      "minLength": 2,
      "maxLength": 120,
      "example": "Acme Apps",
      "description": "Shown as the publisher in the Store"
     },
     "contact_email": {
      "type": "string",
      "example": "dev@acme.example"
     },
     "website": {
      "type": "string",
      "example": "https://acme.example"
     },
     "accept_terms": {
      "type": "boolean",
      "description": "Accepts the developer terms and API policy (required)"
     }
    },
    "required": [
     "display_name",
     "accept_terms"
    ]
   },
   "ReviewDecisionInputDto": {
    "type": "object",
    "properties": {
     "decision": {
      "type": "string",
      "enum": [
       "approved",
       "rejected",
       "suspended",
       "revoked"
      ]
     },
     "reason": {
      "type": "string",
      "minLength": 0,
      "maxLength": 500,
      "description": "Required to reject or suspend"
     },
     "capabilities_version": {
      "type": "number",
      "minimum": 1,
      "description": "With an approval: also approve this pending capability version (the one you reviewed). Refused when a newer one is waiting."
     }
    },
    "required": [
     "decision"
    ]
   },
   "CapabilityDecisionDto": {
    "type": "object",
    "properties": {
     "decision": {
      "type": "string",
      "enum": [
       "approved",
       "rejected"
      ]
     },
     "reason": {
      "type": "string",
      "minLength": 0,
      "maxLength": 500,
      "description": "Required to reject"
     }
    },
    "required": [
     "decision"
    ]
   },
   "CreateVisitorDto": {
    "type": "object",
    "properties": {
     "device_id": {
      "type": "string",
      "maxLength": 100,
      "description": "The browser's random id, sent only after the visitor allowed analytics. Stored as a keyed hash per channel, never as sent."
     },
     "channel_id": {
      "type": "string",
      "description": "Channel ID where the visit originated"
     },
     "country": {
      "type": "string",
      "description": "Visitor country (can be populated via frontend or backend)"
     },
     "city": {
      "type": "string",
      "description": "Visitor city"
     },
     "utm_source": {
      "type": "string",
      "description": "UTM Source for marketing tracking"
     },
     "utm_medium": {
      "type": "string",
      "description": "UTM Medium for marketing tracking"
     },
     "utm_campaign": {
      "type": "string",
      "description": "UTM Campaign for marketing tracking"
     },
     "path": {
      "type": "string",
      "maxLength": 300,
      "description": "Page path that was viewed, e.g. /shop/p/mug"
     },
     "referrer": {
      "type": "string",
      "maxLength": 500,
      "description": "document.referrer (only its host is kept)"
     }
    }
   },
   "CreateBankingDto": {
    "type": "object",
    "properties": {
     "business_id": {
      "type": "string",
      "example": "uuid-of-business"
     },
     "bank_name": {
      "type": "string"
     },
     "holder_name": {
      "type": "string"
     },
     "account_no": {
      "type": "string"
     },
     "ifsc": {
      "type": "string"
     },
     "type": {
      "type": "string"
     },
     "description": {
      "type": "string"
     },
     "phone": {
      "type": "string"
     },
     "email": {
      "type": "string"
     },
     "upi": {
      "type": "string"
     },
     "swift": {
      "type": "string"
     },
     "sort_code": {
      "type": "string"
     },
     "routing_no": {
      "type": "string"
     },
     "country": {
      "type": "object"
     }
    }
   },
   "UpdateBankingDto": {
    "type": "object",
    "properties": {
     "bank_name": {
      "type": "string",
      "example": "HDFC Bank"
     },
     "holder_name": {
      "type": "string",
      "example": "John Doe"
     },
     "account_no": {
      "type": "string",
      "example": "50100234567890"
     },
     "ifsc": {
      "type": "string",
      "example": "HDFC0001234"
     },
     "swift": {
      "type": "string",
      "example": "SWIFT123"
     },
     "upi": {
      "type": "string",
      "example": "john@upi"
     },
     "type": {
      "type": "string",
      "example": "savings"
     },
     "description": {
      "type": "string",
      "example": "Business primary account"
     },
     "phone": {
      "type": "string",
      "example": "+919876543210"
     },
     "email": {
      "type": "string",
      "example": "finance@bank.com"
     },
     "sort_code": {
      "type": "string",
      "example": "123456"
     },
     "routing_no": {
      "type": "string",
      "example": "123456789"
     },
     "country": {
      "type": "object",
      "example": 3
     },
     "business_id": {
      "type": "string",
      "example": "uuid-of-business"
     }
    },
    "required": [
     "bank_name",
     "holder_name",
     "account_no",
     "ifsc",
     "business_id"
    ]
   },
   "CheckoutItemDto": {
    "type": "object",
    "properties": {
     "product_id": {
      "type": "string",
      "description": "product.id (uuid)"
     },
     "quantity": {
      "type": "number",
      "minimum": 1,
      "maximum": 100
     }
    },
    "required": [
     "product_id",
     "quantity"
    ]
   },
   "CheckoutDto": {
    "type": "object",
    "properties": {
     "items": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/CheckoutItemDto"
      }
     },
     "firstname": {
      "type": "string",
      "maxLength": 100
     },
     "lastname": {
      "type": "string",
      "maxLength": 100
     },
     "email": {
      "type": "string",
      "maxLength": 255
     },
     "mobile": {
      "type": "string",
      "maxLength": 30
     },
     "payment_method": {
      "type": "string",
      "maxLength": 50,
      "default": "COD"
     }
    },
    "required": [
     "items"
    ]
   },
   "CreateProductDto": {
    "type": "object",
    "properties": {
     "channel_id": {
      "type": "string",
      "description": "Channel to list the product in (defaults to the token's channel). The caller must manage it."
     },
     "name": {
      "type": "string",
      "maxLength": 255
     },
     "slug": {
      "type": "string",
      "maxLength": 255,
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
      "example": "blue-mug"
     },
     "sku": {
      "type": "string",
      "maxLength": 100
     },
     "description": {
      "type": "string",
      "maxLength": 20000
     },
     "short_description": {
      "type": "string",
      "maxLength": 2000
     },
     "price": {
      "type": "string",
      "pattern": "^\\d{1,6}(\\.\\d{1,2})?$",
      "example": "249.50",
      "description": "Unit price, major units, max 2 decimals, below 1000000"
     },
     "quantity": {
      "type": "number",
      "nullable": true,
      "minimum": 0,
      "maximum": 1000000,
      "description": "Units in stock. Omit / null = stock not tracked (unlimited)."
     },
     "status": {
      "type": "string",
      "description": "Requested status; moderation may override it (never auto-publishes flagged text).",
      "enum": [
       "draft",
       "published",
       "sold",
       "archived"
      ]
     },
     "type": {
      "type": "string",
      "maxLength": 100
     },
     "cod": {
      "type": "boolean"
     },
     "shipping": {
      "type": "boolean"
     },
     "model": {
      "type": "string",
      "maxLength": 255
     },
     "keywords": {
      "type": "string",
      "maxLength": 2000
     }
    },
    "required": [
     "name"
    ]
   },
   "UpdateProductDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 255
     },
     "slug": {
      "type": "string",
      "maxLength": 255,
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
      "example": "blue-mug"
     },
     "sku": {
      "type": "string",
      "maxLength": 100
     },
     "description": {
      "type": "string",
      "maxLength": 20000
     },
     "short_description": {
      "type": "string",
      "maxLength": 2000
     },
     "price": {
      "type": "string",
      "pattern": "^\\d{1,6}(\\.\\d{1,2})?$",
      "example": "249.50",
      "description": "Unit price, major units, max 2 decimals, below 1000000"
     },
     "quantity": {
      "type": "number",
      "nullable": true,
      "minimum": 0,
      "maximum": 1000000,
      "description": "Units in stock. Omit / null = stock not tracked (unlimited)."
     },
     "status": {
      "type": "string",
      "description": "Requested status; moderation may override it (never auto-publishes flagged text).",
      "enum": [
       "draft",
       "published",
       "sold",
       "archived"
      ]
     },
     "type": {
      "type": "string",
      "maxLength": 100
     },
     "cod": {
      "type": "boolean"
     },
     "shipping": {
      "type": "boolean"
     },
     "model": {
      "type": "string",
      "maxLength": 255
     },
     "keywords": {
      "type": "string",
      "maxLength": 2000
     }
    }
   },
   "CreateOrderDto": {
    "type": "object",
    "properties": {
     "items": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/CheckoutItemDto"
      }
     },
     "firstname": {
      "type": "string",
      "maxLength": 100
     },
     "lastname": {
      "type": "string",
      "maxLength": 100
     },
     "email": {
      "type": "string",
      "maxLength": 255
     },
     "mobile": {
      "type": "string",
      "maxLength": 30
     },
     "payment_method": {
      "type": "string",
      "maxLength": 50,
      "enum": [
       "COD"
      ],
      "default": "COD"
     },
     "address_id": {
      "type": "string",
      "description": "One of the caller's own personal addresses (ship-to)"
     },
     "note": {
      "type": "string",
      "maxLength": 1000
     },
     "coupon_code": {
      "type": "string",
      "maxLength": 40,
      "description": "A store coupon code; the discount is computed server-side"
     }
    },
    "required": [
     "items"
    ]
   },
   "CancelOrderDto": {
    "type": "object",
    "properties": {
     "reason": {
      "type": "string",
      "maxLength": 1000
     }
    }
   },
   "UpdateOrderStatusDto": {
    "type": "object",
    "properties": {
     "status": {
      "type": "string",
      "enum": [
       "pending",
       "processing",
       "shipped",
       "delivered",
       "cancelled"
      ]
     },
     "comment": {
      "type": "string",
      "maxLength": 1000
     },
     "notify": {
      "type": "boolean",
      "description": "Notify the buyer"
     }
    },
    "required": [
     "status"
    ]
   },
   "CreateCouponDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 120,
      "example": "Welcome offer"
     },
     "value": {
      "type": "number",
      "minimum": 0,
      "maximum": 10000000,
      "description": "percent: 1–100. fixed: minor units (pence/cents)."
     },
     "currency": {
      "type": "string",
      "nullable": true,
      "minLength": 3,
      "maxLength": 3,
      "example": "GBP",
      "description": "For fixed amounts and minimums"
     },
     "min_order_minor": {
      "type": "number",
      "nullable": true,
      "minimum": 0,
      "maximum": 10000000,
      "description": "Minimum order, minor units"
     },
     "max_discount_minor": {
      "type": "number",
      "nullable": true,
      "minimum": 1,
      "maximum": 10000000,
      "description": "Cap on a percent discount, minor units"
     },
     "starts_at": {
      "type": "string",
      "nullable": true
     },
     "ends_at": {
      "type": "string",
      "nullable": true
     },
     "usage_limit": {
      "type": "number",
      "nullable": true,
      "minimum": 1,
      "maximum": 10000000,
      "description": "Total uses allowed"
     },
     "per_customer_limit": {
      "type": "number",
      "nullable": true,
      "minimum": 1,
      "maximum": 1000,
      "description": "Uses allowed per signed-in customer"
     },
     "code": {
      "type": "string",
      "pattern": "^[A-Za-z0-9][A-Za-z0-9_-]{2,39}$",
      "example": "WELCOME10",
      "description": "3–40 letters, digits, - or _ (stored upper-case)"
     },
     "kind": {
      "type": "string",
      "enum": [
       "percent",
       "fixed",
       "free_shipping"
      ]
     },
     "status": {
      "type": "string",
      "enum": [
       "active",
       "paused",
       "archived"
      ],
      "default": "active"
     }
    },
    "required": [
     "code",
     "kind"
    ]
   },
   "UpdateCouponDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 120,
      "example": "Welcome offer"
     },
     "value": {
      "type": "number",
      "minimum": 0,
      "maximum": 10000000,
      "description": "percent: 1–100. fixed: minor units (pence/cents)."
     },
     "currency": {
      "type": "string",
      "nullable": true,
      "minLength": 3,
      "maxLength": 3,
      "example": "GBP",
      "description": "For fixed amounts and minimums"
     },
     "min_order_minor": {
      "type": "number",
      "nullable": true,
      "minimum": 0,
      "maximum": 10000000,
      "description": "Minimum order, minor units"
     },
     "max_discount_minor": {
      "type": "number",
      "nullable": true,
      "minimum": 1,
      "maximum": 10000000,
      "description": "Cap on a percent discount, minor units"
     },
     "starts_at": {
      "type": "string",
      "nullable": true
     },
     "ends_at": {
      "type": "string",
      "nullable": true
     },
     "usage_limit": {
      "type": "number",
      "nullable": true,
      "minimum": 1,
      "maximum": 10000000,
      "description": "Total uses allowed"
     },
     "per_customer_limit": {
      "type": "number",
      "nullable": true,
      "minimum": 1,
      "maximum": 1000,
      "description": "Uses allowed per signed-in customer"
     },
     "code": {
      "type": "string",
      "pattern": "^[A-Za-z0-9][A-Za-z0-9_-]{2,39}$"
     },
     "kind": {
      "type": "string",
      "enum": [
       "percent",
       "fixed",
       "free_shipping"
      ]
     },
     "status": {
      "type": "string",
      "enum": [
       "active",
       "paused",
       "archived"
      ]
     }
    }
   },
   "ValidateCouponDto": {
    "type": "object",
    "properties": {
     "code": {
      "type": "string",
      "maxLength": 40,
      "example": "WELCOME10"
     },
     "subtotal_minor": {
      "type": "number",
      "minimum": 0,
      "maximum": 10000000,
      "description": "Cart subtotal, minor units"
     },
     "currency": {
      "type": "string",
      "minLength": 3,
      "maxLength": 3,
      "example": "GBP"
     }
    },
    "required": [
     "code",
     "subtotal_minor"
    ]
   },
   "DemoCompleteDto": {
    "type": "object",
    "properties": {
     "t": {
      "type": "string",
      "description": "Checkout capability token (the `t` from checkout_url).",
      "maxLength": 128
     },
     "outcome": {
      "type": "string",
      "enum": [
       "success",
       "fail",
       "challenge",
       "challenge_success",
       "challenge_fail"
      ]
     }
    },
    "required": [
     "t",
     "outcome"
    ]
   },
   "DemoChargeDto": {
    "type": "object",
    "properties": {
     "payment_id": {
      "type": "string",
      "description": "payments.id returned by POST /payments/create.",
      "maxLength": 64
     },
     "card_number": {
      "type": "string",
      "description": "4242424242424242 succeeds, 4000000000000002 declines, 4000002500003155 requires 3-D Secure.",
      "pattern": "^[0-9 -]{12,23}$"
     }
    },
    "required": [
     "payment_id",
     "card_number"
    ]
   },
   "CreatePaymentDto": {
    "type": "object",
    "properties": {
     "provider": {
      "type": "string",
      "description": "Defaults to \"stripe\" (served by \"demo\" while the demo gate is open).",
      "enum": [
       "razorpay",
       "stripe",
       "demo"
      ]
     },
     "amount": {
      "type": "number",
      "description": "Amount in MAJOR units (e.g. rupees / dollars). The service converts this to\nminor units (paise / cents) before storing and sending to the gateway.\nMax 2 decimal places for fiat.",
      "minimum": 1,
      "maximum": 999999.99
     },
     "currency": {
      "type": "string",
      "description": "ISO 4217 code of a currency the platform settles (GBP, USD, EUR, INR).\nIgnored for an order payment: the order's own currency is charged.",
      "enum": [
       "GBP",
       "USD",
       "EUR",
       "INR"
      ],
      "minLength": 3,
      "maxLength": 3
     },
     "customer_name": {
      "type": "string",
      "maxLength": 255
     },
     "customer_email": {
      "type": "string",
      "maxLength": 255
     },
     "customer_phone": {
      "type": "string",
      "maxLength": 255
     },
     "receipt": {
      "type": "string",
      "maxLength": 255
     },
     "metadata": {
      "type": "object"
     },
     "return_url": {
      "type": "string",
      "description": "Where the hosted (demo) checkout sends the browser afterwards, with\n`payment_id`, `status` and `provider` appended. Must be on an allowed\nfrontend origin. Ignored by the Stripe / Razorpay client-side flows.",
      "maxLength": 2048
     }
    },
    "required": [
     "amount"
    ]
   },
   "VerifyPaymentDto": {
    "type": "object",
    "properties": {
     "razorpay_order_id": {
      "type": "string"
     },
     "razorpay_payment_id": {
      "type": "string"
     },
     "razorpay_signature": {
      "type": "string"
     }
    },
    "required": [
     "razorpay_order_id",
     "razorpay_payment_id",
     "razorpay_signature"
    ]
   },
   "RecordInputDto": {
    "type": "object",
    "properties": {
     "values": {
      "type": "object",
      "description": "Field values by key (the list's columns); null clears a field on update",
      "example": {
       "c0": "Aisha Baker",
       "c1": "Hair consultation",
       "c4": "Confirmed"
      }
     }
    },
    "required": [
     "values"
    ]
   },
   "CreateMyAddressDto": {
    "type": "object",
    "properties": {
     "firstname": {
      "type": "string",
      "maxLength": 100
     },
     "lastname": {
      "type": "string",
      "maxLength": 100
     },
     "mobile": {
      "type": "string",
      "pattern": "^\\+?[0-9 ()-]{6,20}$",
      "example": "+447700900123"
     },
     "company": {
      "type": "string",
      "maxLength": 150
     },
     "landmark": {
      "type": "string",
      "maxLength": 255
     },
     "address_1": {
      "type": "string",
      "maxLength": 255
     },
     "address_2": {
      "type": "string",
      "maxLength": 255
     },
     "city": {
      "type": "string",
      "maxLength": 100
     },
     "pincode": {
      "type": "string",
      "pattern": "^[A-Za-z0-9 -]{2,20}$",
      "example": "SW1A 1AA"
     },
     "country": {
      "type": "number",
      "minimum": 1,
      "maximum": 2147483647,
      "description": "country.id (integer)"
     },
     "zone": {
      "type": "string",
      "maxLength": 100
     },
     "area": {
      "type": "string",
      "maxLength": 100
     },
     "type": {
      "type": "string",
      "enum": [
       "home",
       "work",
       "billing",
       "shipping",
       "other"
      ]
     }
    },
    "required": [
     "firstname",
     "address_1"
    ]
   },
   "UpdateMyAddressDto": {
    "type": "object",
    "properties": {
     "firstname": {
      "type": "string",
      "maxLength": 100
     },
     "lastname": {
      "type": "string",
      "maxLength": 100
     },
     "mobile": {
      "type": "string",
      "pattern": "^\\+?[0-9 ()-]{6,20}$",
      "example": "+447700900123"
     },
     "company": {
      "type": "string",
      "maxLength": 150
     },
     "landmark": {
      "type": "string",
      "maxLength": 255
     },
     "address_1": {
      "type": "string",
      "maxLength": 255
     },
     "address_2": {
      "type": "string",
      "maxLength": 255
     },
     "city": {
      "type": "string",
      "maxLength": 100
     },
     "pincode": {
      "type": "string",
      "pattern": "^[A-Za-z0-9 -]{2,20}$",
      "example": "SW1A 1AA"
     },
     "country": {
      "type": "number",
      "minimum": 1,
      "maximum": 2147483647,
      "description": "country.id (integer)"
     },
     "zone": {
      "type": "string",
      "maxLength": 100
     },
     "area": {
      "type": "string",
      "maxLength": 100
     },
     "type": {
      "type": "string",
      "enum": [
       "home",
       "work",
       "billing",
       "shipping",
       "other"
      ]
     }
    }
   },
   "ReviewDecisionDto": {
    "type": "object",
    "properties": {
     "decision": {
      "type": "string",
      "enum": [
       "approved",
       "rejected"
      ]
     },
     "reason": {
      "type": "string",
      "maxLength": 1000,
      "description": "Required when rejecting"
     }
    },
    "required": [
     "decision"
    ]
   },
   "ReviewDocumentDto": {
    "type": "object",
    "properties": {
     "status": {
      "type": "string",
      "enum": [
       "verified",
       "rejected"
      ]
     },
     "reason": {
      "type": "string",
      "maxLength": 1000,
      "description": "Required when rejecting"
     }
    },
    "required": [
     "status"
    ]
   },
   "UpdateSignupPolicyDto": {
    "type": "object",
    "properties": {
     "mode": {
      "type": "string",
      "enum": [
       "open",
       "restricted",
       "closed"
      ]
     },
     "allowed": {
      "example": [
       "@svayam.in",
       "partner@example.com"
      ],
      "description": "E-mail addresses and @domains allowed when restricted",
      "type": "array",
      "items": {
       "type": "string",
       "maxLength": 254
      }
     }
    },
    "required": [
     "mode"
    ]
   },
   "CreateBusinessDto": {
    "type": "object",
    "properties": {
     "tradename": {
      "type": "string",
      "example": "Acme Trading"
     },
     "legalname": {
      "type": "string",
      "example": "Acme Solutions Ltd"
     },
     "firstname": {
      "type": "string",
      "example": "Firstname"
     },
     "lastname": {
      "type": "string",
      "example": "Lastname"
     },
     "email": {
      "type": "string",
      "example": "business@example.com"
     },
     "mobile": {
      "type": "string",
      "example": "+919876543210"
     },
     "channel_id": {
      "type": "string",
      "example": "uuid-of-channel"
     },
     "logo": {
      "type": "string",
      "nullable": true,
      "example": "uuid-of-file"
     },
     "cover": {
      "type": "string",
      "nullable": true,
      "example": "uuid-of-cover-file"
     },
     "description": {
      "type": "string",
      "example": "Business description here"
     },
     "address_1": {
      "type": "string",
      "example": "123 Street Name"
     },
     "address_2": {
      "type": "string",
      "example": "Apartment 4B"
     },
     "city": {
      "type": "string",
      "example": "Indore"
     },
     "pincode": {
      "type": "string",
      "example": "452001"
     },
     "country": {
      "type": "number",
      "minimum": 1,
      "example": 1,
      "description": "Id of a row in the country collection"
     },
     "link": {
      "type": "string",
      "example": "https://example.com"
     },
     "keywords": {
      "type": "string",
      "example": "trading, monk, west"
     },
     "location": {
      "type": "object",
      "example": "Lat: 22.7, Long: 75.8"
     },
     "address_id": {
      "type": "string",
      "example": "uuid-of-address-record"
     },
     "banking_id": {
      "type": "object",
      "example": "id-of-banking-record"
     }
    },
    "required": [
     "tradename",
     "legalname",
     "email",
     "mobile"
    ]
   },
   "UpdateBusinessDto": {
    "type": "object",
    "properties": {
     "timezone": {
      "type": "string",
      "example": "Europe/London"
     },
     "fiscal_year_start": {
      "type": "number",
      "minimum": 1,
      "maximum": 12,
      "example": 4,
      "description": "Month the financial year starts (1 = January)"
     },
     "require_2fa": {
      "type": "boolean",
      "description": "Members must use 2-step verification (owner only; the owner is never locked out)"
     },
     "logo": {
      "type": "string",
      "nullable": true
     },
     "cover": {
      "type": "string",
      "nullable": true
     },
     "description": {
      "type": "string"
     },
     "address_1": {
      "type": "string"
     },
     "address_2": {
      "type": "string"
     },
     "city": {
      "type": "string"
     },
     "pincode": {
      "type": "string"
     },
     "country": {
      "type": "number",
      "minimum": 1
     },
     "link": {
      "type": "string"
     },
     "keywords": {
      "type": "string"
     },
     "location": {
      "type": "object"
     },
     "address_id": {
      "type": "string"
     },
     "banking_id": {
      "type": "object"
     }
    }
   },
   "CreateChannelDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "example": "My Online Store"
     },
     "description": {
      "type": "string",
      "example": "Official channel for our business"
     },
     "trademark_id": {
      "type": "number",
      "minimum": 1,
      "example": 3,
      "description": "Id of a trademark registered to a business you manage"
     },
     "category_id": {
      "type": "string",
      "example": "uuid-of-category"
     },
     "business_id": {
      "type": "string",
      "example": "uuid-of-business"
     },
     "link": {
      "type": "string",
      "example": "https://mywebsite.com"
     },
     "keywords": {
      "type": "string",
      "example": "keyword1, keyword2"
     }
    },
    "required": [
     "title"
    ]
   },
   "UpdateAddressDto": {
    "type": "object",
    "properties": {
     "business_id": {
      "type": "string",
      "example": "uuid-of-business"
     },
     "firstname": {
      "type": "string"
     },
     "lastname": {
      "type": "string"
     },
     "mobile": {
      "type": "string"
     },
     "company": {
      "type": "string"
     },
     "landmark": {
      "type": "string"
     },
     "address_1": {
      "type": "string"
     },
     "address_2": {
      "type": "string"
     },
     "city": {
      "type": "string"
     },
     "pincode": {
      "type": "string"
     },
     "country": {
      "type": "object"
     },
     "zone": {
      "type": "string"
     },
     "area": {
      "type": "string"
     },
     "location": {
      "type": "object"
     },
     "type": {
      "type": "string"
     },
     "file": {
      "type": "object",
      "description": "Upload proof image/pdf"
     }
    }
   },
   "UploadDocumentDto": {
    "type": "object",
    "properties": {
     "document_type": {
      "type": "number",
      "minimum": 1,
      "example": 1,
      "description": "document_type id (GET /business/documents/types)"
     },
     "document_no": {
      "type": "string",
      "maxLength": 100,
      "example": "U72900KA2021PTC000000"
     }
    },
    "required": [
     "document_type"
    ]
   },
   "CreateChangeRequestDto": {
    "type": "object",
    "properties": {
     "field": {
      "type": "string",
      "enum": [
       "tradename",
       "legalname",
       "email",
       "mobile",
       "address_1",
       "address_2",
       "city",
       "pincode",
       "country",
       "entity_type",
       "registration_number",
       "tax_number",
       "website",
       "signatory"
      ]
     },
     "new_value": {
      "type": "string",
      "maxLength": 1000,
      "example": "Acme Retail Pvt Ltd",
      "description": "The value asked for. signatory: JSON {\"name\",\"title\",\"email\",\"phone\"}; entity_type: one of the verification kinds."
     },
     "reason": {
      "type": "string",
      "maxLength": 1000,
      "example": "Company renamed after board resolution"
     },
     "document_id": {
      "type": "number",
      "minimum": 1,
      "description": "Supporting document (a document of this business)"
     }
    },
    "required": [
     "field",
     "new_value",
     "reason"
    ]
   },
   "ChangeRequestItemDto": {
    "type": "object",
    "properties": {
     "field": {
      "type": "string",
      "enum": [
       "tradename",
       "legalname",
       "email",
       "mobile",
       "address_1",
       "address_2",
       "city",
       "pincode",
       "country",
       "entity_type",
       "registration_number",
       "tax_number",
       "website",
       "signatory"
      ]
     },
     "new_value": {
      "type": "string",
      "maxLength": 1000,
      "example": "12345678",
      "description": "The value asked for (as in CreateChangeRequestDto.new_value)"
     }
    },
    "required": [
     "field",
     "new_value"
    ]
   },
   "CreateChangeRequestsDto": {
    "type": "object",
    "properties": {
     "changes": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/ChangeRequestItemDto"
      }
     },
     "reason": {
      "type": "string",
      "maxLength": 1000,
      "example": "Company number typo"
     },
     "document_id": {
      "type": "number",
      "minimum": 1,
      "description": "Supporting document (a document of this business)"
     }
    },
    "required": [
     "changes",
     "reason"
    ]
   },
   "CloseBusinessDto": {
    "type": "object",
    "properties": {
     "confirm": {
      "type": "string",
      "maxLength": 255,
      "description": "Type the business tradename (or legal name) to confirm"
     },
     "reason": {
      "type": "string",
      "maxLength": 1000
     }
    },
    "required": [
     "confirm"
    ]
   },
   "InitiateTransferDto": {
    "type": "object",
    "properties": {
     "email": {
      "type": "string",
      "maxLength": 254,
      "example": "new-owner@example.com",
      "description": "Email of the account that will own the business"
     }
    },
    "required": [
     "email"
    ]
   },
   "TrackVisitDto": {
    "type": "object",
    "properties": {
     "device_id": {
      "type": "string",
      "example": "device-id-1234"
     },
     "domain": {
      "type": "string",
      "example": "my-store.com"
     },
     "page": {
      "type": "string",
      "example": "/products/iphone-15"
     }
    }
   },
   "SecurityAlertsDto": {
    "type": "object",
    "properties": {
     "newdev": {
      "type": "boolean",
      "description": "Sign-in from a new device"
     },
     "pw": {
      "type": "boolean",
      "description": "Password / email changes"
     },
     "mfa": {
      "type": "boolean",
      "description": "Two-factor changes"
     },
     "fail": {
      "type": "boolean",
      "description": "Failed / blocked sign-ins"
     },
     "export": {
      "type": "boolean",
      "description": "Data export requests"
     }
    }
   },
   "UpdatePreferencesDto": {
    "type": "object",
    "properties": {
     "language": {
      "type": "number",
      "nullable": true,
      "minimum": 1,
      "description": "language.id (null clears it)"
     },
     "timezone": {
      "type": "string",
      "maxLength": 64,
      "example": "Europe/London"
     },
     "security_alerts": {
      "$ref": "#/components/schemas/SecurityAlertsDto"
     },
     "theme": {
      "type": "string",
      "enum": [
       "light",
       "dark",
       "system"
      ]
     },
     "call_quality": {
      "type": "boolean",
      "description": "Share call-quality numbers (connection type, delay, jitter, loss, codec, duration) after a call. No addresses or content. Default on."
     },
     "sound": {
      "type": "boolean"
     },
     "haptics": {
      "type": "boolean"
     },
     "push": {
      "type": "boolean"
     },
     "email": {
      "type": "boolean"
     },
     "sms": {
      "type": "boolean"
     }
    }
   },
   "RecoveryEmailDto": {
    "type": "object",
    "properties": {
     "email": {
      "type": "string",
      "maxLength": 254,
      "example": "me@example.org"
     }
    },
    "required": [
     "email"
    ]
   },
   "VerifyRecoveryEmailDto": {
    "type": "object",
    "properties": {
     "code": {
      "type": "string",
      "pattern": "^\\d{6}$",
      "example": "123456"
     }
    },
    "required": [
     "code"
    ]
   },
   "CreateDataRequestDto": {
    "type": "object",
    "properties": {
     "type": {
      "type": "string",
      "enum": [
       "export",
       "delete",
       "rectify",
       "restrict",
       "object",
       "question"
      ]
     },
     "details": {
      "type": "string",
      "maxLength": 2000
     },
     "scope": {
      "type": "string",
      "enum": [
       "account",
       "partial"
      ]
     }
    },
    "required": [
     "type"
    ]
   },
   "ConsentDecisionDto": {
    "type": "object",
    "properties": {
     "kind": {
      "type": "string",
      "enum": [
       "terms",
       "privacy",
       "marketing"
      ]
     },
     "granted": {
      "type": "boolean",
      "description": "true = agree / opt in, false = opt out"
     },
     "version": {
      "type": "string",
      "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,31}$",
      "description": "The document version the person was shown (GET /users/me/consent → versions). A different version is refused with 409.",
      "example": "3.0"
     }
    },
    "required": [
     "kind",
     "granted",
     "version"
    ]
   },
   "RecordConsentDto": {
    "type": "object",
    "properties": {
     "decisions": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/ConsentDecisionDto"
      }
     },
     "source": {
      "type": "string",
      "enum": [
       "signup",
       "settings"
      ],
      "description": "signup only on a new account with no consent recorded yet; default settings"
     }
    },
    "required": [
     "decisions"
    ]
   },
   "CreateProfileDto": {
    "type": "object",
    "properties": {
     "firstname": {
      "type": "string",
      "example": "Riya"
     },
     "lastname": {
      "type": "string",
      "example": "Goyal"
     },
     "username": {
      "type": "string",
      "example": "riya123"
     },
     "avatar": {
      "type": "string",
      "example": "https://example.com/photo.jpg"
     },
     "language": {
      "type": "string"
     },
     "user_group": {
      "type": "string"
     },
     "user_category": {
      "type": "string"
     },
     "gender": {
      "type": "string"
     },
     "date_of_birth": {
      "type": "string",
      "example": "1995-04-21"
     },
     "bio": {
      "type": "string"
     },
     "description": {
      "type": "string"
     },
     "link": {
      "type": "string"
     },
     "custom_link": {
      "type": "string"
     },
     "blood_group": {
      "type": "string"
     },
     "location": {
      "type": "string",
      "example": "51.523,-0.078",
      "description": "Home area \"lat,lng\" for people nearby (stored rounded to ~1 km)"
     },
     "place": {
      "type": "string",
      "maxLength": 120,
      "example": "Shoreditch, London"
     }
    },
    "required": [
     "date_of_birth"
    ]
   },
   "CreateKycDto": {
    "type": "object",
    "properties": {
     "active_profile_id": {
      "type": "string",
      "description": "Profile to file this KYC under (must be yours)"
     },
     "legalname": {
      "type": "string",
      "example": "John Doe"
     },
     "fathername": {
      "type": "string",
      "example": "Richard Doe"
     },
     "mothername": {
      "type": "string",
      "example": "Jane Doe"
     },
     "tax_id_number": {
      "type": "string",
      "example": "ABCDE1234F"
     },
     "id_number": {
      "type": "string",
      "example": "ID-987654321"
     },
     "nationality": {
      "type": "string",
      "example": "Indian"
     },
     "citizenship": {
      "type": "string",
      "example": "India"
     }
    },
    "required": [
     "legalname"
    ]
   },
   "UpsertProfileDetailDto": {
    "type": "object",
    "properties": {
     "active_profile_id": {
      "type": "string",
      "description": "Profile to update (must be yours)"
     },
     "zodiac": {
      "type": "string"
     },
     "clan": {
      "type": "string"
     },
     "mangal": {
      "type": "boolean"
     },
     "birth_place": {
      "type": "object"
     },
     "height": {
      "type": "number"
     },
     "weight": {
      "type": "number"
     },
     "body_type": {
      "type": "string"
     },
     "current_relationship": {
      "type": "string"
     },
     "relationship_intent": {
      "type": "string"
     },
     "current_children": {
      "type": "boolean"
     },
     "children_intent": {
      "type": "boolean"
     },
     "native_language": {
      "type": "string"
     },
     "languages": {
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "orientation": {
      "type": "string"
     },
     "horoscope": {
      "type": "string"
     }
    }
   },
   "UpsertProfilePrivacyDto": {
    "type": "object",
    "properties": {
     "active_profile_id": {
      "type": "string",
      "description": "Profile to update (must be yours)"
     },
     "martial_status": {
      "type": "object"
     },
     "orientation": {
      "type": "object"
     },
     "religion": {
      "type": "object"
     },
     "age": {
      "type": "object"
     },
     "height": {
      "type": "object"
     },
     "current_relationship_status": {
      "type": "object"
     },
     "location": {
      "type": "object"
     }
    }
   },
   "CheckUsernameDto": {
    "type": "object",
    "properties": {
     "username": {
      "type": "string",
      "example": "riya123"
     }
    },
    "required": [
     "username"
    ]
   },
   "UpdateUserDto": {
    "type": "object",
    "properties": {
     "firstname": {
      "type": "string",
      "example": "Riya"
     },
     "lastname": {
      "type": "string",
      "example": "Goyal"
     },
     "mobile": {
      "type": "string",
      "pattern": "^[0-9]{10}$",
      "example": "9999999999"
     },
     "username": {
      "type": "string",
      "example": "riya123"
     },
     "avatar": {
      "type": "string",
      "example": "https://example.com/photo.jpg"
     },
     "language": {
      "type": "string"
     },
     "user_group": {
      "type": "string"
     },
     "user_category": {
      "type": "string"
     },
     "gender": {
      "type": "string"
     },
     "date_of_birth": {
      "type": "string"
     },
     "bio": {
      "type": "string"
     },
     "description": {
      "type": "string"
     },
     "link": {
      "type": "string"
     },
     "custom_link": {
      "type": "string"
     },
     "blood_group": {
      "type": "string"
     },
     "location": {
      "type": "string",
      "example": "51.523,-0.078",
      "description": "Home area \"lat,lng\" for people nearby (stored rounded to ~1 km)"
     },
     "place": {
      "type": "string",
      "maxLength": 120,
      "example": "Shoreditch, London"
     }
    }
   },
   "CreateTrademarkDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "example": "My Brand Name"
     },
     "class": {
      "type": "number",
      "minimum": 1,
      "maximum": 45,
      "example": 9
     },
     "description": {
      "type": "string",
      "example": "Trademark description here"
     },
     "proprietor": {
      "type": "string",
      "example": "John Doe"
     },
     "business_id": {
      "type": "string",
      "example": "uuid-of-business"
     },
     "application_no": {
      "type": "string",
      "example": "APP123456"
     },
     "start_date": {
      "type": "string",
      "example": "2026-05-25"
     },
     "channel_id": {
      "type": "string",
      "nullable": true,
      "example": "uuid-of-channel"
     },
     "country": {
      "type": "object",
      "example": 3
     },
     "logo": {
      "type": "string",
      "nullable": true,
      "example": null
     }
    },
    "required": [
     "title",
     "business_id"
    ]
   },
   "UpdateTrademarkDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "example": "My Brand Name"
     },
     "class": {
      "type": "number",
      "minimum": 1,
      "maximum": 45,
      "example": 9
     },
     "description": {
      "type": "string",
      "example": "Trademark description here"
     },
     "proprietor": {
      "type": "string",
      "example": "John Doe"
     },
     "business_id": {
      "type": "string",
      "example": "uuid-of-business"
     },
     "application_no": {
      "type": "string",
      "example": "APP123456"
     },
     "start_date": {
      "type": "string",
      "example": "2026-05-25"
     },
     "channel_id": {
      "type": "string",
      "nullable": true,
      "example": "uuid-of-channel"
     },
     "country": {
      "type": "object",
      "example": 3
     },
     "logo": {
      "type": "string",
      "nullable": true,
      "example": null
     }
    }
   },
   "CreateAddressDto": {
    "type": "object",
    "properties": {
     "business_id": {
      "type": "string",
      "example": "uuid-of-business"
     },
     "firstname": {
      "type": "string"
     },
     "lastname": {
      "type": "string"
     },
     "mobile": {
      "type": "string"
     },
     "company": {
      "type": "string"
     },
     "landmark": {
      "type": "string"
     },
     "address_1": {
      "type": "string"
     },
     "address_2": {
      "type": "string"
     },
     "city": {
      "type": "string"
     },
     "pincode": {
      "type": "string"
     },
     "country": {
      "type": "object"
     },
     "zone": {
      "type": "string"
     },
     "area": {
      "type": "string"
     },
     "location": {
      "type": "object"
     },
     "type": {
      "type": "string"
     },
     "file": {
      "type": "object",
      "description": "Upload proof image/pdf"
     }
    }
   },
   "CreatePostDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 255,
      "description": "Title of the post"
     },
     "description": {
      "type": "string",
      "description": "Main description/content of the post"
     },
     "sub_description": {
      "type": "string",
      "description": "Sub description of the post"
     },
     "meta_title": {
      "type": "string",
      "maxLength": 255,
      "description": "Meta title for SEO"
     },
     "meta_description": {
      "type": "string",
      "description": "Meta description for SEO"
     },
     "meta_keywords": {
      "type": "string",
      "maxLength": 255,
      "description": "Meta keywords for SEO"
     },
     "location": {
      "type": "string",
      "maxLength": 255,
      "description": "Coordinates as \"lat,lng\", stored rounded to about 110 m. Leave it out when unknown: no default city is ever filled in, and a post with no place of its own gets `location` null (or its channel business city, marked `source: \"channel\"`)."
     },
     "place": {
      "type": "string",
      "maxLength": 120,
      "description": "Where it was posted, for people (\"Shoreditch, London\")"
     },
     "parent_id": {
      "type": "string",
      "description": "Parent Post ID if it is a reply or sub-post"
     },
     "download_link": {
      "type": "string",
      "maxLength": 255,
      "description": "Download link if applicable"
     },
     "project_link": {
      "type": "string",
      "maxLength": 255,
      "description": "Project link if applicable"
     },
     "requires": {
      "type": "string",
      "maxLength": 255,
      "description": "Requirements or prerequisites"
     },
     "transcript": {
      "type": "string",
      "description": "Transcript text if video/audio"
     },
     "attribute": {
      "type": "string",
      "description": "Post attributes/tags"
     },
     "type": {
      "type": "string",
      "maxLength": 255,
      "description": "Post type (e.g., post, article, video). campaign/event/job/fundraiser are reserved."
     },
     "group_id": {
      "type": "string",
      "description": "Post into a community group (members only; never public)"
     },
     "public": {
      "type": "boolean",
      "description": "Is this post public?",
      "default": true
     },
     "fee": {
      "type": "object",
      "description": "Fee amount if applicable"
     },
     "topic": {
      "type": "string",
      "description": "Topic ID"
     },
     "hashtags": {
      "type": "string",
      "maxLength": 255,
      "description": "Hashtags (comma-separated string)"
     },
     "downloads": {
      "type": "object",
      "description": "Downloads count"
     },
     "users": {
      "type": "string",
      "description": "Users (comma-separated UUIDs)"
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published"
      ],
      "description": "Post status: draft or published (moderation may hold it)"
     },
     "published": {
      "type": "string",
      "description": "Published date/time"
     },
     "active_profile_id": {
      "type": "string",
      "description": "Profile to post as (must belong to the caller; defaults to the session profile)"
     }
    },
    "required": [
     "title"
    ]
   },
   "UpdatePostDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 255,
      "description": "Title of the post"
     },
     "description": {
      "type": "string",
      "description": "Main description/content of the post"
     },
     "sub_description": {
      "type": "string",
      "description": "Sub description of the post"
     },
     "meta_title": {
      "type": "string",
      "maxLength": 255,
      "description": "Meta title for SEO"
     },
     "meta_description": {
      "type": "string",
      "description": "Meta description for SEO"
     },
     "meta_keywords": {
      "type": "string",
      "maxLength": 255,
      "description": "Meta keywords for SEO"
     },
     "location": {
      "type": "string",
      "maxLength": 255,
      "description": "Coordinates as \"lat,lng\", stored rounded to about 110 m. Leave it out when unknown: no default city is ever filled in, and a post with no place of its own gets `location` null (or its channel business city, marked `source: \"channel\"`)."
     },
     "place": {
      "type": "string",
      "maxLength": 120,
      "description": "Where it was posted, for people (\"Shoreditch, London\")"
     },
     "parent_id": {
      "type": "string",
      "description": "Parent Post ID if it is a reply or sub-post"
     },
     "download_link": {
      "type": "string",
      "maxLength": 255,
      "description": "Download link if applicable"
     },
     "project_link": {
      "type": "string",
      "maxLength": 255,
      "description": "Project link if applicable"
     },
     "requires": {
      "type": "string",
      "maxLength": 255,
      "description": "Requirements or prerequisites"
     },
     "transcript": {
      "type": "string",
      "description": "Transcript text if video/audio"
     },
     "attribute": {
      "type": "string",
      "description": "Post attributes/tags"
     },
     "type": {
      "type": "string",
      "maxLength": 255,
      "description": "Post type (e.g., post, article, video). campaign/event/job/fundraiser are reserved."
     },
     "group_id": {
      "type": "string",
      "description": "Post into a community group (members only; never public)"
     },
     "public": {
      "type": "boolean",
      "description": "Is this post public?",
      "default": true
     },
     "fee": {
      "type": "object",
      "description": "Fee amount if applicable"
     },
     "topic": {
      "type": "string",
      "description": "Topic ID"
     },
     "hashtags": {
      "type": "string",
      "maxLength": 255,
      "description": "Hashtags (comma-separated string)"
     },
     "downloads": {
      "type": "object",
      "description": "Downloads count"
     },
     "users": {
      "type": "string",
      "description": "Users (comma-separated UUIDs)"
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published"
      ],
      "description": "Post status: draft or published (moderation may hold it)"
     },
     "published": {
      "type": "string",
      "description": "Published date/time"
     },
     "active_profile_id": {
      "type": "string",
      "description": "Profile to post as (must belong to the caller; defaults to the session profile)"
     }
    }
   },
   "DonateDto": {
    "type": "object",
    "properties": {
     "amount": {
      "type": "number",
      "minimum": 1,
      "maximum": 10000000
     },
     "message": {
      "type": "string",
      "maxLength": 255
     },
     "name": {
      "type": "string",
      "maxLength": 255
     },
     "active_profile_id": {
      "type": "string"
     },
     "anonymous": {
      "type": "boolean"
     }
    },
    "required": [
     "amount",
     "message"
    ]
   },
   "CreateCampaignDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string"
     },
     "description": {
      "type": "string"
     },
     "demand": {
      "type": "string",
      "pattern": "^\\d{1,18}(\\.\\d{1,2})?$"
     },
     "category": {
      "type": "string"
     },
     "category_id": {
      "type": "string"
     },
     "post_id": {
      "type": "string"
     },
     "status": {
      "type": "string"
     },
     "verified": {
      "type": "string"
     },
     "active_profile_id": {
      "type": "string"
     },
     "institution_id": {
      "type": "string"
     },
     "location": {
      "type": "string",
      "example": "28.6139,77.2090",
      "description": "Coordinates as \"latitude,longitude\". Stored as a PostGIS point; place names are not geocoded."
     }
    },
    "required": [
     "title",
     "description"
    ]
   },
   "UpdateCampaignDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string"
     },
     "description": {
      "type": "string"
     },
     "demand": {
      "type": "string",
      "pattern": "^\\d{1,18}(\\.\\d{1,2})?$"
     },
     "category": {
      "type": "string"
     },
     "category_id": {
      "type": "string"
     },
     "post_id": {
      "type": "string"
     },
     "status": {
      "type": "string"
     },
     "verified": {
      "type": "string"
     },
     "institution_id": {
      "type": "string"
     },
     "location": {
      "type": "string",
      "example": "28.6139,77.2090",
      "description": "Coordinates as \"latitude,longitude\". Stored as a PostGIS point; place names are not geocoded. Send an empty string to clear it."
     },
     "media": {
      "type": "object",
      "description": "Existing image ids to keep on update, e.g. [490,491]. Images not listed are removed."
     },
     "keep_images": {
      "type": "object",
      "description": "Alias of `media`: existing image ids to keep on update."
     }
    }
   },
   "CreateCampaignUpdateDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 255
     },
     "description": {
      "type": "string"
     },
     "file": {
      "type": "string"
     },
     "status": {
      "type": "number",
      "minimum": 1
     }
    },
    "required": [
     "title"
    ]
   },
   "UpdateCampaignUpdateDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 255
     },
     "description": {
      "type": "string"
     },
     "file": {
      "type": "string"
     },
     "status": {
      "type": "number",
      "minimum": 1
     }
    }
   },
   "WithdrawDonationDto": {
    "type": "object",
    "properties": {
     "campaign_id": {
      "type": "number",
      "description": "Campaign ID to withdraw from (Integer)"
     },
     "amount": {
      "type": "number",
      "maximum": 99999.99,
      "minimum": 1,
      "description": "Amount to withdraw, in major units (e.g. rupees) with at most 2 decimals. Must be > 0 and <= 99999.99."
     },
     "description": {
      "type": "string",
      "maxLength": 2000,
      "description": "Description for the withdrawal"
     },
     "file_id": {
      "type": "number",
      "minimum": 1,
      "description": "Proof document: id of a file record (integer) you own"
     },
     "banking_id": {
      "type": "number",
      "minimum": 1,
      "description": "Bank account (banking.id) to pay out to. Required when you have more than one personal bank account."
     }
    },
    "required": [
     "amount",
     "description"
    ]
   },
   "CreateEventDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "minLength": 3,
      "maxLength": 255,
      "example": "Sunburn Arena ft. Alan Walker"
     },
     "start_at": {
      "type": "string",
      "example": "2026-11-02T18:30:00+05:30",
      "description": "ISO-8601 with offset. Required. Stored verbatim."
     },
     "end_at": {
      "type": "string",
      "example": "2026-11-03T00:00:00+05:30"
     },
     "summary": {
      "type": "string",
      "maxLength": 255
     },
     "description": {
      "type": "string"
     },
     "timezone": {
      "type": "string",
      "maxLength": 255,
      "example": "Asia/Kolkata"
     },
     "duration_text": {
      "type": "string",
      "maxLength": 255,
      "example": "4 hours"
     },
     "all_day": {
      "type": "string",
      "example": "false"
     },
     "venue_name": {
      "type": "string",
      "maxLength": 255
     },
     "address": {
      "type": "string"
     },
     "city": {
      "type": "string",
      "maxLength": 255
     },
     "state": {
      "type": "string",
      "maxLength": 255
     },
     "country": {
      "type": "string",
      "maxLength": 255
     },
     "latitude": {
      "type": "string",
      "example": "28.4595"
     },
     "longitude": {
      "type": "string",
      "example": "77.0266"
     },
     "is_online": {
      "type": "string",
      "example": "false"
     },
     "online_url": {
      "type": "string"
     },
     "category_id": {
      "type": "string",
      "description": "category uuid"
     },
     "tags": {
      "type": "object",
      "description": "CSV \"a,b\" or JSON array"
     },
     "price_from": {
      "type": "string",
      "example": "1499"
     },
     "price_to": {
      "type": "string",
      "example": "4999"
     },
     "currency": {
      "type": "string",
      "maxLength": 255,
      "example": "INR"
     },
     "capacity": {
      "type": "string",
      "example": "5000"
     },
     "age_limit": {
      "type": "string",
      "maxLength": 255
     },
     "organizer_name": {
      "type": "string",
      "maxLength": 255
     },
     "highlights": {
      "type": "object",
      "description": "JSON array of strings"
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published"
      ]
     },
     "active_profile_id": {
      "type": "string",
      "description": "authoring profile uuid"
     }
    },
    "required": [
     "title",
     "start_at"
    ]
   },
   "UpdateEventDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "minLength": 3,
      "maxLength": 255
     },
     "start_at": {
      "type": "string"
     },
     "end_at": {
      "type": "string"
     },
     "summary": {
      "type": "string",
      "maxLength": 255
     },
     "description": {
      "type": "string"
     },
     "timezone": {
      "type": "string",
      "maxLength": 255
     },
     "duration_text": {
      "type": "string",
      "maxLength": 255
     },
     "all_day": {
      "type": "string"
     },
     "venue_name": {
      "type": "string",
      "maxLength": 255
     },
     "address": {
      "type": "string"
     },
     "city": {
      "type": "string",
      "maxLength": 255
     },
     "state": {
      "type": "string",
      "maxLength": 255
     },
     "country": {
      "type": "string",
      "maxLength": 255
     },
     "latitude": {
      "type": "string"
     },
     "longitude": {
      "type": "string"
     },
     "is_online": {
      "type": "string"
     },
     "online_url": {
      "type": "string"
     },
     "category_id": {
      "type": "string"
     },
     "tags": {
      "type": "object"
     },
     "price_from": {
      "type": "string"
     },
     "price_to": {
      "type": "string"
     },
     "currency": {
      "type": "string",
      "maxLength": 255
     },
     "capacity": {
      "type": "string"
     },
     "age_limit": {
      "type": "string",
      "maxLength": 255
     },
     "organizer_name": {
      "type": "string",
      "maxLength": 255
     },
     "highlights": {
      "type": "object"
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published",
       "cancelled",
       "postponed"
      ]
     },
     "active_profile_id": {
      "type": "string"
     }
    }
   },
   "InviteMemberDto": {
    "type": "object",
    "properties": {
     "email": {
      "type": "string",
      "example": "member@example.com"
     },
     "permission": {
      "type": "string",
      "enum": [
       "admin",
       "manager",
       "editor",
       "view"
      ],
      "example": "manager"
     }
    },
    "required": [
     "email",
     "permission"
    ]
   },
   "UpdateMemberDto": {
    "type": "object",
    "properties": {
     "permission": {
      "type": "string",
      "enum": [
       "admin",
       "manager",
       "editor",
       "view"
      ]
     },
     "status": {
      "type": "string",
      "enum": [
       "active",
       "suspended"
      ]
     }
    }
   },
   "ActForOwnerDto": {
    "type": "object",
    "properties": {
     "days": {
      "type": "number",
      "minimum": 1,
      "maximum": 365,
      "example": 90
     },
     "scopes": {
      "type": "array",
      "enum": [
       "billing",
       "developer",
       "profile"
      ],
      "description": "What they may do for the owner (default: all)",
      "example": [
       "billing",
       "developer",
       "profile"
      ],
      "items": {
       "type": "string",
       "enum": [
        "billing",
        "developer",
        "profile"
       ]
      }
     },
     "note": {
      "type": "string",
      "maxLength": 200,
      "example": "Runs billing while I travel"
     }
    }
   },
   "CvUploadDto": {
    "type": "object",
    "properties": {
     "filename": {
      "type": "string",
      "description": "The file's name as picked (shown to staff; its extension must fit `content_type`).",
      "minLength": 1,
      "maxLength": 200
     },
     "content_type": {
      "type": "string",
      "description": "application/pdf, application/msword or the .docx type.",
      "enum": [
       "application/pdf",
       "application/msword",
       "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
      ]
     },
     "size": {
      "type": "number",
      "description": "Exact size in bytes (1 to 5 MB). The upload URL accepts only this size.",
      "minimum": 1,
      "maximum": 5242880
     }
    },
    "required": [
     "filename",
     "content_type",
     "size"
    ]
   },
   "WebApplyDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
     },
     "email": {
      "type": "string",
      "maxLength": 254
     },
     "phone": {
      "type": "string",
      "maxLength": 32
     },
     "phone_country": {
      "type": "string",
      "enum": [
       "GB",
       "US",
       "IE",
       "IN"
      ]
     },
     "cover_note": {
      "type": "string",
      "description": "A short note to the employer.",
      "maxLength": 5000
     },
     "link": {
      "type": "string",
      "description": "One link (portfolio, LinkedIn, GitHub). https only.",
      "maxLength": 500
     },
     "cv_token": {
      "type": "string",
      "description": "From POST …/cv-upload, after the file was PUT to its upload URL.",
      "maxLength": 2048
     },
     "consent": {
      "type": "boolean",
      "description": "The applicant agrees that the employer processes this application (UK\nGDPR art. 6(1)(b)/(f)). Must be true: an application without it is refused."
     },
     "consent_text": {
      "type": "string",
      "description": "The wording shown next to the consent box (kept as evidence).",
      "maxLength": 1000
     },
     "page_url": {
      "type": "string",
      "description": "Page the form was sent from.",
      "maxLength": 500
     },
     "captcha_token": {
      "type": "string",
      "description": "Cloudflare Turnstile token, when the channel turns on settings › protection › forms_captcha.",
      "maxLength": 2048
     },
     "website": {
      "type": "string",
      "description": "Honeypot: render it hidden and leave it empty.",
      "maxLength": 500
     }
    },
    "required": [
     "name",
     "email",
     "consent"
    ]
   },
   "UpdateWebApplicationDto": {
    "type": "object",
    "properties": {
     "status": {
      "type": "string",
      "enum": [
       "received",
       "reviewing",
       "interview",
       "offer",
       "hired",
       "not_selected"
      ]
     }
    },
    "required": [
     "status"
    ]
   },
   "CreateJobDto": {
    "type": "object",
    "properties": {
     "active_profile_id": {
      "type": "string"
     },
     "title": {
      "type": "string",
      "maxLength": 255
     },
     "description": {
      "type": "string"
     },
     "sub_description": {
      "type": "string"
     },
     "hashtags": {
      "type": "string",
      "maxLength": 255
     },
     "latitude": {
      "type": "number"
     },
     "longitude": {
      "type": "number"
     },
     "category_id": {
      "type": "string"
     },
     "company_name": {
      "type": "string",
      "maxLength": 255
     },
     "job_location": {
      "type": "string",
      "maxLength": 255
     },
     "location_type": {
      "type": "string",
      "maxLength": 60
     },
     "job_type": {
      "type": "string",
      "maxLength": 60
     },
     "experience_level": {
      "type": "string",
      "maxLength": 60
     },
     "salary_min": {
      "type": "number",
      "minimum": 0
     },
     "salary_max": {
      "type": "number",
      "minimum": 0
     },
     "requirements": {
      "type": "string",
      "maxLength": 255
     },
     "application_link": {
      "type": "string",
      "maxLength": 255
     },
     "application_email": {
      "type": "string"
     },
     "deadline": {
      "type": "string"
     },
     "openings": {
      "type": "number",
      "minimum": 1
     },
     "hiring_status": {
      "type": "string",
      "enum": [
       "open",
       "closed",
       "paused",
       "filled"
      ]
     }
    },
    "required": [
     "title",
     "description",
     "application_link"
    ]
   },
   "UpdateJobDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 255
     },
     "description": {
      "type": "string"
     },
     "sub_description": {
      "type": "string"
     },
     "hashtags": {
      "type": "string",
      "maxLength": 255
     },
     "latitude": {
      "type": "number"
     },
     "longitude": {
      "type": "number"
     },
     "category_id": {
      "type": "string"
     },
     "company_name": {
      "type": "string",
      "maxLength": 255
     },
     "job_location": {
      "type": "string",
      "maxLength": 255
     },
     "location_type": {
      "type": "string",
      "maxLength": 60
     },
     "job_type": {
      "type": "string",
      "maxLength": 60
     },
     "experience_level": {
      "type": "string",
      "maxLength": 60
     },
     "salary_min": {
      "type": "number",
      "minimum": 0
     },
     "salary_max": {
      "type": "number",
      "minimum": 0
     },
     "requirements": {
      "type": "string",
      "maxLength": 255
     },
     "application_link": {
      "type": "string",
      "maxLength": 255
     },
     "application_email": {
      "type": "string"
     },
     "deadline": {
      "type": "string"
     },
     "openings": {
      "type": "number",
      "minimum": 1
     },
     "hiring_status": {
      "type": "string",
      "enum": [
       "open",
       "closed",
       "paused",
       "filled"
      ]
     },
     "archived": {
      "type": "string",
      "enum": [
       "true",
       "false",
       "1",
       "0"
      ]
     }
    }
   },
   "UpdateApplicationStatusDto": {
    "type": "object",
    "properties": {
     "status": {
      "type": "string",
      "maxLength": 120
     },
     "status_id": {
      "type": "number",
      "minimum": 1
     }
    }
   },
   "CreateStoryDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 255
     },
     "description": {
      "type": "string"
     },
     "url": {
      "type": "string",
      "maxLength": 255
     },
     "status": {
      "type": "string",
      "enum": [
       "published",
       "draft",
       "archived",
       "expired"
      ]
     },
     "file_id": {
      "type": "number"
     },
     "active_profile_id": {
      "type": "string"
     },
     "location": {
      "type": "string",
      "description": "\"lat,lng\" where it was posted (stored rounded to ~110 m).",
      "maxLength": 64
     },
     "place": {
      "type": "string",
      "maxLength": 120
     }
    }
   },
   "CreateStoryCommentDto": {
    "type": "object",
    "properties": {
     "content": {
      "type": "string",
      "maxLength": 255
     },
     "active_profile_id": {
      "type": "string"
     }
    },
    "required": [
     "content"
    ]
   },
   "AppKeyChannelCategoryDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "example": "Retail"
     }
    },
    "required": [
     "name"
    ]
   },
   "AppKeyChannelBusinessDto": {
    "type": "object",
    "properties": {
     "tradename": {
      "type": "string",
      "example": "Acme Trading"
     },
     "logo": {
      "type": "string",
      "nullable": true,
      "example": null
     }
    },
    "required": [
     "tradename"
    ]
   },
   "AppKeyModeDto": {
    "type": "object",
    "properties": {
     "mode": {
      "type": "string",
      "enum": [
       "live",
       "test"
      ],
      "example": "live",
      "description": "A test app key only reads"
     }
    },
    "required": [
     "mode"
    ]
   },
   "AppKeyChannelDto": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid",
      "example": "65a4a10a-a7d0-4037-abc2-04445fedf8bb"
     },
     "title": {
      "type": "string",
      "example": "Acme Store"
     },
     "description": {
      "type": "string",
      "nullable": true,
      "example": "Official channel of Acme"
     },
     "logo": {
      "type": "string",
      "nullable": true,
      "example": "https://cdn.example.com/logo.png"
     },
     "icon": {
      "type": "string",
      "nullable": true,
      "example": null
     },
     "cover": {
      "type": "string",
      "nullable": true,
      "example": null
     },
     "domain": {
      "type": "string",
      "nullable": true,
      "example": "shop.example.com"
     },
     "link": {
      "type": "string",
      "nullable": true,
      "example": "https://shop.example.com"
     },
     "keywords": {
      "type": "string",
      "nullable": true,
      "example": "fashion, retail"
     },
     "category": {
      "nullable": true,
      "allOf": [
       {
        "$ref": "#/components/schemas/AppKeyChannelCategoryDto"
       }
      ]
     },
     "business": {
      "nullable": true,
      "allOf": [
       {
        "$ref": "#/components/schemas/AppKeyChannelBusinessDto"
       }
      ]
     },
     "apps": {
      "description": "Ids of the apps installed on the channel",
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "signup": {
      "type": "string",
      "enum": [
       "open",
       "restricted",
       "closed"
      ],
      "example": "open",
      "description": "Who may create an account here: a sign-up page can say \"by invitation\" up front"
     },
     "branding": {
      "type": "object",
      "additionalProperties": true,
      "description": "Settings › Branding: theme colours, fonts and tracking ids, each with its default when unset",
      "example": {
       "app_name": "Acme",
       "primary_color": "blue",
       "font": "system"
      }
     },
     "currency": {
      "type": "string",
      "example": "GBP",
      "description": "ISO 4217 currency the channel prices and settles in (Settings › General; GBP when unset). Orders are stamped with it."
     },
     "media": {
      "type": "object",
      "additionalProperties": true,
      "description": "How to ask the CDN for a sized image (docs/storage.md › Sized images)"
     },
     "app_key": {
      "$ref": "#/components/schemas/AppKeyModeDto"
     },
     "config": {
      "type": "object",
      "additionalProperties": {
       "type": "string"
      },
      "description": "Entries marked public in Settings › App config (NAME → value). Secrets never.",
      "example": {
       "SUPPORT_EMAIL": "help@example.com"
      }
     }
    },
    "required": [
     "id",
     "title",
     "apps",
     "signup",
     "branding",
     "currency",
     "media",
     "app_key",
     "config"
    ]
   },
   "StatsPeriodDto": {
    "type": "object",
    "properties": {
     "key": {
      "type": "string",
      "enum": [
       "today",
       "7d",
       "30d",
       "custom"
      ],
      "example": "7d"
     },
     "from": {
      "type": "string",
      "format": "date-time",
      "example": "2026-10-25T23:00:00.000Z",
      "description": "Included"
     },
     "to": {
      "type": "string",
      "format": "date-time",
      "example": "2026-11-01T10:30:00.000Z",
      "description": "Excluded"
     },
     "tz": {
      "type": "string",
      "example": "Europe/London"
     }
    },
    "required": [
     "key",
     "from",
     "to",
     "tz"
    ]
   },
   "StatsOrdersDto": {
    "type": "object",
    "properties": {
     "count": {
      "type": "number",
      "example": 42,
      "description": "Orders placed in the period, cancelled ones included"
     },
     "cancelled": {
      "type": "number",
      "example": 3,
      "description": "Of those, cancelled now"
     }
    },
    "required": [
     "count",
     "cancelled"
    ]
   },
   "StatsRevenueDto": {
    "type": "object",
    "properties": {
     "currency": {
      "type": "string",
      "example": "GBP"
     },
     "amount": {
      "type": "number",
      "example": 1234.5,
      "description": "Sum of order totals in major units: paid (card payment succeeded) or delivered orders only. Cancelled and refunded orders are left out, never subtracted"
     },
     "amount_minor": {
      "type": "number",
      "example": 123450,
      "description": "The same in minor units (pence, cents)"
     },
     "orders": {
      "type": "number",
      "example": 39,
      "description": "Paid or delivered orders counted in this currency"
     }
    },
    "required": [
     "currency",
     "amount",
     "amount_minor",
     "orders"
    ]
   },
   "StatsLeadsDto": {
    "type": "object",
    "properties": {
     "open": {
      "type": "number",
      "example": 16,
      "description": "CRM deals open now (not bound to the period)"
     },
     "new": {
      "type": "number",
      "example": 5,
      "description": "CRM contacts (leads) created in the period"
     }
    },
    "required": [
     "open",
     "new"
    ]
   },
   "StatsPreviousDto": {
    "type": "object",
    "properties": {
     "from": {
      "type": "string",
      "format": "date-time"
     },
     "to": {
      "type": "string",
      "format": "date-time"
     },
     "orders": {
      "$ref": "#/components/schemas/StatsOrdersDto"
     },
     "revenue": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/StatsRevenueDto"
      }
     },
     "new_customers": {
      "type": "number",
      "example": 8
     }
    },
    "required": [
     "from",
     "to",
     "orders",
     "revenue",
     "new_customers"
    ]
   },
   "ChannelStatsDto": {
    "type": "object",
    "properties": {
     "channel_id": {
      "type": "string",
      "format": "uuid"
     },
     "period": {
      "$ref": "#/components/schemas/StatsPeriodDto"
     },
     "currency": {
      "type": "string",
      "example": "GBP",
      "description": "The channel's currency (Settings › General; GBP when unset)"
     },
     "orders": {
      "$ref": "#/components/schemas/StatsOrdersDto"
     },
     "revenue": {
      "description": "Revenue grouped by currency, the channel's own first. Empty when nothing was sold.",
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/StatsRevenueDto"
      }
     },
     "buyers": {
      "type": "number",
      "example": 30,
      "description": "Distinct signed-in buyers who ordered in the period"
     },
     "new_customers": {
      "type": "number",
      "example": 12,
      "description": "Accounts that signed up on this channel in the period"
     },
     "leads": {
      "$ref": "#/components/schemas/StatsLeadsDto"
     },
     "previous": {
      "description": "The window of the same length just before, for comparisons",
      "allOf": [
       {
        "$ref": "#/components/schemas/StatsPreviousDto"
       }
      ]
     },
     "generated_at": {
      "type": "string",
      "format": "date-time"
     }
    },
    "required": [
     "channel_id",
     "period",
     "currency",
     "orders",
     "revenue",
     "buyers",
     "new_customers",
     "leads",
     "previous",
     "generated_at"
    ]
   },
   "UpdateChannelDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "example": "My Online Store"
     },
     "description": {
      "type": "string",
      "example": "Official channel for our business"
     },
     "trademark_id": {
      "type": "number",
      "minimum": 1,
      "example": 3,
      "description": "Id of a trademark registered to a business you manage"
     },
     "category_id": {
      "type": "string",
      "example": "uuid-of-category"
     },
     "link": {
      "type": "string",
      "example": "https://mywebsite.com"
     },
     "keywords": {
      "type": "string",
      "example": "keyword1, keyword2"
     }
    }
   },
   "ArchiveChannelDto": {
    "type": "object",
    "properties": {
     "reason": {
      "type": "string",
      "maxLength": 500,
      "example": "Brand retired"
     }
    }
   },
   "PatchChannelSettingsDto": {
    "type": "object",
    "properties": {
     "section": {
      "type": "string",
      "enum": [
       "general",
       "channel",
       "notifications",
       "languages",
       "privacy",
       "protection",
       "auth",
       "usernames",
       "calendar",
       "branding",
       "web",
       "system"
      ],
      "example": "general"
     },
     "values": {
      "type": "object",
      "example": {
       "timezone": "Europe/London",
       "time_format": "24h"
      },
      "description": "Keys of the section to change; each is validated against the section schema"
     }
    },
    "required": [
     "section",
     "values"
    ]
   },
   "AddDomainDto": {
    "type": "object",
    "properties": {
     "domain": {
      "type": "string",
      "maxLength": 253,
      "example": "shop.example.com"
     }
    },
    "required": [
     "domain"
    ]
   },
   "OriginDto": {
    "type": "object",
    "properties": {
     "origin": {
      "type": "string",
      "example": "https://web.example.com"
     }
    },
    "required": [
     "origin"
    ]
   },
   "OriginCredentialsDto": {
    "type": "object",
    "properties": {
     "allow_credentials": {
      "type": "boolean",
      "description": "Answer Access-Control-Allow-Credentials for these origins (cookies). Off by default: apps that send a Bearer token don't need it."
     }
    },
    "required": [
     "allow_credentials"
    ]
   },
   "SendEmailDto": {
    "type": "object",
    "properties": {
     "to": {
      "type": "array",
      "items": {
       "oneOf": [
        {
         "type": "string"
        },
        {
         "type": "array"
        }
       ]
      }
     },
     "subject": {
      "type": "string",
      "maxLength": 250
     },
     "html": {
      "type": "string",
      "maxLength": 500000
     },
     "text": {
      "type": "string",
      "maxLength": 200000
     },
     "channel_id": {
      "type": "string"
     }
    },
    "required": [
     "to",
     "subject",
     "html"
    ]
   },
   "CreatePlanDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 150
     },
     "description": {
      "type": "string",
      "maxLength": 2000
     },
     "price": {
      "type": "number",
      "minimum": 0
     },
     "interval": {
      "type": "string",
      "enum": [
       "day",
       "week",
       "month",
       "year"
      ]
     },
     "status": {
      "type": "string",
      "enum": [
       "published",
       "draft",
       "archived"
      ]
     }
    },
    "required": [
     "title",
     "price"
    ]
   },
   "UpdatePlanDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 150
     },
     "description": {
      "type": "string",
      "maxLength": 2000
     },
     "price": {
      "type": "number",
      "minimum": 0
     },
     "interval": {
      "type": "string",
      "enum": [
       "day",
       "week",
       "month",
       "year"
      ]
     },
     "status": {
      "type": "string",
      "enum": [
       "published",
       "draft",
       "archived"
      ]
     }
    }
   },
   "SubscribeDto": {
    "type": "object",
    "properties": {
     "plan_id": {
      "type": "number",
      "minimum": 1
     },
     "payment_id": {
      "type": "string",
      "description": "Required for a plan with price > 0: a `payments` row of the caller with\n status \"success\" and amount = the plan price, not used before."
     }
    },
    "required": [
     "plan_id"
    ]
   },
   "ChangePlanDto": {
    "type": "object",
    "properties": {
     "new_plan_id": {
      "type": "number",
      "minimum": 1
     },
     "payment_id": {
      "type": "string",
      "description": "Required when the change costs money (proration amount > 0): a\n successful, unused payment of the caller for exactly that amount."
     }
    },
    "required": [
     "new_plan_id"
    ]
   },
   "SendPostGiftDto": {
    "type": "object",
    "properties": {
     "post_id": {
      "type": "number",
      "minimum": 1
     },
     "gift_id": {
      "type": "number",
      "minimum": 1
     }
    },
    "required": [
     "post_id",
     "gift_id"
    ]
   },
   "CreateSearchDto": {
    "type": "object",
    "properties": {
     "query": {
      "type": "string",
      "minLength": 2,
      "maxLength": 80
     },
     "active_profile_id": {
      "type": "string"
     }
    },
    "required": [
     "query"
    ]
   },
   "DeleteSearchHistoryDto": {
    "type": "object",
    "properties": {
     "keyword_id": {
      "type": "number"
     },
     "active_profile_id": {
      "type": "string"
     },
     "match": {
      "type": "string"
     },
     "scope": {
      "type": "string"
     }
    }
   },
   "CreateHighlightDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 255,
      "example": "Travel 2026",
      "description": "Title of the highlight"
     },
     "description": {
      "type": "string",
      "example": "My recent trip to Manali"
     },
     "active_profile_id": {
      "type": "string",
      "example": "Optional Profile ID if creating for business profile"
     },
     "sort": {
      "type": "string"
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published",
       "archived"
      ]
     }
    },
    "required": [
     "title"
    ]
   },
   "UpdateHighlightDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 255
     },
     "description": {
      "type": "string"
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published",
       "archived"
      ],
      "example": "published"
     },
     "sort": {
      "type": "object",
      "example": 1
     }
    }
   },
   "AddMediaToHighlightDto": {
    "type": "object",
    "properties": {
     "story_id": {
      "type": "number",
      "description": "ID of an existing story to add to highlight"
     },
     "file_id": {
      "type": "number",
      "minimum": 1,
      "description": "Or an existing image from your drive (`file` row id)"
     },
     "active_profile_id": {
      "type": "string",
      "example": "Optional Profile ID if adding for business profile"
     },
     "title": {
      "type": "string",
      "maxLength": 255
     },
     "description": {
      "type": "string"
     },
     "url": {
      "type": "string",
      "maxLength": 255
     },
     "sort": {
      "type": "string"
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published",
       "archived"
      ]
     }
    }
   },
   "UpdateHighlightMediaDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 255
     },
     "description": {
      "type": "string"
     },
     "url": {
      "type": "string",
      "maxLength": 255
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published",
       "archived"
      ]
     },
     "sort": {
      "type": "object"
     }
    }
   },
   "CreateBannerDto": {
    "type": "object",
    "properties": {
     "placement": {
      "type": "string",
      "nullable": true,
      "maxLength": 60,
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
      "example": "home-hero"
     },
     "starts_at": {
      "type": "string",
      "nullable": true,
      "description": "Show from (ISO date-time)"
     },
     "ends_at": {
      "type": "string",
      "nullable": true,
      "description": "Show until (ISO date-time)"
     },
     "sort": {
      "type": "number",
      "minimum": 0,
      "maximum": 10000
     },
     "name": {
      "type": "string",
      "maxLength": 255,
      "example": "Autumn sale"
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published"
      ],
      "default": "draft"
     }
    },
    "required": [
     "name"
    ]
   },
   "UpdateBannerDto": {
    "type": "object",
    "properties": {
     "placement": {
      "type": "string",
      "nullable": true,
      "maxLength": 60,
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
      "example": "home-hero"
     },
     "starts_at": {
      "type": "string",
      "nullable": true,
      "description": "Show from (ISO date-time)"
     },
     "ends_at": {
      "type": "string",
      "nullable": true,
      "description": "Show until (ISO date-time)"
     },
     "sort": {
      "type": "number",
      "minimum": 0,
      "maximum": 10000
     },
     "name": {
      "type": "string",
      "maxLength": 255
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published",
       "archived"
      ]
     }
    }
   },
   "BannerImageDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "nullable": true,
      "maxLength": 255
     },
     "image": {
      "type": "string",
      "nullable": true,
      "description": "directus_files id"
     },
     "description": {
      "type": "string",
      "nullable": true,
      "maxLength": 5000,
      "description": "Rich text (sanitized server-side)"
     },
     "link": {
      "type": "string",
      "nullable": true,
      "example": "/shop"
     },
     "button_text": {
      "type": "string",
      "nullable": true,
      "maxLength": 60
     },
     "sort": {
      "type": "number",
      "minimum": 0,
      "maximum": 10000
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published",
       "archived"
      ]
     }
    }
   },
   "CreateCollectionDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 120,
      "example": "Electronics"
     },
     "description": {
      "type": "string",
      "nullable": true,
      "maxLength": 2000
     },
     "parent_id": {
      "type": "string",
      "nullable": true,
      "description": "Parent collection of the same channel"
     },
     "status": {
      "type": "string",
      "enum": [
       "published",
       "draft"
      ],
      "default": "published"
     }
    },
    "required": [
     "name"
    ]
   },
   "UpdateCollectionDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 120
     },
     "description": {
      "type": "string",
      "nullable": true,
      "maxLength": 2000
     },
     "parent_id": {
      "type": "string",
      "nullable": true
     },
     "status": {
      "type": "string",
      "enum": [
       "published",
       "draft"
      ]
     }
    }
   },
   "ModerateReviewDto": {
    "type": "object",
    "properties": {
     "status": {
      "type": "string",
      "enum": [
       "published",
       "hidden"
      ]
     }
    },
    "required": [
     "status"
    ]
   },
   "CreateInstitutionDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "description": "Name of the institution"
     },
     "type": {
      "type": "string",
      "description": "Type of the institution (e.g., University, School, NGO)"
     },
     "status": {
      "enum": [
       "published",
       "draft",
       "archived"
      ],
      "type": "string",
      "description": "Status of the institution"
     }
    },
    "required": [
     "name",
     "type"
    ]
   },
   "UpdateInstitutionDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "description": "Name of the institution"
     },
     "type": {
      "type": "string",
      "description": "Type of the institution"
     },
     "status": {
      "enum": [
       "published",
       "draft",
       "archived"
      ],
      "type": "string",
      "description": "Status of the institution"
     }
    }
   },
   "CreateAttributeGroupDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string"
     },
     "sort": {
      "type": "number"
     }
    },
    "required": [
     "name"
    ]
   },
   "UpdateAttributeGroupDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string"
     },
     "sort": {
      "type": "number"
     }
    }
   },
   "CreateAttributeDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string"
     },
     "attribute_group": {
      "type": "number",
      "description": "Attribute group id (same channel)"
     },
     "sort": {
      "type": "number"
     }
    },
    "required": [
     "name",
     "attribute_group"
    ]
   },
   "UpdateAttributeDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string"
     },
     "attribute_group": {
      "type": "number",
      "description": "Attribute group id (same channel)"
     },
     "sort": {
      "type": "number"
     }
    }
   },
   "CreateAttributeDataDto": {
    "type": "object",
    "properties": {
     "description": {
      "type": "string"
     },
     "attribute_id": {
      "type": "string",
      "description": "Attribute uuid (same channel)"
     },
     "product_id": {
      "type": "string",
      "description": "Product uuid (same channel)"
     },
     "campaign_id": {
      "type": "number",
      "description": "Campaign id (same channel)"
     },
     "sort": {
      "type": "number"
     }
    },
    "required": [
     "description",
     "attribute_id"
    ]
   },
   "UpdateAttributeDataDto": {
    "type": "object",
    "properties": {
     "description": {
      "type": "string"
     },
     "attribute_id": {
      "type": "string",
      "description": "Attribute uuid (same channel)"
     },
     "product_id": {
      "type": "string",
      "description": "Product uuid (same channel)"
     },
     "campaign_id": {
      "type": "number",
      "description": "Campaign id (same channel)"
     },
     "sort": {
      "type": "number"
     }
    }
   },
   "CreateReportDto": {
    "type": "object",
    "properties": {
     "report_reason": {
      "type": "object",
      "description": "ID of the report reason"
     },
     "description": {
      "type": "string",
      "maxLength": 5000,
      "description": "Detailed description of the report"
     },
     "post_id": {
      "type": "object",
      "description": "ID of the reported post"
     },
     "comment_id": {
      "type": "object",
      "description": "ID of the reported comment"
     },
     "product_id": {
      "type": "object",
      "description": "ID of the reported product"
     },
     "campaign_id": {
      "type": "object",
      "description": "ID of the reported campaign"
     },
     "business_id": {
      "type": "object",
      "description": "ID of the reported business"
     },
     "profile_id": {
      "type": "string",
      "description": "ID of the reported profile (UUID)"
     },
     "active_profile_id": {
      "type": "string",
      "description": "Active profile ID of the reporter"
     },
     "ch_id": {
      "type": "object",
      "description": "Ignored. The report's channel is derived from the reported content."
     },
     "channel_id": {
      "type": "string",
      "description": "Ignored. The report's channel is derived from the reported content."
     }
    },
    "required": [
     "report_reason"
    ]
   },
   "UpdateReportDto": {
    "type": "object",
    "properties": {
     "status": {
      "type": "number",
      "minimum": 1,
      "description": "New status id (report_status.id)"
     },
     "title": {
      "type": "string",
      "description": "Audit trail title for the status change"
     },
     "description": {
      "type": "string",
      "description": "Audit trail description for the status change"
     }
    },
    "required": [
     "status"
    ]
   },
   "CreateFaqGroupDto": {
    "type": "object",
    "properties": {
     "slug": {
      "type": "string",
      "nullable": true,
      "maxLength": 120,
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
      "example": "bookings"
     },
     "type": {
      "type": "string",
      "nullable": true,
      "maxLength": 60,
      "example": "business",
      "description": "Audience type"
     },
     "parent_id": {
      "type": "number",
      "nullable": true,
      "minimum": 1,
      "description": "Parent category id (same channel)"
     },
     "description": {
      "type": "string",
      "nullable": true,
      "maxLength": 2000
     },
     "name": {
      "type": "string",
      "maxLength": 255,
      "example": "Bookings"
     }
    },
    "required": [
     "name"
    ]
   },
   "UpdateFaqGroupDto": {
    "type": "object",
    "properties": {
     "slug": {
      "type": "string",
      "nullable": true,
      "maxLength": 120,
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
      "example": "bookings"
     },
     "type": {
      "type": "string",
      "nullable": true,
      "maxLength": 60,
      "example": "business",
      "description": "Audience type"
     },
     "parent_id": {
      "type": "number",
      "nullable": true,
      "minimum": 1,
      "description": "Parent category id (same channel)"
     },
     "description": {
      "type": "string",
      "nullable": true,
      "maxLength": 2000
     },
     "name": {
      "type": "string",
      "maxLength": 255
     }
    }
   },
   "CreateFaqDto": {
    "type": "object",
    "properties": {
     "description": {
      "type": "string",
      "nullable": true,
      "maxLength": 20000,
      "description": "Answer as rich text, sanitized server-side"
     },
     "slug": {
      "type": "string",
      "nullable": true,
      "maxLength": 120,
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
      "example": "how-do-i-reschedule"
     },
     "sort": {
      "type": "number",
      "minimum": 0,
      "maximum": 10000
     },
     "faq_group_id": {
      "type": "number",
      "minimum": 1,
      "description": "Category (faq_group) id of this channel"
     },
     "title": {
      "type": "string",
      "maxLength": 255,
      "example": "How do I reschedule?"
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published"
      ],
      "default": "draft"
     }
    },
    "required": [
     "faq_group_id",
     "title"
    ]
   },
   "UpdateFaqDto": {
    "type": "object",
    "properties": {
     "description": {
      "type": "string",
      "nullable": true,
      "maxLength": 20000,
      "description": "Answer as rich text, sanitized server-side"
     },
     "slug": {
      "type": "string",
      "nullable": true,
      "maxLength": 120,
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
      "example": "how-do-i-reschedule"
     },
     "sort": {
      "type": "number",
      "minimum": 0,
      "maximum": 10000
     },
     "faq_group_id": {
      "type": "number",
      "minimum": 1
     },
     "title": {
      "type": "string",
      "maxLength": 255
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published",
       "archived"
      ]
     }
    }
   },
   "CreateFormDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "description": "Name of the person submitting"
     },
     "email": {
      "type": "string",
      "description": "Email address of the submitter"
     },
     "mobile": {
      "type": "string",
      "description": "Mobile/Phone number"
     },
     "subject": {
      "type": "string",
      "description": "Subject of the form/enquiry"
     },
     "description": {
      "type": "string",
      "description": "Detailed description"
     },
     "budget": {
      "type": "string",
      "description": "Budget value/range"
     },
     "city": {
      "type": "string",
      "description": "City"
     },
     "company": {
      "type": "string",
      "description": "Company Name"
     },
     "job_title": {
      "type": "string",
      "description": "Job Title"
     },
     "type": {
      "type": "string",
      "description": "Type of form (e.g. contact_us, enquiry)"
     },
     "channel_id": {
      "type": "string",
      "description": "Channel UUID"
     },
     "active_profile_id": {
      "type": "string",
      "description": "Active profile ID of the submitter"
     },
     "business_id": {
      "type": "object",
      "description": "Business ID (M2O)"
     },
     "country": {
      "type": "object",
      "description": "Country ID (M2O)"
     },
     "zone": {
      "type": "object",
      "description": "Zone ID (M2O)"
     },
     "rm_id": {
      "type": "object",
      "description": "Relationship Manager ID (M2O)"
     }
    },
    "required": [
     "name",
     "email"
    ]
   },
   "UpdateFormStatusDto": {
    "type": "object",
    "properties": {
     "status": {
      "type": "number",
      "minimum": 1,
      "description": "New workflow status (form_status id)"
     },
     "comment": {
      "type": "string",
      "description": "Manager comment for the status update"
     },
     "notify": {
      "type": "boolean",
      "description": "Flag to notify the user"
     }
    },
    "required": [
     "status"
    ]
   },
   "PublicFormSubmitDto": {
    "type": "object",
    "properties": {
     "fields": {
      "type": "object",
      "description": "The answers, keyed by the form's field keys (see GET /public/forms/:formKey)",
      "example": {
       "name": "Asha Rao",
       "email": "asha@example.com",
       "message": "Please call me back."
      }
     },
     "consent": {
      "type": "boolean",
      "description": "The visitor ticked the consent box shown with the form's consent.text"
     },
     "consent_version": {
      "type": "string",
      "maxLength": 32,
      "description": "consent.version the page showed; a stale one is refused with 409 FORM_CHANGED"
     },
     "captcha_token": {
      "type": "string",
      "maxLength": 2048,
      "description": "Cloudflare Turnstile token from the widget on the page (single use)"
     },
     "website": {
      "type": "string",
      "maxLength": 500,
      "description": "Honeypot: render it hidden and leave it empty"
     },
     "job_id": {
      "type": "number",
      "minimum": 1,
      "description": "Application forms without a fixed job: the job applied for"
     },
     "page_url": {
      "type": "string",
      "maxLength": 500,
      "description": "Page the form was sent from"
     },
     "utm_source": {
      "type": "string",
      "maxLength": 200
     },
     "utm_medium": {
      "type": "string",
      "maxLength": 200
     },
     "utm_campaign": {
      "type": "string",
      "maxLength": 200
     },
     "utm_term": {
      "type": "string",
      "maxLength": 200
     },
     "utm_content": {
      "type": "string",
      "maxLength": 200
     }
    }
   },
   "PublicFormCvUploadDto": {
    "type": "object",
    "properties": {
     "job_id": {
      "type": "number",
      "minimum": 1,
      "description": "Application forms without a fixed job: the job applied for (submit must name the same one)"
     },
     "filename": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200,
      "description": "The file's name as picked; its extension must fit content_type"
     },
     "content_type": {
      "type": "string",
      "enum": [
       "application/pdf",
       "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
      ]
     },
     "size": {
      "type": "number",
      "minimum": 1,
      "maximum": 5242880,
      "description": "Exact size in bytes (1 to 5242880)"
     }
    },
    "required": [
     "filename",
     "content_type",
     "size"
    ]
   },
   "CreateContactDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "nullable": true,
      "maxLength": 200
     },
     "email": {
      "type": "string",
      "nullable": true,
      "maxLength": 254
     },
     "phone": {
      "type": "string",
      "nullable": true,
      "description": "E.164 (`+447700900123`), or national format with `phone_country`.",
      "maxLength": 32
     },
     "phone_country": {
      "type": "string",
      "description": "Country for a national-format phone (default GB).",
      "enum": [
       "GB",
       "US",
       "IE",
       "IN"
      ]
     },
     "company": {
      "type": "string",
      "nullable": true,
      "maxLength": 200
     },
     "job_title": {
      "type": "string",
      "nullable": true,
      "maxLength": 120
     },
     "owner_id": {
      "type": "string",
      "nullable": true,
      "description": "Assigned staff member (must manage the channel)."
     },
     "user_id": {
      "type": "string",
      "nullable": true,
      "description": "Platform account of this channel, when known."
     },
     "user_profile_id": {
      "type": "string",
      "nullable": true
     },
     "tags": {
      "type": "array",
      "items": {
       "type": "string",
       "maxLength": 40
      }
     },
     "custom_fields": {
      "type": "object",
      "description": "Flat object; keys may be restricted per channel. Max 8 KB."
     },
     "interest": {
      "type": "string",
      "nullable": true,
      "maxLength": 200
     },
     "description": {
      "type": "string",
      "nullable": true,
      "maxLength": 5000
     },
     "source": {
      "type": "string",
      "nullable": true,
      "maxLength": 40
     },
     "utm_source": {
      "type": "string",
      "nullable": true,
      "maxLength": 200
     },
     "utm_medium": {
      "type": "string",
      "nullable": true,
      "maxLength": 200
     },
     "utm_campaign": {
      "type": "string",
      "nullable": true,
      "maxLength": 200
     },
     "utm_term": {
      "type": "string",
      "nullable": true,
      "maxLength": 200
     },
     "utm_content": {
      "type": "string",
      "nullable": true,
      "maxLength": 200
     },
     "marketing_consent": {
      "type": "boolean",
      "description": "Marketing consent (UK GDPR / PECR). The server stamps the time."
     },
     "marketing_consent_source": {
      "type": "string",
      "description": "How consent was captured, e.g. \"phone call\", \"paper form\".",
      "maxLength": 64
     }
    }
   },
   "UpdateContactDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "nullable": true,
      "maxLength": 200
     },
     "email": {
      "type": "string",
      "nullable": true,
      "maxLength": 254
     },
     "phone": {
      "type": "string",
      "nullable": true,
      "description": "E.164 (`+447700900123`), or national format with `phone_country`.",
      "maxLength": 32
     },
     "phone_country": {
      "type": "string",
      "description": "Country for a national-format phone (default GB).",
      "enum": [
       "GB",
       "US",
       "IE",
       "IN"
      ]
     },
     "company": {
      "type": "string",
      "nullable": true,
      "maxLength": 200
     },
     "job_title": {
      "type": "string",
      "nullable": true,
      "maxLength": 120
     },
     "owner_id": {
      "type": "string",
      "nullable": true,
      "description": "Assigned staff member (must manage the channel)."
     },
     "user_id": {
      "type": "string",
      "nullable": true,
      "description": "Platform account of this channel, when known."
     },
     "user_profile_id": {
      "type": "string",
      "nullable": true
     },
     "tags": {
      "type": "array",
      "items": {
       "type": "string",
       "maxLength": 40
      }
     },
     "custom_fields": {
      "type": "object",
      "description": "Flat object; keys may be restricted per channel. Max 8 KB."
     },
     "interest": {
      "type": "string",
      "nullable": true,
      "maxLength": 200
     },
     "description": {
      "type": "string",
      "nullable": true,
      "maxLength": 5000
     },
     "source": {
      "type": "string",
      "nullable": true,
      "maxLength": 40
     },
     "utm_source": {
      "type": "string",
      "nullable": true,
      "maxLength": 200
     },
     "utm_medium": {
      "type": "string",
      "nullable": true,
      "maxLength": 200
     },
     "utm_campaign": {
      "type": "string",
      "nullable": true,
      "maxLength": 200
     },
     "utm_term": {
      "type": "string",
      "nullable": true,
      "maxLength": 200
     },
     "utm_content": {
      "type": "string",
      "nullable": true,
      "maxLength": 200
     },
     "marketing_consent": {
      "type": "boolean",
      "description": "Marketing consent (UK GDPR / PECR). The server stamps the time."
     },
     "marketing_consent_source": {
      "type": "string",
      "description": "How consent was captured, e.g. \"phone call\", \"paper form\".",
      "maxLength": 64
     }
    }
   },
   "StageInputDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 80
     },
     "kind": {
      "type": "string",
      "description": "open (default) | won | lost",
      "enum": [
       "open",
       "won",
       "lost"
      ]
     },
     "probability": {
      "type": "number",
      "nullable": true,
      "description": "Win probability 0–100.",
      "minimum": 0,
      "maximum": 100
     }
    },
    "required": [
     "name"
    ]
   },
   "CreatePipelineDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 120
     },
     "is_default": {
      "type": "boolean"
     },
     "stages": {
      "description": "Ordered stages; defaults to New / Interested / Meeting Booked / Converted (won) / Lost (lost).",
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/StageInputDto"
      }
     }
    },
    "required": [
     "name"
    ]
   },
   "UpdatePipelineDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 120
     },
     "is_default": {
      "type": "boolean",
      "description": "true makes this the channel's default (the previous default is unset)."
     },
     "sort": {
      "type": "number",
      "minimum": 0,
      "maximum": 1000
     }
    }
   },
   "CreateStageDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 80
     },
     "kind": {
      "type": "string",
      "description": "open (default) | won | lost",
      "enum": [
       "open",
       "won",
       "lost"
      ]
     },
     "probability": {
      "type": "number",
      "nullable": true,
      "description": "Win probability 0–100.",
      "minimum": 0,
      "maximum": 100
     }
    },
    "required": [
     "name"
    ]
   },
   "ReorderStagesDto": {
    "type": "object",
    "properties": {
     "stage_ids": {
      "type": "array",
      "items": {
       "type": "string"
      }
     }
    },
    "required": [
     "stage_ids"
    ]
   },
   "UpdateStageDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 80
     },
     "kind": {
      "type": "string",
      "enum": [
       "open",
       "won",
       "lost"
      ]
     },
     "probability": {
      "type": "number",
      "nullable": true,
      "minimum": 0,
      "maximum": 100
     }
    }
   },
   "CreateDealDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 200
     },
     "contact_id": {
      "type": "string",
      "nullable": true
     },
     "pipeline_id": {
      "type": "string",
      "description": "Defaults to the channel's default pipeline (created on first use)."
     },
     "stage_id": {
      "type": "string",
      "description": "Defaults to the pipeline's first open stage."
     },
     "value_minor": {
      "type": "number",
      "description": "Integer minor units (pence / cents).",
      "minimum": 0,
      "maximum": 10000000000000
     },
     "currency": {
      "type": "string",
      "description": "ISO 4217, e.g. GBP (default).",
      "pattern": "^[A-Z]{3}$"
     },
     "owner_id": {
      "type": "string",
      "nullable": true
     },
     "expected_close_date": {
      "type": "string",
      "nullable": true,
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
     },
     "source": {
      "type": "string",
      "nullable": true,
      "maxLength": 40
     },
     "interest": {
      "type": "string",
      "nullable": true,
      "maxLength": 200
     }
    },
    "required": [
     "title"
    ]
   },
   "UpdateDealDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 200
     },
     "contact_id": {
      "type": "string",
      "nullable": true
     },
     "value_minor": {
      "type": "number",
      "minimum": 0,
      "maximum": 10000000000000
     },
     "currency": {
      "type": "string",
      "pattern": "^[A-Z]{3}$"
     },
     "owner_id": {
      "type": "string",
      "nullable": true
     },
     "expected_close_date": {
      "type": "string",
      "nullable": true,
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
     },
     "source": {
      "type": "string",
      "nullable": true,
      "maxLength": 40
     },
     "interest": {
      "type": "string",
      "nullable": true,
      "maxLength": 200
     }
    }
   },
   "MoveDealDto": {
    "type": "object",
    "properties": {
     "stage_id": {
      "type": "string",
      "description": "A stage of the deal's pipeline. Moving to a won/lost stage closes the deal."
     },
     "reason": {
      "type": "string",
      "description": "Required when the target stage is a lost stage.",
      "maxLength": 500
     }
    },
    "required": [
     "stage_id"
    ]
   },
   "CloseDealDto": {
    "type": "object",
    "properties": {
     "outcome": {
      "type": "string",
      "enum": [
       "won",
       "lost"
      ]
     },
     "reason": {
      "type": "string",
      "description": "Required for lost.",
      "maxLength": 500
     }
    },
    "required": [
     "outcome"
    ]
   },
   "CreateActivityDto": {
    "type": "object",
    "properties": {
     "type": {
      "type": "string",
      "enum": [
       "note",
       "call",
       "email",
       "meeting",
       "task"
      ]
     },
     "contact_id": {
      "type": "string"
     },
     "deal_id": {
      "type": "string"
     },
     "subject": {
      "type": "string",
      "nullable": true,
      "maxLength": 200
     },
     "body": {
      "type": "string",
      "nullable": true,
      "maxLength": 10000
     },
     "direction": {
      "type": "string",
      "description": "calls / emails",
      "enum": [
       "inbound",
       "outbound"
      ]
     },
     "occurred_at": {
      "type": "string",
      "description": "When it happened (defaults to now)."
     },
     "due_at": {
      "type": "string",
      "nullable": true,
      "description": "Tasks / meetings."
     },
     "done": {
      "type": "boolean",
      "description": "Tasks: completion (the server stamps completed_at)."
     },
     "duration_minutes": {
      "type": "number",
      "nullable": true,
      "minimum": 0,
      "maximum": 1440
     },
     "event_type": {
      "type": "string",
      "nullable": true,
      "description": "Meetings / tasks: the booking type shown on the calendar (e.g. \"Consultation\").",
      "maxLength": 60
     }
    },
    "required": [
     "type"
    ]
   },
   "UpdateActivityDto": {
    "type": "object",
    "properties": {
     "subject": {
      "type": "string",
      "nullable": true,
      "maxLength": 200
     },
     "body": {
      "type": "string",
      "nullable": true,
      "maxLength": 10000
     },
     "direction": {
      "type": "string",
      "description": "calls / emails",
      "enum": [
       "inbound",
       "outbound"
      ]
     },
     "occurred_at": {
      "type": "string",
      "description": "When it happened (defaults to now)."
     },
     "due_at": {
      "type": "string",
      "nullable": true,
      "description": "Tasks / meetings."
     },
     "done": {
      "type": "boolean",
      "description": "Tasks: completion (the server stamps completed_at)."
     },
     "duration_minutes": {
      "type": "number",
      "nullable": true,
      "minimum": 0,
      "maximum": 1440
     },
     "event_type": {
      "type": "string",
      "nullable": true,
      "description": "Meetings / tasks: the booking type shown on the calendar (e.g. \"Consultation\").",
      "maxLength": 60
     }
    }
   },
   "WebLeadDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 200
     },
     "email": {
      "type": "string",
      "maxLength": 254
     },
     "phone": {
      "type": "string",
      "maxLength": 32
     },
     "phone_country": {
      "type": "string",
      "enum": [
       "GB",
       "US",
       "IE",
       "IN"
      ]
     },
     "company": {
      "type": "string",
      "maxLength": 200
     },
     "message": {
      "type": "string",
      "maxLength": 5000
     },
     "interest": {
      "type": "string",
      "description": "What they're interested in (e.g. a service).",
      "maxLength": 200
     },
     "form_id": {
      "type": "string",
      "description": "Identifies the form on the site (slug, e.g. \"contact-page\").",
      "pattern": "^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$"
     },
     "utm_source": {
      "type": "string",
      "maxLength": 200
     },
     "utm_medium": {
      "type": "string",
      "maxLength": 200
     },
     "utm_campaign": {
      "type": "string",
      "maxLength": 200
     },
     "utm_term": {
      "type": "string",
      "maxLength": 200
     },
     "utm_content": {
      "type": "string",
      "maxLength": 200
     },
     "marketing_consent": {
      "type": "boolean",
      "description": "Opt-in tick box (must be unticked by default under PECR)."
     },
     "consent_text": {
      "type": "string",
      "description": "The consent wording shown next to the tick box (kept as evidence).",
      "maxLength": 500
     },
     "consent_version": {
      "type": "string",
      "description": "Version of that wording (a form definition's consent.version).",
      "pattern": "^[A-Za-z0-9][A-Za-z0-9_.-]{0,31}$"
     },
     "page_url": {
      "type": "string",
      "description": "Page the form was submitted from.",
      "maxLength": 500
     },
     "captcha_token": {
      "type": "string",
      "description": "Cloudflare Turnstile token from the form, needed when the channel turns\non settings › protection › forms_captcha.",
      "maxLength": 2048
     },
     "website": {
      "type": "string",
      "description": "Honeypot: leave empty.",
      "maxLength": 500
     }
    }
   },
   "ReadMarksStateDto": {
    "type": "object",
    "properties": {
     "list": {
      "type": "string",
      "example": "crm.contacts"
     },
     "channel_id": {
      "type": "string",
      "format": "uuid"
     },
     "read": {
      "type": "object",
      "additionalProperties": {
       "type": "string",
       "format": "date-time",
       "nullable": true
      },
      "description": "Each asked id → when this person read it, or null (unread). Ids not in the channel are left out.",
      "example": {
       "9b1f0c3e-1d2a-4c5b-8e7f-0a1b2c3d4e5f": "2026-11-01T09:12:00.000Z",
       "0c2d4e6f-1a3b-4c5d-8e9f-a0b1c2d3e4f5": null
      }
     }
    },
    "required": [
     "list",
     "channel_id",
     "read"
    ]
   },
   "ReadMarksCountsDto": {
    "type": "object",
    "properties": {
     "list": {
      "type": "string",
      "example": "crm.contacts"
     },
     "channel_id": {
      "type": "string",
      "format": "uuid"
     },
     "total": {
      "type": "number",
      "example": 40,
      "description": "Records in the list"
     },
     "read": {
      "type": "number",
      "example": 15,
      "description": "Read by this person"
     },
     "unread": {
      "type": "number",
      "example": 25,
      "description": "Not read by this person"
     }
    },
    "required": [
     "list",
     "channel_id",
     "total",
     "read",
     "unread"
    ]
   },
   "ReadMarksIdsDto": {
    "type": "object",
    "properties": {
     "channel_id": {
      "type": "string",
      "format": "uuid",
      "description": "The channel; the session's channel when left out"
     },
     "ids": {
      "maxItems": 200,
      "example": [
       "9b1f0c3e-1d2a-4c5b-8e7f-0a1b2c3d4e5f"
      ],
      "type": "array",
      "items": {
       "type": "string",
       "pattern": "^[A-Za-z0-9_-]{1,64}$"
      }
     }
    },
    "required": [
     "ids"
    ]
   },
   "ReadMarksChangeDto": {
    "type": "object",
    "properties": {
     "list": {
      "type": "string",
      "example": "crm.contacts"
     },
     "channel_id": {
      "type": "string",
      "format": "uuid"
     },
     "changed": {
      "type": "number",
      "example": 3,
      "description": "Marks added (read) or removed (unread); ones already right are not counted"
     },
     "unread": {
      "type": "number",
      "example": 25,
      "description": "Unread records left in the list for this person"
     },
     "more": {
      "type": "boolean",
      "example": false,
      "description": "read-all only: more records remain past the per-call cap; call again"
     }
    },
    "required": [
     "list",
     "channel_id",
     "changed",
     "unread"
    ]
   },
   "ReadMarksChannelDto": {
    "type": "object",
    "properties": {
     "channel_id": {
      "type": "string",
      "format": "uuid",
      "description": "The channel; the session's channel when left out"
     }
    }
   },
   "CreatePageDto": {
    "type": "object",
    "properties": {
     "description": {
      "type": "string",
      "nullable": true,
      "maxLength": 2000,
      "description": "Intro (plain text)"
     },
     "image": {
      "type": "string",
      "nullable": true,
      "description": "directus_files id of the hero image"
     },
     "meta_title": {
      "type": "string",
      "nullable": true,
      "maxLength": 255
     },
     "meta_description": {
      "type": "string",
      "nullable": true,
      "maxLength": 500
     },
     "meta_keyword": {
      "type": "string",
      "nullable": true,
      "maxLength": 255
     },
     "tags": {
      "type": "string",
      "nullable": true,
      "maxLength": 255
     },
     "og_image": {
      "type": "string",
      "nullable": true,
      "description": "directus_files id of the og:image"
     },
     "canonical_url": {
      "type": "string",
      "nullable": true,
      "maxLength": 2048,
      "example": "https://shop.example.com/about-us"
     },
     "noindex": {
      "type": "boolean",
      "description": "Ask search engines not to index"
     },
     "title": {
      "type": "string",
      "maxLength": 255,
      "example": "About us"
     },
     "slug": {
      "type": "string",
      "maxLength": 120,
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
      "example": "about-us",
      "description": "Unique per channel"
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published"
      ],
      "default": "draft"
     }
    },
    "required": [
     "title",
     "slug"
    ]
   },
   "UpdatePageDto": {
    "type": "object",
    "properties": {
     "description": {
      "type": "string",
      "nullable": true,
      "maxLength": 2000,
      "description": "Intro (plain text)"
     },
     "image": {
      "type": "string",
      "nullable": true,
      "description": "directus_files id of the hero image"
     },
     "meta_title": {
      "type": "string",
      "nullable": true,
      "maxLength": 255
     },
     "meta_description": {
      "type": "string",
      "nullable": true,
      "maxLength": 500
     },
     "meta_keyword": {
      "type": "string",
      "nullable": true,
      "maxLength": 255
     },
     "tags": {
      "type": "string",
      "nullable": true,
      "maxLength": 255
     },
     "og_image": {
      "type": "string",
      "nullable": true,
      "description": "directus_files id of the og:image"
     },
     "canonical_url": {
      "type": "string",
      "nullable": true,
      "maxLength": 2048,
      "example": "https://shop.example.com/about-us"
     },
     "noindex": {
      "type": "boolean",
      "description": "Ask search engines not to index"
     },
     "title": {
      "type": "string",
      "maxLength": 255
     },
     "slug": {
      "type": "string",
      "maxLength": 120,
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
      "example": "about-us"
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published",
       "archived"
      ]
     }
    }
   },
   "CreateSectionDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 255
     },
     "content": {
      "type": "string",
      "maxLength": 100000,
      "description": "Rich text (HTML). Sanitized server-side with an allow-list."
     },
     "sort": {
      "type": "number",
      "minimum": 0,
      "maximum": 10000
     }
    }
   },
   "ReorderDto": {
    "type": "object",
    "properties": {
     "ids": {
      "description": "Every section id of the page, in the new order",
      "type": "array",
      "items": {
       "type": "number",
       "minimum": 1
      }
     }
    },
    "required": [
     "ids"
    ]
   },
   "UpdateSectionDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 255
     },
     "content": {
      "type": "string",
      "maxLength": 100000,
      "description": "Rich text (HTML). Sanitized server-side with an allow-list."
     },
     "sort": {
      "type": "number",
      "minimum": 0,
      "maximum": 10000
     }
    }
   },
   "CreateTaskDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 200
     },
     "notes": {
      "type": "string",
      "maxLength": 2000
     },
     "due_date": {
      "type": "string",
      "nullable": true,
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
     },
     "priority": {
      "type": "string",
      "enum": [
       "high",
       "medium",
       "low"
      ]
     },
     "business_id": {
      "type": "string",
      "nullable": true
     }
    },
    "required": [
     "title"
    ]
   },
   "UpdateTaskDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 200
     },
     "notes": {
      "type": "string",
      "maxLength": 2000
     },
     "due_date": {
      "type": "string",
      "nullable": true,
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
     },
     "priority": {
      "type": "string",
      "enum": [
       "high",
       "medium",
       "low"
      ]
     },
     "business_id": {
      "type": "string",
      "nullable": true
     },
     "done": {
      "type": "boolean"
     }
    }
   },
   "CreateNoteDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 200
     },
     "body": {
      "type": "string",
      "maxLength": 20000
     }
    },
    "required": [
     "title"
    ]
   },
   "UpdateNoteDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 200
     },
     "body": {
      "type": "string",
      "maxLength": 20000
     }
    }
   },
   "CreateReminderDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 200
     },
     "remind_at": {
      "type": "string"
     },
     "recurrence": {
      "type": "string",
      "enum": [
       "none",
       "daily",
       "weekly",
       "monthly",
       "yearly"
      ]
     },
     "channels": {
      "type": "string",
      "enum": [
       "app",
       "email",
       "sms"
      ]
     },
     "note": {
      "type": "string",
      "maxLength": 500
     }
    },
    "required": [
     "title",
     "remind_at"
    ]
   },
   "UpdateReminderDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 200
     },
     "remind_at": {
      "type": "string"
     },
     "recurrence": {
      "type": "string",
      "enum": [
       "none",
       "daily",
       "weekly",
       "monthly",
       "yearly"
      ]
     },
     "channels": {
      "type": "string",
      "enum": [
       "app",
       "email",
       "sms"
      ]
     },
     "note": {
      "type": "string",
      "maxLength": 500
     },
     "done": {
      "type": "boolean"
     }
    }
   },
   "SnoozeReminderDto": {
    "type": "object",
    "properties": {
     "until": {
      "type": "string"
     },
     "minutes": {
      "type": "number",
      "minimum": 1,
      "maximum": 525600
     }
    }
   },
   "CreateCalendarEventDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 200,
      "example": "Roadmap review"
     },
     "description": {
      "type": "string",
      "maxLength": 5000
     },
     "location": {
      "type": "string",
      "maxLength": 500
     },
     "start_at": {
      "type": "string",
      "example": "2026-10-19T16:00:00Z"
     },
     "end_at": {
      "type": "string",
      "example": "2026-10-19T17:00:00Z"
     },
     "all_day": {
      "type": "boolean",
      "default": false
     },
     "timezone": {
      "type": "string",
      "maxLength": 64,
      "example": "Europe/London"
     },
     "rrule": {
      "type": "string",
      "nullable": true,
      "example": "FREQ=WEEKLY;BYDAY=MO,WE;COUNT=10"
     },
     "color": {
      "type": "string",
      "pattern": "^#[0-9A-Fa-f]{6}$",
      "example": "#3B5BDB"
     },
     "category": {
      "type": "string",
      "maxLength": 50
     },
     "reminders": {
      "example": [
       10,
       60
      ],
      "description": "Minutes before start (max 5, each 0..40320)",
      "type": "array",
      "items": {
       "type": "number",
       "maximum": 40320,
       "minimum": 0
      }
     },
     "channel_id": {
      "type": "string"
     }
    },
    "required": [
     "title",
     "start_at"
    ]
   },
   "UpdateCalendarEventDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 200
     },
     "description": {
      "type": "string",
      "nullable": true,
      "maxLength": 5000
     },
     "location": {
      "type": "string",
      "nullable": true,
      "maxLength": 500
     },
     "start_at": {
      "type": "string"
     },
     "end_at": {
      "type": "string"
     },
     "all_day": {
      "type": "boolean"
     },
     "timezone": {
      "type": "string",
      "maxLength": 64
     },
     "rrule": {
      "type": "string",
      "nullable": true
     },
     "color": {
      "type": "string",
      "nullable": true,
      "pattern": "^#[0-9A-Fa-f]{6}$"
     },
     "category": {
      "type": "string",
      "nullable": true,
      "maxLength": 50
     },
     "reminders": {
      "type": "array",
      "items": {
       "type": "number",
       "maximum": 40320,
       "minimum": 0
      }
     },
     "channel_id": {
      "type": "string",
      "nullable": true
     }
    }
   },
   "CreateVaultItemDto": {
    "type": "object",
    "properties": {
     "label": {
      "type": "string",
      "maxLength": 200,
      "example": "Stripe Dashboard"
     },
     "username": {
      "type": "string",
      "maxLength": 255,
      "example": "billing@example.com"
     },
     "password": {
      "type": "string",
      "maxLength": 1024,
      "example": "correct horse battery staple"
     },
     "url": {
      "type": "string",
      "example": "https://dashboard.stripe.com",
      "description": "Checked by the server against /^(|https?:\\/\\/[^\\s]{1,2040})$/i."
     },
     "notes": {
      "type": "string",
      "maxLength": 2000
     },
     "channel_id": {
      "type": "string"
     }
    },
    "required": [
     "label",
     "password"
    ]
   },
   "UpdateVaultItemDto": {
    "type": "object",
    "properties": {
     "label": {
      "type": "string",
      "maxLength": 200
     },
     "username": {
      "type": "string",
      "nullable": true,
      "maxLength": 255
     },
     "password": {
      "type": "string",
      "maxLength": 1024
     },
     "url": {
      "type": "string",
      "nullable": true,
      "description": "Checked by the server against /^(|https?:\\/\\/[^\\s]{1,2040})$/i."
     },
     "notes": {
      "type": "string",
      "nullable": true,
      "maxLength": 2000
     },
     "channel_id": {
      "type": "string",
      "nullable": true
     }
    }
   },
   "CreateMenuDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 120,
      "example": "Main menu"
     },
     "location": {
      "type": "string",
      "nullable": true,
      "maxLength": 60,
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
      "example": "header",
      "description": "Where it renders"
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published"
      ],
      "default": "draft"
     },
     "sort": {
      "type": "number",
      "minimum": 0,
      "maximum": 10000
     }
    },
    "required": [
     "name"
    ]
   },
   "UpdateMenuDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 120
     },
     "location": {
      "type": "string",
      "nullable": true,
      "maxLength": 60,
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
      "example": "footer"
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published",
       "archived"
      ]
     },
     "sort": {
      "type": "number",
      "minimum": 0,
      "maximum": 10000
     }
    }
   },
   "CreateMenuItemDto": {
    "type": "object",
    "properties": {
     "label": {
      "type": "string",
      "maxLength": 120,
      "example": "Shop"
     },
     "url": {
      "type": "string",
      "example": "/shop"
     },
     "target": {
      "type": "string",
      "enum": [
       "_self",
       "_blank"
      ],
      "default": "_self"
     },
     "parent_id": {
      "type": "number",
      "nullable": true,
      "minimum": 1,
      "description": "Parent item id (same menu) or null"
     },
     "sort": {
      "type": "number",
      "minimum": 0,
      "maximum": 10000
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published",
       "archived"
      ],
      "default": "published"
     }
    },
    "required": [
     "label",
     "url"
    ]
   },
   "MenuItemPositionDto": {
    "type": "object",
    "properties": {
     "id": {
      "type": "number",
      "minimum": 1
     },
     "parent_id": {
      "type": "number",
      "nullable": true,
      "minimum": 1
     },
     "sort": {
      "type": "number",
      "minimum": 0,
      "maximum": 10000
     }
    },
    "required": [
     "id",
     "sort"
    ]
   },
   "ReorderMenuItemsDto": {
    "type": "object",
    "properties": {
     "items": {
      "description": "Every item of the menu with its new parent and sort",
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/MenuItemPositionDto"
      }
     }
    },
    "required": [
     "items"
    ]
   },
   "UpdateMenuItemDto": {
    "type": "object",
    "properties": {
     "label": {
      "type": "string",
      "maxLength": 120
     },
     "url": {
      "type": "string",
      "example": "/about-us"
     },
     "target": {
      "type": "string",
      "enum": [
       "_self",
       "_blank"
      ]
     },
     "parent_id": {
      "type": "number",
      "nullable": true,
      "minimum": 1,
      "description": "New parent id, or null for top level"
     },
     "sort": {
      "type": "number",
      "minimum": 0,
      "maximum": 10000
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published",
       "archived"
      ]
     }
    }
   },
   "CreateTestimonialDto": {
    "type": "object",
    "properties": {
     "role": {
      "type": "string",
      "nullable": true,
      "maxLength": 120,
      "example": "Regular customer"
     },
     "rating": {
      "type": "number",
      "nullable": true,
      "minimum": 1,
      "maximum": 5
     },
     "avatar": {
      "type": "string",
      "nullable": true,
      "description": "directus_files id of the avatar"
     },
     "sort": {
      "type": "number",
      "minimum": 0,
      "maximum": 10000
     },
     "name": {
      "type": "string",
      "maxLength": 120,
      "example": "Zara Reid"
     },
     "content": {
      "type": "string",
      "maxLength": 2000,
      "example": "Best clinic in Leeds!"
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published"
      ],
      "default": "draft"
     }
    },
    "required": [
     "name",
     "content"
    ]
   },
   "UpdateTestimonialDto": {
    "type": "object",
    "properties": {
     "role": {
      "type": "string",
      "nullable": true,
      "maxLength": 120,
      "example": "Regular customer"
     },
     "rating": {
      "type": "number",
      "nullable": true,
      "minimum": 1,
      "maximum": 5
     },
     "avatar": {
      "type": "string",
      "nullable": true,
      "description": "directus_files id of the avatar"
     },
     "sort": {
      "type": "number",
      "minimum": 0,
      "maximum": 10000
     },
     "name": {
      "type": "string",
      "maxLength": 120
     },
     "content": {
      "type": "string",
      "maxLength": 2000
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published",
       "archived"
      ]
     }
    }
   },
   "LinkDto": {
    "type": "object",
    "properties": {
     "label": {
      "type": "string",
      "maxLength": 40
     },
     "url": {
      "type": "string",
      "example": "/contact"
     },
     "target": {
      "type": "string",
      "enum": [
       "_self",
       "_blank"
      ]
     }
    }
   },
   "AnnouncementDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "minLength": 2,
      "maxLength": 140
     },
     "body": {
      "type": "string",
      "minLength": 0,
      "maxLength": 1000
     },
     "level": {
      "type": "string",
      "enum": [
       "info",
       "warning",
       "critical"
      ]
     },
     "ends_at": {
      "type": "string"
     },
     "cascade": {
      "type": "boolean",
      "description": "Also show on every channel below this one"
     }
    },
    "required": [
     "title"
    ]
   },
   "HeaderConfigDto": {
    "type": "object",
    "properties": {
     "logo": {
      "type": "string",
      "nullable": true,
      "description": "directus_files id"
     },
     "sticky": {
      "type": "boolean"
     },
     "menu_id": {
      "type": "number",
      "nullable": true,
      "minimum": 1,
      "description": "Menu id (this channel)"
     },
     "show_search": {
      "type": "boolean"
     },
     "cta": {
      "nullable": true,
      "allOf": [
       {
        "$ref": "#/components/schemas/LinkDto"
       }
      ]
     },
     "announcement": {
      "nullable": true,
      "allOf": [
       {
        "$ref": "#/components/schemas/AnnouncementDto"
       }
      ]
     }
    }
   },
   "FooterColumnDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 60
     },
     "menu_id": {
      "type": "number",
      "nullable": true,
      "minimum": 1,
      "description": "Menu id (this channel)"
     },
     "text": {
      "type": "string",
      "maxLength": 500,
      "description": "Plain text"
     }
    }
   },
   "SocialLinkDto": {
    "type": "object",
    "properties": {
     "network": {
      "type": "string",
      "enum": [
       "facebook",
       "instagram",
       "x",
       "twitter",
       "linkedin",
       "youtube",
       "tiktok",
       "pinterest",
       "whatsapp",
       "telegram",
       "github"
      ]
     },
     "url": {
      "type": "string",
      "maxLength": 500,
      "example": "https://instagram.com/acme"
     }
    }
   },
   "FooterConfigDto": {
    "type": "object",
    "properties": {
     "columns": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/FooterColumnDto"
      }
     },
     "copyright": {
      "type": "string",
      "maxLength": 200
     },
     "social": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/SocialLinkDto"
      }
     },
     "show_newsletter": {
      "type": "boolean"
     }
    }
   },
   "ThemeConfigDto": {
    "type": "object",
    "properties": {
     "primary_color": {
      "type": "string",
      "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$",
      "example": "#4F46E5"
     },
     "secondary_color": {
      "type": "string",
      "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$",
      "example": "#0EA5E9"
     },
     "background_color": {
      "type": "string",
      "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$",
      "example": "#FFFFFF"
     },
     "text_color": {
      "type": "string",
      "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$",
      "example": "#111827"
     },
     "font_family": {
      "type": "string",
      "pattern": "^[A-Za-z0-9 -]{1,60}$",
      "example": "Inter"
     },
     "border_radius": {
      "type": "number",
      "minimum": 0,
      "maximum": 32
     },
     "mode": {
      "type": "string",
      "enum": [
       "light",
       "dark",
       "auto"
      ]
     }
    }
   },
   "SiteLayoutDto": {
    "type": "object",
    "properties": {
     "header": {
      "$ref": "#/components/schemas/HeaderConfigDto"
     },
     "footer": {
      "$ref": "#/components/schemas/FooterConfigDto"
     },
     "theme": {
      "$ref": "#/components/schemas/ThemeConfigDto"
     }
    }
   },
   "CreateBlogPostDto": {
    "type": "object",
    "properties": {
     "excerpt": {
      "type": "string",
      "nullable": true,
      "maxLength": 300
     },
     "body_html": {
      "type": "string",
      "maxLength": 100000,
      "description": "Rich text; sanitized on save"
     },
     "cover": {
      "type": "string",
      "nullable": true,
      "description": "directus_files id of the cover image"
     },
     "category": {
      "type": "string",
      "nullable": true,
      "maxLength": 60,
      "example": "News"
     },
     "tags": {
      "maxItems": 20,
      "type": "array",
      "items": {
       "type": "string",
       "maxLength": 40
      }
     },
     "featured": {
      "type": "boolean"
     },
     "publish_at": {
      "type": "string",
      "nullable": true,
      "description": "Required when status is scheduled"
     },
     "seo_title": {
      "type": "string",
      "nullable": true,
      "maxLength": 70
     },
     "seo_description": {
      "type": "string",
      "nullable": true,
      "maxLength": 170
     },
     "title": {
      "type": "string",
      "maxLength": 200,
      "example": "Our autumn collection is here"
     },
     "slug": {
      "type": "string",
      "maxLength": 120,
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
      "description": "Lower-case kebab; made from the title when omitted",
      "example": "autumn-collection"
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "scheduled",
       "published",
       "archived"
      ],
      "default": "draft"
     }
    },
    "required": [
     "title"
    ]
   },
   "UpdateBlogPostDto": {
    "type": "object",
    "properties": {
     "excerpt": {
      "type": "string",
      "nullable": true,
      "maxLength": 300
     },
     "body_html": {
      "type": "string",
      "maxLength": 100000,
      "description": "Rich text; sanitized on save"
     },
     "cover": {
      "type": "string",
      "nullable": true,
      "description": "directus_files id of the cover image"
     },
     "category": {
      "type": "string",
      "nullable": true,
      "maxLength": 60,
      "example": "News"
     },
     "tags": {
      "maxItems": 20,
      "type": "array",
      "items": {
       "type": "string",
       "maxLength": 40
      }
     },
     "featured": {
      "type": "boolean"
     },
     "publish_at": {
      "type": "string",
      "nullable": true,
      "description": "Required when status is scheduled"
     },
     "seo_title": {
      "type": "string",
      "nullable": true,
      "maxLength": 70
     },
     "seo_description": {
      "type": "string",
      "nullable": true,
      "maxLength": 170
     },
     "title": {
      "type": "string",
      "maxLength": 200
     },
     "slug": {
      "type": "string",
      "maxLength": 120,
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "scheduled",
       "published",
       "archived"
      ]
     }
    }
   },
   "CreateSurfaceDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "example": "start",
      "description": "1–48 lower-case letters, digits or dashes"
     },
     "title": {
      "type": "string",
      "example": "Start page",
      "maxLength": 80
     },
     "description": {
      "type": "string",
      "maxLength": 300
     },
     "blocks": {
      "type": "array",
      "items": {
       "type": "object"
      },
      "description": "Ordered blocks. Each is {type: banner|shortcut|ad|text, id? (keep to update, omit for new), enabled?, key?, starts_at?, ends_at?, locales?, countries? | exclude_countries?, platforms?} plus its type's fields (see docs/home-surfaces.md)."
     }
    },
    "required": [
     "name"
    ]
   },
   "CheckBlockDto": {
    "type": "object",
    "properties": {
     "block": {
      "type": "object",
      "additionalProperties": true
     }
    },
    "required": [
     "block"
    ]
   },
   "ReplaceSurfaceDto": {
    "type": "object",
    "properties": {
     "version": {
      "type": "number",
      "description": "The version you are replacing (or send If-Match: \"<version>\")"
     },
     "title": {
      "type": "string",
      "maxLength": 80
     },
     "description": {
      "type": "string",
      "maxLength": 300,
      "nullable": true
     },
     "blocks": {
      "type": "array",
      "items": {
       "type": "object"
      },
      "description": "Ordered blocks. Each is {type: banner|shortcut|ad|text, id? (keep to update, omit for new), enabled?, key?, starts_at?, ends_at?, locales?, countries? | exclude_countries?, platforms?} plus its type's fields (see docs/home-surfaces.md)."
     }
    }
   },
   "AddBlockDto": {
    "type": "object",
    "properties": {
     "version": {
      "type": "number",
      "description": "The version you saw (or send If-Match: \"<version>\")"
     },
     "block": {
      "type": "object",
      "additionalProperties": true,
      "description": "Ordered blocks. Each is {type: banner|shortcut|ad|text, id? (keep to update, omit for new), enabled?, key?, starts_at?, ends_at?, locales?, countries? | exclude_countries?, platforms?} plus its type's fields (see docs/home-surfaces.md)."
     },
     "position": {
      "type": "number",
      "description": "Index to insert at (default: the end)"
     }
    },
    "required": [
     "block"
    ]
   },
   "ReorderBlocksDto": {
    "type": "object",
    "properties": {
     "version": {
      "type": "number",
      "description": "The version you saw (or send If-Match: \"<version>\")"
     },
     "ids": {
      "description": "Every block id, in the new order",
      "type": "array",
      "items": {
       "type": "string"
      }
     }
    },
    "required": [
     "ids"
    ]
   },
   "UpdateBlockDto": {
    "type": "object",
    "properties": {
     "version": {
      "type": "number",
      "description": "The version you saw (or send If-Match: \"<version>\")"
     },
     "block": {
      "type": "object",
      "additionalProperties": true,
      "description": "Fields to change; null clears a field. The type can't change."
     }
    },
    "required": [
     "block"
    ]
   },
   "VersionDto": {
    "type": "object",
    "properties": {
     "version": {
      "type": "number",
      "description": "The version you saw (or send If-Match: \"<version>\")"
     }
    }
   },
   "DocTocEntryDto": {
    "type": "object",
    "properties": {
     "depth": {
      "type": "number",
      "example": 2
     },
     "text": {
      "type": "string",
      "example": "Refresh tokens"
     },
     "id": {
      "type": "string",
      "example": "refresh-tokens",
      "description": "Anchor id (rehype-slug / github-slugger)"
     }
    },
    "required": [
     "depth",
     "text",
     "id"
    ]
   },
   "DocAdminDto": {
    "type": "object",
    "properties": {
     "id": {
      "type": "number",
      "example": 12
     },
     "channel_id": {
      "type": "string",
      "format": "uuid"
     },
     "kind": {
      "type": "string",
      "enum": [
       "page",
       "group"
      ]
     },
     "version": {
      "type": "string",
      "example": "v1"
     },
     "parent_id": {
      "type": "number",
      "nullable": true,
      "example": 10
     },
     "slug": {
      "type": "string",
      "example": "sessions"
     },
     "path": {
      "type": "string",
      "example": "guides/auth/sessions"
     },
     "sort": {
      "type": "number",
      "example": 0
     },
     "title": {
      "type": "string",
      "example": "Sessions"
     },
     "nav_title": {
      "type": "string",
      "nullable": true
     },
     "nav_hidden": {
      "type": "boolean"
     },
     "description": {
      "type": "string",
      "nullable": true
     },
     "body_md": {
      "type": "string",
      "description": "Safe, canonical Markdown"
     },
     "toc": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/DocTocEntryDto"
      }
     },
     "reading_minutes": {
      "type": "number",
      "example": 3
     },
     "word_count": {
      "type": "number",
      "example": 512
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published",
       "archived"
      ]
     },
     "deprecated": {
      "type": "boolean"
     },
     "deprecated_banner": {
      "type": "string",
      "nullable": true
     },
     "seo_title": {
      "type": "string",
      "nullable": true
     },
     "seo_description": {
      "type": "string",
      "nullable": true
     },
     "author_user_id": {
      "type": "string",
      "nullable": true,
      "format": "uuid"
     },
     "updated_by_user_id": {
      "type": "string",
      "nullable": true,
      "format": "uuid"
     },
     "date_created": {
      "type": "string",
      "nullable": true,
      "format": "date-time"
     },
     "date_updated": {
      "type": "string",
      "nullable": true,
      "format": "date-time"
     }
    },
    "required": [
     "id",
     "channel_id",
     "kind",
     "version",
     "parent_id",
     "slug",
     "path",
     "sort",
     "title",
     "nav_title",
     "nav_hidden",
     "description",
     "body_md",
     "toc",
     "reading_minutes",
     "word_count",
     "status",
     "deprecated",
     "deprecated_banner",
     "seo_title",
     "seo_description",
     "author_user_id",
     "updated_by_user_id",
     "date_created",
     "date_updated"
    ]
   },
   "DocListResultDto": {
    "type": "object",
    "properties": {
     "data": {
      "description": "Pages without body_md",
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/DocAdminDto"
      }
     },
     "page": {
      "type": "number",
      "example": 1
     },
     "limit": {
      "type": "number",
      "example": 20
     },
     "total": {
      "type": "number",
      "example": 42
     },
     "hasMore": {
      "type": "boolean"
     }
    },
    "required": [
     "data",
     "page",
     "limit",
     "total",
     "hasMore"
    ]
   },
   "DocTreeNodeDto": {
    "type": "object",
    "properties": {
     "id": {
      "type": "number",
      "example": 12
     },
     "kind": {
      "type": "string",
      "enum": [
       "page",
       "group"
      ]
     },
     "title": {
      "type": "string",
      "example": "Sessions"
     },
     "nav_title": {
      "type": "string",
      "nullable": true
     },
     "slug": {
      "type": "string",
      "example": "sessions"
     },
     "path": {
      "type": "string",
      "example": "guides/auth/sessions"
     },
     "sort": {
      "type": "number"
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published",
       "archived"
      ]
     },
     "nav_hidden": {
      "type": "boolean"
     },
     "deprecated": {
      "type": "boolean"
     },
     "date_updated": {
      "type": "string",
      "nullable": true,
      "format": "date-time"
     },
     "children": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/DocTreeNodeDto"
      }
     }
    },
    "required": [
     "id",
     "kind",
     "title",
     "nav_title",
     "slug",
     "path",
     "sort",
     "status",
     "nav_hidden",
     "deprecated",
     "date_updated",
     "children"
    ]
   },
   "DocTreeResultDto": {
    "type": "object",
    "properties": {
     "version": {
      "type": "string",
      "example": "v1"
     },
     "total": {
      "type": "number",
      "example": 42
     },
     "tree": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/DocTreeNodeDto"
      }
     }
    },
    "required": [
     "version",
     "total",
     "tree"
    ]
   },
   "PreviewDocDto": {
    "type": "object",
    "properties": {
     "body_md": {
      "type": "string",
      "maxLength": 100000,
      "example": "Hi <b>there</b>\n\n:::tip Did you know\nIt works.\n:::",
      "description": "Markdown to check"
     }
    },
    "required": [
     "body_md"
    ]
   },
   "DocCodeBlockDto": {
    "type": "object",
    "properties": {
     "lang": {
      "type": "string",
      "nullable": true,
      "example": "ts"
     },
     "title": {
      "type": "string",
      "nullable": true,
      "example": "client.ts"
     },
     "group": {
      "type": "number",
      "nullable": true,
      "description": "Index of its :::code-group, else null"
     }
    },
    "required": [
     "lang",
     "title",
     "group"
    ]
   },
   "DocWarningDto": {
    "type": "object",
    "properties": {
     "code": {
      "type": "string",
      "example": "HTML_ESCAPED",
      "enum": [
       "HTML_ESCAPED",
       "HTML_COMMENT_REMOVED",
       "MDX_REMOVED",
       "UNSAFE_URL",
       "CODE_LANGUAGE_REMOVED",
       "CODE_META_CLEANED",
       "DIRECTIVE_AS_TEXT",
       "UNKNOWN_CONTAINER",
       "ATTRIBUTES_REMOVED",
       "CODE_GROUP_CONTENT"
      ]
     },
     "message": {
      "type": "string",
      "example": "Raw HTML is not allowed in docs; it is shown as text."
     },
     "line": {
      "type": "number",
      "nullable": true,
      "example": 3
     }
    },
    "required": [
     "code",
     "message",
     "line"
    ]
   },
   "DocPreviewResultDto": {
    "type": "object",
    "properties": {
     "body_md": {
      "type": "string",
      "example": "Hi \\<b>there\\</b>\n\n:::tip[Did you know]\nIt works.\n:::"
     },
     "toc": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/DocTocEntryDto"
      }
     },
     "reading_minutes": {
      "type": "number"
     },
     "word_count": {
      "type": "number"
     },
     "code_blocks": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/DocCodeBlockDto"
      }
     },
     "callouts": {
      "type": "number"
     },
     "warnings": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/DocWarningDto"
      }
     }
    },
    "required": [
     "body_md",
     "toc",
     "reading_minutes",
     "word_count",
     "code_blocks",
     "callouts",
     "warnings"
    ]
   },
   "ReorderDocItemDto": {
    "type": "object",
    "properties": {
     "id": {
      "type": "number",
      "example": 12
     },
     "parent_id": {
      "type": "number",
      "nullable": true,
      "description": "Omitted = parent unchanged; null = top level"
     },
     "sort": {
      "type": "number",
      "minimum": -100000,
      "maximum": 100000,
      "example": 0
     }
    },
    "required": [
     "id",
     "sort"
    ]
   },
   "ReorderDocsDto": {
    "type": "object",
    "properties": {
     "version": {
      "type": "string",
      "pattern": "^(?!latest$)[a-z0-9][a-z0-9._-]{0,31}$",
      "example": "v1"
     },
     "items": {
      "maxItems": 500,
      "description": "Up to 500 moves, applied together",
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/ReorderDocItemDto"
      }
     }
    },
    "required": [
     "version",
     "items"
    ]
   },
   "DocReorderResultDto": {
    "type": "object",
    "properties": {
     "version": {
      "type": "string",
      "example": "v1"
     },
     "moved": {
      "type": "number",
      "example": 4,
      "description": "Pages whose parent, order or path changed"
     }
    },
    "required": [
     "version",
     "moved"
    ]
   },
   "CreateDocDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 200,
      "example": "Sessions"
     },
     "kind": {
      "type": "string",
      "enum": [
       "page",
       "group"
      ],
      "default": "page",
      "description": "page: has content; group: a sidebar heading only (no body, not a page of its own)"
     },
     "slug": {
      "type": "string",
      "maxLength": 80,
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
      "example": "sessions",
      "description": "This page's path segment (default: from the title)"
     },
     "parent_id": {
      "type": "number",
      "nullable": true,
      "example": 12,
      "description": "Parent page id (same channel and version); null = top level"
     },
     "version": {
      "type": "string",
      "pattern": "^(?!latest$)[a-z0-9][a-z0-9._-]{0,31}$",
      "example": "v1",
      "description": "Version tag (default: the channel's latest version, else v1). Fixed once created."
     },
     "sort": {
      "type": "number",
      "minimum": -100000,
      "maximum": 100000,
      "example": 10,
      "default": 0,
      "description": "Position among its siblings (lower first)"
     },
     "nav_title": {
      "type": "string",
      "maxLength": 80,
      "example": "Sessions",
      "description": "Shorter label for the sidebar"
     },
     "nav_hidden": {
      "type": "boolean",
      "default": false,
      "description": "Kept out of the sidebar and prev/next (still reachable by path)"
     },
     "description": {
      "type": "string",
      "maxLength": 300,
      "example": "How sign-in sessions work and how to refresh them."
     },
     "body_md": {
      "type": "string",
      "maxLength": 100000,
      "example": "## Refresh tokens\n\n:::warning[Keep it secret]\nNever ship a server key.\n:::\n\n```ts title=\"client.ts\"\nawait client.refresh()\n```",
      "description": "Markdown (docs/cms-docs.md); made safe and canonical on save"
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published",
       "archived"
      ],
      "default": "draft"
     },
     "deprecated": {
      "type": "boolean",
      "default": false,
      "description": "Show a deprecation banner on this page"
     },
     "deprecated_banner": {
      "type": "string",
      "maxLength": 300,
      "example": "Use sessions instead."
     },
     "seo_title": {
      "type": "string",
      "maxLength": 70
     },
     "seo_description": {
      "type": "string",
      "maxLength": 170
     }
    },
    "required": [
     "title"
    ]
   },
   "DocWriteResultDto": {
    "type": "object",
    "properties": {
     "id": {
      "type": "number",
      "example": 12
     },
     "channel_id": {
      "type": "string",
      "format": "uuid"
     },
     "kind": {
      "type": "string",
      "enum": [
       "page",
       "group"
      ]
     },
     "version": {
      "type": "string",
      "example": "v1"
     },
     "parent_id": {
      "type": "number",
      "nullable": true,
      "example": 10
     },
     "slug": {
      "type": "string",
      "example": "sessions"
     },
     "path": {
      "type": "string",
      "example": "guides/auth/sessions"
     },
     "sort": {
      "type": "number",
      "example": 0
     },
     "title": {
      "type": "string",
      "example": "Sessions"
     },
     "nav_title": {
      "type": "string",
      "nullable": true
     },
     "nav_hidden": {
      "type": "boolean"
     },
     "description": {
      "type": "string",
      "nullable": true
     },
     "body_md": {
      "type": "string",
      "description": "Safe, canonical Markdown"
     },
     "toc": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/DocTocEntryDto"
      }
     },
     "reading_minutes": {
      "type": "number",
      "example": 3
     },
     "word_count": {
      "type": "number",
      "example": 512
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published",
       "archived"
      ]
     },
     "deprecated": {
      "type": "boolean"
     },
     "deprecated_banner": {
      "type": "string",
      "nullable": true
     },
     "seo_title": {
      "type": "string",
      "nullable": true
     },
     "seo_description": {
      "type": "string",
      "nullable": true
     },
     "author_user_id": {
      "type": "string",
      "nullable": true,
      "format": "uuid"
     },
     "updated_by_user_id": {
      "type": "string",
      "nullable": true,
      "format": "uuid"
     },
     "date_created": {
      "type": "string",
      "nullable": true,
      "format": "date-time"
     },
     "date_updated": {
      "type": "string",
      "nullable": true,
      "format": "date-time"
     },
     "warnings": {
      "description": "What was changed to make the Markdown safe (empty when nothing)",
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/DocWarningDto"
      }
     }
    },
    "required": [
     "id",
     "channel_id",
     "kind",
     "version",
     "parent_id",
     "slug",
     "path",
     "sort",
     "title",
     "nav_title",
     "nav_hidden",
     "description",
     "body_md",
     "toc",
     "reading_minutes",
     "word_count",
     "status",
     "deprecated",
     "deprecated_banner",
     "seo_title",
     "seo_description",
     "author_user_id",
     "updated_by_user_id",
     "date_created",
     "date_updated",
     "warnings"
    ]
   },
   "UpdateDocDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "maxLength": 200
     },
     "slug": {
      "type": "string",
      "maxLength": 80,
      "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
      "description": "A new slug moves the pages under this one too"
     },
     "parent_id": {
      "type": "number",
      "nullable": true,
      "description": "A new parent moves the pages under this one too"
     },
     "sort": {
      "type": "number",
      "minimum": -100000,
      "maximum": 100000
     },
     "nav_title": {
      "type": "string",
      "nullable": true,
      "maxLength": 80
     },
     "nav_hidden": {
      "type": "boolean"
     },
     "description": {
      "type": "string",
      "nullable": true,
      "maxLength": 300
     },
     "body_md": {
      "type": "string",
      "maxLength": 100000
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "published",
       "archived"
      ]
     },
     "deprecated": {
      "type": "boolean"
     },
     "deprecated_banner": {
      "type": "string",
      "nullable": true,
      "maxLength": 300
     },
     "seo_title": {
      "type": "string",
      "nullable": true,
      "maxLength": 70
     },
     "seo_description": {
      "type": "string",
      "nullable": true,
      "maxLength": 170
     }
    }
   },
   "DocDeletedDto": {
    "type": "object",
    "properties": {
     "id": {
      "type": "number",
      "example": 12
     },
     "deleted": {
      "type": "boolean",
      "example": true
     }
    },
    "required": [
     "id",
     "deleted"
    ]
   },
   "DocVersionAdminDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "example": "v2"
     },
     "label": {
      "type": "string",
      "nullable": true
     },
     "is_latest": {
      "type": "boolean",
      "description": "What `latest` resolves to for readers now"
     },
     "marked_latest": {
      "type": "boolean",
      "description": "Marked latest in its settings (readers fall back while it has no live pages)"
     },
     "deprecated": {
      "type": "boolean"
     },
     "banner": {
      "type": "string",
      "nullable": true
     },
     "sort": {
      "type": "number"
     },
     "pages": {
      "type": "number",
      "example": 42
     },
     "published": {
      "type": "number",
      "example": 40
     },
     "live": {
      "type": "boolean",
      "description": "Has live pages (readers can open it)"
     },
     "configured": {
      "type": "boolean",
      "description": "Has a settings row"
     }
    },
    "required": [
     "name",
     "label",
     "is_latest",
     "marked_latest",
     "deprecated",
     "banner",
     "sort",
     "pages",
     "published",
     "live",
     "configured"
    ]
   },
   "DocVersionsAdminResultDto": {
    "type": "object",
    "properties": {
     "latest_version": {
      "type": "string",
      "nullable": true,
      "example": "v2"
     },
     "versions": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/DocVersionAdminDto"
      }
     }
    },
    "required": [
     "latest_version",
     "versions"
    ]
   },
   "PutDocVersionDto": {
    "type": "object",
    "properties": {
     "label": {
      "type": "string",
      "nullable": true,
      "maxLength": 60,
      "example": "v2 (current)"
     },
     "is_latest": {
      "type": "boolean",
      "description": "Make this the version `latest` points to (it must have live pages)"
     },
     "deprecated": {
      "type": "boolean",
      "description": "Every page of this version shows a deprecation banner"
     },
     "banner": {
      "type": "string",
      "nullable": true,
      "maxLength": 300,
      "example": "v1 is no longer maintained."
     },
     "sort": {
      "type": "number",
      "minimum": -100000,
      "maximum": 100000,
      "description": "Order in the version switcher (lower first)"
     }
    }
   },
   "DocVersionRecordDto": {
    "type": "object",
    "properties": {
     "id": {
      "type": "number"
     },
     "channel_id": {
      "type": "string",
      "format": "uuid"
     },
     "name": {
      "type": "string",
      "example": "v2"
     },
     "label": {
      "type": "string",
      "nullable": true
     },
     "is_latest": {
      "type": "boolean"
     },
     "deprecated": {
      "type": "boolean"
     },
     "banner": {
      "type": "string",
      "nullable": true
     },
     "sort": {
      "type": "number"
     }
    },
    "required": [
     "id",
     "channel_id",
     "name",
     "label",
     "is_latest",
     "deprecated",
     "banner",
     "sort"
    ]
   },
   "CloneDocVersionDto": {
    "type": "object",
    "properties": {
     "from": {
      "type": "string",
      "pattern": "^(?!latest$)[a-z0-9][a-z0-9._-]{0,31}$",
      "example": "v1",
      "description": "Copy every page of this version"
     },
     "as_draft": {
      "type": "boolean",
      "default": true,
      "description": "Copied pages start as drafts"
     }
    },
    "required": [
     "from"
    ]
   },
   "DocCloneResultDto": {
    "type": "object",
    "properties": {
     "version": {
      "type": "string",
      "example": "v2"
     },
     "from": {
      "type": "string",
      "example": "v1"
     },
     "copied": {
      "type": "number",
      "example": 42
     },
     "as_draft": {
      "type": "boolean"
     }
    },
    "required": [
     "version",
     "from",
     "copied",
     "as_draft"
    ]
   },
   "DocVersionDeletedDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "example": "v0"
     },
     "deleted": {
      "type": "boolean",
      "example": true
     }
    },
    "required": [
     "name",
     "deleted"
    ]
   },
   "PublicDocVersionDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "example": "v2"
     },
     "label": {
      "type": "string",
      "example": "v2 (current)"
     },
     "is_latest": {
      "type": "boolean"
     },
     "deprecated": {
      "type": "boolean"
     },
     "banner": {
      "type": "string",
      "nullable": true
     }
    },
    "required": [
     "name",
     "label",
     "is_latest",
     "deprecated",
     "banner"
    ]
   },
   "PublicDocVersionsDto": {
    "type": "object",
    "properties": {
     "latest_version": {
      "type": "string",
      "nullable": true,
      "example": "v2"
     },
     "versions": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/PublicDocVersionDto"
      }
     }
    },
    "required": [
     "latest_version",
     "versions"
    ]
   },
   "DocDeprecationDto": {
    "type": "object",
    "properties": {
     "deprecated": {
      "type": "boolean"
     },
     "banner": {
      "type": "string",
      "nullable": true,
      "example": "You are reading the docs for v1, which is deprecated."
     }
    },
    "required": [
     "deprecated",
     "banner"
    ]
   },
   "PublicNavNodeDto": {
    "type": "object",
    "properties": {
     "id": {
      "type": "number",
      "example": 12
     },
     "kind": {
      "type": "string",
      "enum": [
       "page",
       "group"
      ],
      "description": "group: a heading without a page (don't link it)"
     },
     "title": {
      "type": "string",
      "example": "Sessions"
     },
     "path": {
      "type": "string",
      "example": "guides/auth/sessions"
     },
     "deprecated": {
      "type": "boolean"
     },
     "children": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/PublicNavNodeDto"
      }
     }
    },
    "required": [
     "id",
     "kind",
     "title",
     "path",
     "deprecated",
     "children"
    ]
   },
   "PublicDocNavDto": {
    "type": "object",
    "properties": {
     "version": {
      "type": "string",
      "example": "v2"
     },
     "label": {
      "type": "string",
      "example": "v2 (current)"
     },
     "latest_version": {
      "type": "string",
      "example": "v2"
     },
     "is_latest": {
      "type": "boolean"
     },
     "deprecation": {
      "description": "The version's own deprecation",
      "allOf": [
       {
        "$ref": "#/components/schemas/DocDeprecationDto"
       }
      ]
     },
     "nav": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/PublicNavNodeDto"
      }
     }
    },
    "required": [
     "version",
     "label",
     "latest_version",
     "is_latest",
     "deprecation",
     "nav"
    ]
   },
   "DocCrumbDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "example": "Tokens"
     },
     "path": {
      "type": "string",
      "example": "guides/auth/tokens"
     },
     "kind": {
      "type": "string",
      "enum": [
       "page",
       "group"
      ],
      "example": "page"
     }
    },
    "required": [
     "title",
     "path",
     "kind"
    ]
   },
   "DocLinkDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "example": "Tokens"
     },
     "path": {
      "type": "string",
      "example": "guides/auth/tokens"
     }
    },
    "required": [
     "title",
     "path"
    ]
   },
   "PublicOtherVersionDto": {
    "type": "object",
    "properties": {
     "version": {
      "type": "string",
      "example": "v1"
     },
     "label": {
      "type": "string",
      "example": "v1"
     },
     "is_latest": {
      "type": "boolean"
     },
     "path": {
      "type": "string",
      "example": "guides/auth/sessions",
      "description": "This page in that version, else that version's first page"
     },
     "same_page": {
      "type": "boolean",
      "description": "false when path is that version's first page instead"
     }
    },
    "required": [
     "version",
     "label",
     "is_latest",
     "path",
     "same_page"
    ]
   },
   "PublicDocPageDto": {
    "type": "object",
    "properties": {
     "id": {
      "type": "number",
      "example": 12
     },
     "version": {
      "type": "string",
      "example": "v2"
     },
     "slug": {
      "type": "string",
      "example": "sessions"
     },
     "path": {
      "type": "string",
      "example": "guides/auth/sessions"
     },
     "title": {
      "type": "string",
      "example": "Sessions"
     },
     "nav_title": {
      "type": "string",
      "nullable": true
     },
     "description": {
      "type": "string",
      "nullable": true
     },
     "body_md": {
      "type": "string",
      "example": "## Refresh tokens\n\nUse the refresh token…"
     },
     "toc": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/DocTocEntryDto"
      }
     },
     "reading_minutes": {
      "type": "number",
      "example": 3
     },
     "word_count": {
      "type": "number",
      "example": 512
     },
     "seo_title": {
      "type": "string",
      "nullable": true
     },
     "seo_description": {
      "type": "string",
      "nullable": true
     },
     "date_created": {
      "type": "string",
      "nullable": true,
      "format": "date-time"
     },
     "date_updated": {
      "type": "string",
      "nullable": true,
      "format": "date-time"
     },
     "is_latest": {
      "type": "boolean"
     },
     "latest_version": {
      "type": "string",
      "example": "v2"
     },
     "deprecation": {
      "$ref": "#/components/schemas/DocDeprecationDto"
     },
     "breadcrumbs": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/DocCrumbDto"
      }
     },
     "prev": {
      "nullable": true,
      "allOf": [
       {
        "$ref": "#/components/schemas/DocLinkDto"
       }
      ]
     },
     "next": {
      "nullable": true,
      "allOf": [
       {
        "$ref": "#/components/schemas/DocLinkDto"
       }
      ]
     },
     "other_versions": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/PublicOtherVersionDto"
      }
     }
    },
    "required": [
     "id",
     "version",
     "slug",
     "path",
     "title",
     "nav_title",
     "description",
     "body_md",
     "toc",
     "reading_minutes",
     "word_count",
     "seo_title",
     "seo_description",
     "date_created",
     "date_updated",
     "is_latest",
     "latest_version",
     "deprecation",
     "breadcrumbs",
     "prev",
     "next",
     "other_versions"
    ]
   },
   "DocHeadingHitDto": {
    "type": "object",
    "properties": {
     "depth": {
      "type": "number",
      "example": 2
     },
     "text": {
      "type": "string",
      "example": "Refresh tokens"
     },
     "id": {
      "type": "string",
      "example": "refresh-tokens",
      "description": "Anchor id (rehype-slug / github-slugger)"
     },
     "highlights": {
      "type": "array",
      "items": {
       "type": "array",
       "items": {
        "type": "integer"
       },
       "minItems": 2,
       "maxItems": 2
      },
      "example": [
       [
        0,
        7
       ]
      ]
     }
    },
    "required": [
     "depth",
     "text",
     "id",
     "highlights"
    ]
   },
   "DocHighlightsDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "array",
      "items": {
       "type": "array",
       "items": {
        "type": "integer"
       },
       "minItems": 2,
       "maxItems": 2
      },
      "example": [
       [
        0,
        7
       ]
      ],
      "description": "[start, end) offsets in title"
     },
     "excerpt": {
      "type": "array",
      "items": {
       "type": "array",
       "items": {
        "type": "integer"
       },
       "minItems": 2,
       "maxItems": 2
      },
      "example": [
       [
        12,
        19
       ]
      ],
      "description": "[start, end) offsets in excerpt"
     }
    },
    "required": [
     "title",
     "excerpt"
    ]
   },
   "PublicDocSearchHitDto": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string",
      "example": "Sessions"
     },
     "path": {
      "type": "string",
      "example": "guides/auth/sessions"
     },
     "version": {
      "type": "string",
      "example": "v2"
     },
     "breadcrumbs": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/DocCrumbDto"
      }
     },
     "excerpt": {
      "type": "string",
      "nullable": true,
      "example": "…Use the refresh token to get a new session…"
     },
     "headings": {
      "description": "Headings containing a query word; link as /<path>#<id>",
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/DocHeadingHitDto"
      }
     },
     "highlights": {
      "$ref": "#/components/schemas/DocHighlightsDto"
     },
     "score": {
      "type": "number",
      "example": 61
     }
    },
    "required": [
     "title",
     "path",
     "version",
     "breadcrumbs",
     "excerpt",
     "headings",
     "highlights",
     "score"
    ]
   },
   "PublicDocSearchDto": {
    "type": "object",
    "properties": {
     "query": {
      "type": "string",
      "example": "refresh token"
     },
     "version": {
      "type": "string",
      "nullable": true,
      "example": "v2"
     },
     "latest_version": {
      "type": "string",
      "nullable": true,
      "example": "v2"
     },
     "is_latest": {
      "type": "boolean"
     },
     "total": {
      "type": "number",
      "example": 3,
      "description": "Every live page that matches"
     },
     "hits": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/PublicDocSearchHitDto"
      }
     }
    },
    "required": [
     "query",
     "version",
     "latest_version",
     "is_latest",
     "total",
     "hits"
    ]
   },
   "CreateTicketDto": {
    "type": "object",
    "properties": {
     "attachment_ids": {
      "description": "Drive file ids you uploaded (max 10)",
      "type": "array",
      "items": {
       "type": "number",
       "minimum": 1
      }
     },
     "channel_id": {
      "type": "string",
      "description": "Channel the ticket is for"
     },
     "subject": {
      "type": "string",
      "maxLength": 200,
      "example": "Refund for a failed payment"
     },
     "category": {
      "type": "string",
      "maxLength": 60,
      "example": "Billing and purchases"
     },
     "priority": {
      "type": "string",
      "enum": [
       "low",
       "normal",
       "high",
       "urgent"
      ],
      "default": "normal"
     },
     "message": {
      "type": "string",
      "maxLength": 10000,
      "description": "First message"
     }
    },
    "required": [
     "channel_id",
     "subject",
     "category",
     "message"
    ]
   },
   "ReplyDto": {
    "type": "object",
    "properties": {
     "attachment_ids": {
      "description": "Drive file ids you uploaded (max 10)",
      "type": "array",
      "items": {
       "type": "number",
       "minimum": 1
      }
     },
     "message": {
      "type": "string",
      "maxLength": 10000
     }
    },
    "required": [
     "message"
    ]
   },
   "StaffReplyDto": {
    "type": "object",
    "properties": {
     "attachment_ids": {
      "description": "Drive file ids you uploaded (max 10)",
      "type": "array",
      "items": {
       "type": "number",
       "minimum": 1
      }
     },
     "message": {
      "type": "string",
      "maxLength": 10000
     },
     "internal": {
      "type": "boolean",
      "description": "Internal note: never shown to the customer"
     },
     "status": {
      "type": "string",
      "enum": [
       "open",
       "pending",
       "resolved",
       "closed"
      ],
      "description": "Status to set with this reply (default: pending)"
     }
    },
    "required": [
     "message"
    ]
   },
   "StaffUpdateTicketDto": {
    "type": "object",
    "properties": {
     "status": {
      "type": "string",
      "enum": [
       "open",
       "pending",
       "resolved",
       "closed"
      ]
     },
     "assigned_to": {
      "type": "string",
      "nullable": true,
      "description": "User id of a channel admin/manager, or null to unassign"
     },
     "priority": {
      "type": "string",
      "enum": [
       "low",
       "normal",
       "high",
       "urgent"
      ]
     }
    }
   },
   "CreateApiKeyDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 100,
      "example": "Warehouse sync"
     },
     "mode": {
      "type": "string",
      "enum": [
       "live",
       "test"
      ],
      "default": "live"
     },
     "project_id": {
      "type": "string",
      "description": "A developer project the key belongs to (third-party and Marketplace apps). Without one, it is the channel's own key (Settings › API)."
     },
     "scopes": {
      "type": "array",
      "enum": [
       "products:read",
       "products:write",
       "orders:read",
       "orders:write",
       "customers:read",
       "crm:read",
       "crm:write",
       "e2ee:gateway",
       "channel:config:read",
       "releases:write",
       "updates:write",
       "profile_data:read",
       "search:read",
       "search:write",
       "search:admin",
       "media:read",
       "media:write",
       "features:read",
       "features:write",
       "jobs:apply"
      ],
      "items": {
       "type": "string",
       "enum": [
        "products:read",
        "products:write",
        "orders:read",
        "orders:write",
        "customers:read",
        "crm:read",
        "crm:write",
        "e2ee:gateway",
        "channel:config:read",
        "releases:write",
        "updates:write",
        "profile_data:read",
        "search:read",
        "search:write",
        "search:admin",
        "media:read",
        "media:write",
        "features:read",
        "features:write",
        "jobs:apply"
       ]
      }
     },
     "app_id": {
      "type": "string",
      "description": "Developer app this key belongs to (/app-builder). Its scopes must be covered by the app's capabilities."
     },
     "ip_allowlist": {
      "example": [
       "203.0.113.0/24",
       "2001:db8::1"
      ],
      "description": "Only these IPs / CIDR blocks may use the key; empty = any",
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "expires_at": {
      "type": "string",
      "example": "2027-01-01T00:00:00Z"
     }
    },
    "required": [
     "name",
     "scopes"
    ]
   },
   "UpdateApiKeyDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 100
     },
     "scopes": {
      "type": "array",
      "enum": [
       "products:read",
       "products:write",
       "orders:read",
       "orders:write",
       "customers:read",
       "crm:read",
       "crm:write",
       "e2ee:gateway",
       "channel:config:read",
       "releases:write",
       "updates:write",
       "profile_data:read",
       "search:read",
       "search:write",
       "search:admin",
       "media:read",
       "media:write",
       "features:read",
       "features:write",
       "jobs:apply"
      ],
      "items": {
       "type": "string",
       "enum": [
        "products:read",
        "products:write",
        "orders:read",
        "orders:write",
        "customers:read",
        "crm:read",
        "crm:write",
        "e2ee:gateway",
        "channel:config:read",
        "releases:write",
        "updates:write",
        "profile_data:read",
        "search:read",
        "search:write",
        "search:admin",
        "media:read",
        "media:write",
        "features:read",
        "features:write",
        "jobs:apply"
       ]
      }
     },
     "ip_allowlist": {
      "description": "[] clears the list",
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "expires_at": {
      "type": "string",
      "nullable": true,
      "description": "null = never expires"
     },
     "app_id": {
      "type": "string",
      "nullable": true,
      "description": "Developer app this key belongs to (/app-builder). Its scopes must be covered by the app's capabilities."
     }
    }
   },
   "RotateApiKeyDto": {
    "type": "object",
    "properties": {
     "grace_seconds": {
      "type": "number",
      "minimum": 0,
      "maximum": 604800,
      "default": 0,
      "description": "Seconds the OLD key keeps working (0 = revoke it immediately)"
     }
    }
   },
   "CreateAppKeyDto": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 100,
      "example": "iOS and Android app"
     },
     "mode": {
      "type": "string",
      "enum": [
       "live",
       "test"
      ],
      "default": "live"
     }
    },
    "required": [
     "name"
    ]
   },
   "CreateWebhookDto": {
    "type": "object",
    "properties": {
     "url": {
      "type": "string",
      "maxLength": 2048,
      "example": "https://example.com/hooks/kodkila"
     },
     "description": {
      "type": "string",
      "minLength": 0,
      "maxLength": 255
     },
     "events": {
      "type": "array",
      "enum": [
       "order.created",
       "order.status_changed",
       "order.paid",
       "payment.succeeded",
       "payment.failed",
       "payment.refunded",
       "payment.disputed",
       "product.created",
       "product.updated",
       "product.deleted",
       "cms.surface.published",
       "cms.surface.unpublished",
       "media.asset.ready",
       "media.asset.failed",
       "media.track.ready",
       "webhook.ping",
       "*"
      ],
      "example": [
       "order.created"
      ],
      "items": {
       "type": "string",
       "enum": [
        "order.created",
        "order.status_changed",
        "order.paid",
        "payment.succeeded",
        "payment.failed",
        "payment.refunded",
        "payment.disputed",
        "product.created",
        "product.updated",
        "product.deleted",
        "cms.surface.published",
        "cms.surface.unpublished",
        "media.asset.ready",
        "media.asset.failed",
        "media.track.ready",
        "webhook.ping",
        "*"
       ]
      }
     }
    },
    "required": [
     "url",
     "events"
    ]
   },
   "UpdateWebhookDto": {
    "type": "object",
    "properties": {
     "url": {
      "type": "string",
      "maxLength": 2048
     },
     "description": {
      "type": "string",
      "minLength": 0,
      "maxLength": 255
     },
     "events": {
      "type": "array",
      "enum": [
       "order.created",
       "order.status_changed",
       "order.paid",
       "payment.succeeded",
       "payment.failed",
       "payment.refunded",
       "payment.disputed",
       "product.created",
       "product.updated",
       "product.deleted",
       "cms.surface.published",
       "cms.surface.unpublished",
       "media.asset.ready",
       "media.asset.failed",
       "media.track.ready",
       "webhook.ping",
       "*"
      ],
      "items": {
       "type": "string",
       "enum": [
        "order.created",
        "order.status_changed",
        "order.paid",
        "payment.succeeded",
        "payment.failed",
        "payment.refunded",
        "payment.disputed",
        "product.created",
        "product.updated",
        "product.deleted",
        "cms.surface.published",
        "cms.surface.unpublished",
        "media.asset.ready",
        "media.asset.failed",
        "media.track.ready",
        "webhook.ping",
        "*"
       ]
      }
     },
     "status": {
      "type": "string",
      "enum": [
       "enabled",
       "disabled"
      ],
      "description": "Re-enabling resets the consecutive-failure counter"
     }
    }
   },
   "RotateWebhookSecretDto": {
    "type": "object",
    "properties": {
     "grace_seconds": {
      "type": "number",
      "minimum": 0,
      "maximum": 604800,
      "default": 0,
      "description": "Seconds deliveries are ALSO signed with the old secret"
     }
    }
   },
   "ModerationReasonDto": {
    "type": "object",
    "properties": {
     "reason": {
      "type": "string",
      "maxLength": 500,
      "description": "Why; kept in the business audit log"
     }
    }
   },
   "ResolveReportDto": {
    "type": "object",
    "properties": {
     "outcome": {
      "type": "string",
      "enum": [
       "resolved",
       "dismissed"
      ],
      "default": "resolved"
     },
     "note": {
      "type": "string",
      "maxLength": 500
     }
    }
   },
   "ReportDto": {
    "type": "object",
    "properties": {
     "target_type": {
      "type": "string",
      "enum": [
       "account",
       "profile",
       "business",
       "channel"
      ]
     },
     "target_id": {
      "type": "string"
     },
     "category": {
      "type": "string",
      "enum": [
       "spam",
       "fraud",
       "abuse",
       "illegal",
       "impersonation",
       "copyright",
       "privacy",
       "other"
      ]
     },
     "details": {
      "type": "string",
      "minLength": 0,
      "maxLength": 2000
     }
    },
    "required": [
     "target_type",
     "target_id",
     "category"
    ]
   },
   "AppealDto": {
    "type": "object",
    "properties": {
     "text": {
      "type": "string",
      "minLength": 10,
      "maxLength": 2000
     }
    },
    "required": [
     "text"
    ]
   },
   "LegalRequestDto": {
    "type": "object",
    "properties": {
     "kind": {
      "type": "string",
      "enum": [
       "data_access",
       "data_erasure",
       "data_correction",
       "law_enforcement",
       "court_order",
       "copyright",
       "other"
      ]
     },
     "requester_name": {
      "type": "string",
      "minLength": 2,
      "maxLength": 200
     },
     "requester_email": {
      "type": "string"
     },
     "organisation": {
      "type": "string",
      "minLength": 0,
      "maxLength": 200
     },
     "subject": {
      "type": "string",
      "minLength": 0,
      "maxLength": 300,
      "description": "Who or what it is about"
     },
     "details": {
      "type": "string",
      "minLength": 20,
      "maxLength": 5000
     },
     "due_at": {
      "type": "string",
      "description": "Managers only: a deadline the order sets"
     }
    },
    "required": [
     "kind",
     "requester_name",
     "details"
    ]
   },
   "DirectActionDto": {
    "type": "object",
    "properties": {
     "target_type": {
      "type": "string",
      "enum": [
       "account",
       "profile",
       "business",
       "channel"
      ]
     },
     "target_id": {
      "type": "string"
     },
     "category": {
      "type": "string",
      "enum": [
       "spam",
       "fraud",
       "abuse",
       "illegal",
       "impersonation",
       "copyright",
       "privacy",
       "other"
      ]
     },
     "details": {
      "type": "string",
      "minLength": 0,
      "maxLength": 2000
     },
     "action": {
      "type": "string",
      "enum": [
       "warning",
       "suspended"
      ]
     },
     "reason": {
      "type": "string",
      "minLength": 3,
      "maxLength": 1000,
      "description": "Shown to the owner"
     },
     "internal_note": {
      "type": "string",
      "minLength": 0,
      "maxLength": 2000,
      "description": "Only the channel's managers see it"
     }
    },
    "required": [
     "target_type",
     "target_id",
     "category",
     "action",
     "reason"
    ]
   },
   "DecisionDto": {
    "type": "object",
    "properties": {
     "decision": {
      "type": "string",
      "enum": [
       "warning",
       "suspended",
       "dismissed"
      ]
     },
     "reason": {
      "type": "string",
      "minLength": 0,
      "maxLength": 1000,
      "description": "Shown to the owner (required unless dismissed)"
     },
     "internal_note": {
      "type": "string",
      "minLength": 0,
      "maxLength": 2000
     }
    },
    "required": [
     "decision"
    ]
   },
   "ReasonDto": {
    "type": "object",
    "properties": {
     "reason": {
      "type": "string",
      "minLength": 0,
      "maxLength": 1000
     }
    }
   },
   "AppealDecisionDto": {
    "type": "object",
    "properties": {
     "outcome": {
      "type": "string",
      "enum": [
       "upheld",
       "reversed"
      ]
     },
     "reason": {
      "type": "string",
      "minLength": 3,
      "maxLength": 1000
     }
    },
    "required": [
     "outcome",
     "reason"
    ]
   },
   "LegalUpdateDto": {
    "type": "object",
    "properties": {
     "status": {
      "type": "string",
      "enum": [
       "open",
       "in_progress",
       "completed",
       "refused"
      ]
     },
     "response": {
      "type": "string",
      "minLength": 0,
      "maxLength": 5000
     }
    },
    "required": [
     "status"
    ]
   },
   "KeysPauseDto": {
    "type": "object",
    "properties": {
     "target_channel_id": {
      "type": "string",
      "description": "This channel or one below it"
     },
     "pause": {
      "type": "boolean"
     },
     "reason": {
      "type": "string",
      "minLength": 0,
      "maxLength": 400
     }
    },
    "required": [
     "target_channel_id",
     "pause"
    ]
   },
   "SuffixMigrationRunDto": {
    "type": "object",
    "properties": {
     "dry_run": {
      "type": "boolean",
      "description": "true (default): only count and sample; false: rename and notify"
     },
     "channel_id": {
      "type": "string",
      "description": "Only this channel (default: every channel)"
     },
     "sample_size": {
      "type": "number",
      "minimum": 0,
      "maximum": 50,
      "description": "How many masked decisions to return (0 to 50, default 10)"
     }
    }
   },
   "DropSuffixDto": {
    "type": "object",
    "properties": {
     "current_username": {
      "type": "string",
      "maxLength": 64,
      "description": "My current username, as I sign in with it (asha.07)"
     },
     "profile_id": {
      "type": "string",
      "description": "Which of my profiles (default: my profile in this channel)"
     }
    },
    "required": [
     "current_username"
    ]
   },
   "RenameUsernameDto": {
    "type": "object",
    "properties": {
     "username": {
      "type": "string",
      "maxLength": 64,
      "description": "The new username"
     },
     "profile_id": {
      "type": "string",
      "description": "Which of my profiles (default: my profile in this channel)"
     }
    },
    "required": [
     "username"
    ]
   },
   "AbuseTargetDto": {
    "type": "object",
    "properties": {
     "type": {
      "type": "string",
      "enum": [
       "account",
       "profile",
       "business",
       "channel",
       "message",
       "media",
       "group"
      ]
     },
     "id": {
      "type": "string",
      "pattern": "^[^\\u0000-\\u001f\\u007f]{1,256}$",
      "description": "account/profile/business/channel: its id (uuid). message: your app's message id. media: the file, media file, media asset or e2ee blob id. group: your app's group id (1 to 128 characters, no spaces; never looked up)"
     },
     "sender_account_id": {
      "type": "string",
      "description": "message only (required): the account that sent it Checked by the server against /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i."
     },
     "conversation_id": {
      "type": "string",
      "pattern": "^[^\\u0000-\\u001f\\u007f]{1,256}$",
      "description": "message only: your app's conversation id"
     },
     "kind": {
      "type": "string",
      "enum": [
       "file",
       "media_file",
       "media_asset",
       "e2ee_blob"
      ],
      "description": "media only: which store the id is from; guessed when left out (number: file, uuid: media file then media asset, else e2ee blob)"
     },
     "member_account_ids": {
      "maxItems": 10,
      "description": "group only: the members you are reporting (account ids of your channel, never your own). Each one is filed as its own report. Left out: the report is about the group as a whole and goes to the channel's case",
      "type": "array",
      "items": {
       "type": "string",
       "description": "Checked by the server against /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i."
      }
     }
    },
    "required": [
     "type",
     "id"
    ]
   },
   "AbuseEvidenceDto": {
    "type": "object",
    "properties": {
     "type": {
      "type": "string",
      "enum": [
       "message",
       "media",
       "post",
       "comment",
       "url",
       "text",
       "other"
      ]
     },
     "ref": {
      "type": "string",
      "pattern": "^[^\\u0000-\\u001f\\u007f]{1,256}$",
      "description": "An id or an https URL (never fetched). Anything that reads as a link must be https (400 BAD_EVIDENCE_REF); for type url it is required to be one"
     },
     "sha256": {
      "type": "string",
      "description": "SHA-256 of the item, hex Checked by the server against /^[0-9a-f]{64}$/i."
     },
     "excerpt": {
      "type": "string",
      "maxLength": 1000,
      "description": "Text you choose to share with the moderators (for an end-to-end encrypted message, the part you saw)"
     },
     "at": {
      "type": "string",
      "description": "When it was sent or seen (ISO 8601)"
     }
    },
    "required": [
     "type"
    ]
   },
   "AbuseReportDto": {
    "type": "object",
    "properties": {
     "target": {
      "$ref": "#/components/schemas/AbuseTargetDto"
     },
     "reason": {
      "type": "string",
      "enum": [
       "spam",
       "scam",
       "fraud",
       "harassment",
       "bullying",
       "hate",
       "threat",
       "violence",
       "sexual",
       "nudity",
       "self_harm",
       "misinformation",
       "child_safety",
       "terrorism",
       "illegal",
       "impersonation",
       "copyright",
       "privacy",
       "other"
      ]
     },
     "details": {
      "type": "string",
      "minLength": 0,
      "maxLength": 2000,
      "description": "What happened, in your words"
     },
     "evidence": {
      "maxItems": 10,
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/AbuseEvidenceDto"
      }
     }
    },
    "required": [
     "target",
     "reason"
    ]
   },
   "EnrollPartnerDto": {
    "type": "object",
    "properties": {
     "platform_name": {
      "type": "string",
      "minLength": 2,
      "maxLength": 80,
      "example": "viremail"
     },
     "description": {
      "type": "string",
      "minLength": 0,
      "maxLength": 500
     },
     "site_url": {
      "type": "string",
      "minLength": 0,
      "maxLength": 300,
      "example": "https://viremail.com"
     },
     "category": {
      "type": "string",
      "enum": [
       "email",
       "social",
       "browser",
       "news",
       "shopping",
       "video",
       "tools",
       "community",
       "other"
      ]
     },
     "monthly_visitors": {
      "type": "number",
      "minimum": 0,
      "description": "About how many people visit a month"
     },
     "accept_terms": {
      "type": "boolean",
      "description": "Accepts the Ad Partner Terms"
     }
    },
    "required": [
     "accept_terms"
    ]
   },
   "PartnerDto": {
    "type": "object",
    "properties": {
     "platform_name": {
      "type": "string",
      "minLength": 2,
      "maxLength": 80,
      "example": "viremail"
     },
     "description": {
      "type": "string",
      "minLength": 0,
      "maxLength": 500
     },
     "site_url": {
      "type": "string",
      "minLength": 0,
      "maxLength": 300,
      "example": "https://viremail.com"
     },
     "category": {
      "type": "string",
      "enum": [
       "email",
       "social",
       "browser",
       "news",
       "shopping",
       "video",
       "tools",
       "community",
       "other"
      ]
     },
     "monthly_visitors": {
      "type": "number",
      "minimum": 0,
      "description": "About how many people visit a month"
     }
    }
   },
   "PartnerDecisionDto": {
    "type": "object",
    "properties": {
     "decision": {
      "type": "string",
      "enum": [
       "approved",
       "rejected",
       "suspended",
       "reinstated"
      ]
     },
     "reason": {
      "type": "string",
      "minLength": 0,
      "maxLength": 1000
     },
     "share_percent": {
      "type": "number",
      "minimum": 0,
      "maximum": 100,
      "description": "The partner's share in percent (default 68)"
     }
    },
    "required": [
     "decision"
    ]
   },
   "CampaignNotesDto": {
    "type": "object",
    "properties": {
     "notes": {
      "type": "string",
      "minLength": 0,
      "maxLength": 10000
     }
    },
    "required": [
     "notes"
    ]
   },
   "CampaignDto": {
    "type": "object",
    "properties": {
     "channel_id": {
      "type": "string",
      "description": "The business's own channel to promote"
     },
     "name": {
      "type": "string",
      "minLength": 2,
      "maxLength": 120
     },
     "objective": {
      "type": "string",
      "enum": [
       "traffic",
       "sales",
       "leads",
       "awareness"
      ]
     },
     "daily_budget_minor": {
      "type": "number",
      "minimum": 1,
      "maximum": 10000000,
      "description": "Daily budget in minor units (pence/cents)"
     },
     "max_cpc_minor": {
      "type": "number",
      "minimum": 1,
      "maximum": 10000,
      "description": "Highest cost per click in minor units"
     },
     "start_at": {
      "type": "string",
      "nullable": true
     },
     "end_at": {
      "type": "string",
      "nullable": true
     },
     "countries": {
      "example": [
       "GB",
       "US"
      ],
      "description": "Empty: everywhere",
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "partner_ids": {
      "description": "Partner platforms (channel ids) to run on; empty: every partner platform",
      "type": "array",
      "items": {
       "type": "string"
      }
     }
    }
   },
   "AdDto": {
    "type": "object",
    "properties": {
     "headline": {
      "type": "string",
      "minLength": 2,
      "maxLength": 60
     },
     "body": {
      "type": "string",
      "minLength": 0,
      "maxLength": 140
     },
     "image_url": {
      "type": "string",
      "minLength": 0,
      "maxLength": 500,
      "description": "https image address"
     },
     "destination_url": {
      "type": "string",
      "minLength": 8,
      "maxLength": 500,
      "description": "A page on the promoted channel (https)"
     },
     "cta": {
      "type": "string",
      "enum": [
       "learn_more",
       "shop_now",
       "book_now",
       "sign_up",
       "contact_us",
       "get_offer"
      ]
     },
     "status": {
      "type": "string",
      "enum": [
       "active",
       "paused"
      ]
     }
    }
   },
   "SubmitCampaignDto": {
    "type": "object",
    "properties": {
     "accept_policy": {
      "type": "boolean",
      "description": "Accepts the advertising policy"
     }
    },
    "required": [
     "accept_policy"
    ]
   },
   "CampaignDecisionDto": {
    "type": "object",
    "properties": {
     "decision": {
      "type": "string",
      "enum": [
       "approved",
       "changes_requested",
       "rejected",
       "suspended",
       "reinstated"
      ]
     },
     "reason": {
      "type": "string",
      "minLength": 0,
      "maxLength": 1000,
      "description": "Shown to the advertiser (required unless approving or reinstating)"
     }
    },
    "required": [
     "decision"
    ]
   },
   "DeviceKeyDto": {
    "type": "object",
    "properties": {
     "alg": {
      "type": "string",
      "enum": [
       "ed25519",
       "p256"
      ]
     },
     "public_key": {
      "type": "string",
      "maxLength": 96,
      "pattern": "^[A-Za-z0-9+/_-]+={0,2}$",
      "description": "base64url public key: Ed25519 32 bytes; P-256 65 bytes uncompressed (or 33 compressed)"
     },
     "signature": {
      "type": "string",
      "maxLength": 128,
      "pattern": "^[A-Za-z0-9+/_-]+={0,2}$",
      "description": "base64url signature by this key over \"kodkila-e2ee-device-key-v1\\n<channel_id>\\n<account_id>\\n<registration_id>\\n<alg>\\n<public_key>\" (P-256: raw r||s or DER)"
     }
    },
    "required": [
     "alg",
     "public_key",
     "signature"
    ]
   },
   "SignedPreKeyDto": {
    "type": "object",
    "properties": {
     "signature": {
      "type": "string",
      "maxLength": 100,
      "pattern": "^[A-Za-z0-9+/_-]+={0,2}$"
     },
     "id": {
      "type": "number",
      "minimum": 0,
      "maximum": 16777215
     },
     "public_key": {
      "type": "string",
      "maxLength": 64,
      "pattern": "^[A-Za-z0-9+/_-]+={0,2}$"
     }
    },
    "required": [
     "signature",
     "id",
     "public_key"
    ]
   },
   "KyberPreKeyDto": {
    "type": "object",
    "properties": {
     "id": {
      "type": "number",
      "minimum": 0,
      "maximum": 16777215
     },
     "public_key": {
      "type": "string",
      "maxLength": 2200,
      "pattern": "^[A-Za-z0-9+/_-]+={0,2}$"
     },
     "signature": {
      "type": "string",
      "maxLength": 100,
      "pattern": "^[A-Za-z0-9+/_-]+={0,2}$"
     }
    },
    "required": [
     "id",
     "public_key",
     "signature"
    ]
   },
   "EcPreKeyDto": {
    "type": "object",
    "properties": {
     "id": {
      "type": "number",
      "minimum": 0,
      "maximum": 16777215
     },
     "public_key": {
      "type": "string",
      "maxLength": 64,
      "pattern": "^[A-Za-z0-9+/_-]+={0,2}$"
     }
    },
    "required": [
     "id",
     "public_key"
    ]
   },
   "RegisterDeviceDto": {
    "type": "object",
    "properties": {
     "registration_id": {
      "type": "number",
      "minimum": 1,
      "maximum": 16380
     },
     "identity_key": {
      "type": "string",
      "maxLength": 64,
      "pattern": "^[A-Za-z0-9+/_-]+={0,2}$",
      "description": "base64url, 33 bytes"
     },
     "name_ct": {
      "type": "string",
      "maxLength": 1024,
      "description": "encrypted device name (opaque)"
     },
     "provisioning_address": {
      "type": "string",
      "pattern": "^[A-Za-z0-9_-]{43}$",
      "description": "The provisioning address this device showed as a QR. Required with a link_token bound to it, and to register without signing in (the response then also carries tokens)."
     },
     "reregister": {
      "type": "boolean",
      "description": "Replace every device and the identity key (lost primary). Needs a session signed in within the last 10 minutes."
     },
     "device_key": {
      "description": "This device's own signing key. Optional until the device-key grace ends, required afterwards. A keyed device is acted for only with a device token.",
      "allOf": [
       {
        "$ref": "#/components/schemas/DeviceKeyDto"
       }
      ]
     },
     "signed_pre_key": {
      "$ref": "#/components/schemas/SignedPreKeyDto"
     },
     "kyber_pre_key": {
      "$ref": "#/components/schemas/KyberPreKeyDto"
     },
     "pre_keys": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/EcPreKeyDto"
      }
     },
     "kyber_pre_keys": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/KyberPreKeyDto"
      }
     },
     "capabilities": {
      "type": "object"
     },
     "link_token": {
      "type": "string",
      "maxLength": 64,
      "pattern": "^[A-Za-z0-9+/_-]+={0,2}$"
     }
    },
    "required": [
     "registration_id",
     "identity_key",
     "signed_pre_key",
     "kyber_pre_key",
     "pre_keys",
     "kyber_pre_keys"
    ]
   },
   "LinkTokenDto": {
    "type": "object",
    "properties": {
     "provisioning_address": {
      "type": "string",
      "pattern": "^[A-Za-z0-9_-]{43}$",
      "description": "Bind the token to this provisioning address (the new device's QR): it then works only with that address, after the new device received the message, and lets the new device sign in without a password."
     }
    }
   },
   "DeviceProofDto": {
    "type": "object",
    "properties": {
     "ts": {
      "type": "number",
      "description": "the device's clock, epoch ms (within 5 minutes of the server)"
     },
     "nonce": {
      "type": "string",
      "pattern": "^[A-Za-z0-9_-]{16,64}$",
      "description": "16 to 64 random base64url characters, never reused"
     },
     "signature": {
      "type": "string",
      "maxLength": 128,
      "pattern": "^[A-Za-z0-9+/_-]+={0,2}$",
      "description": "base64url signature by the device key over \"kodkila-e2ee-device-proof-v1\\n<channel_id>\\n<account_id>\\n<device_id>\\n<ts>\\n<nonce>\""
     }
    },
    "required": [
     "ts",
     "nonce",
     "signature"
    ]
   },
   "SetDeviceKeyDto": {
    "type": "object",
    "properties": {
     "device_key": {
      "$ref": "#/components/schemas/DeviceKeyDto"
     }
    },
    "required": [
     "device_key"
    ]
   },
   "PutPushDto": {
    "type": "object",
    "properties": {
     "route_tag": {
      "type": "string",
      "description": "Route tag for this account on this device: 16 to 32 random base64url characters made by the client. Every push to the device carries it as `rt`. Left out: the stored tag stays.",
      "pattern": "^[A-Za-z0-9_-]{16,32}$",
      "example": "q3Vx9JkLm2Tz0pRw8Ya4bC"
     },
     "platform": {
      "type": "string",
      "enum": [
       "apns",
       "apns_voip",
       "fcm"
      ]
     },
     "token": {
      "type": "string",
      "minLength": 8,
      "maxLength": 4096
     },
     "environment": {
      "type": "string",
      "enum": [
       "production",
       "sandbox"
      ]
     },
     "topic": {
      "type": "string",
      "pattern": "^[A-Za-z0-9.-]{1,200}$"
     }
    },
    "required": [
     "platform",
     "token"
    ]
   },
   "RingCallDto": {
    "type": "object",
    "properties": {
     "to": {
      "type": "string",
      "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
      "description": "The callee's account id on this channel"
     },
     "access_key": {
      "type": "string",
      "maxLength": 32,
      "description": "The callee's unidentified-access key (16 bytes, base64), the one a contact holds from the callee's profile key and uses for sealed-sender sends. Only a holder can ring the callee; with a wrong key the answer is the same and nothing rings"
     },
     "ttl_seconds": {
      "type": "number",
      "minimum": 10,
      "maximum": 60,
      "description": "How long it rings, 10 to 60 seconds (default 45)"
     },
     "caller_blob": {
      "type": "string",
      "maxLength": 1024,
      "description": "Opaque caller details sealed by the app (base64url, at most 1024 characters), for the callee's ringing screen. Passed through untouched as `cb` in the VoIP and FCM ring push of every callee device; never logged, never stored, not sent with cancels. 400 CALLER_BLOB_INVALID when it is not base64url or too long"
     }
    },
    "required": [
     "to",
     "access_key"
    ]
   },
   "CancelCallDto": {
    "type": "object",
    "properties": {
     "reason": {
      "type": "string",
      "enum": [
       "hangup",
       "timeout",
       "answered",
       "declined",
       "busy"
      ],
      "description": "Why the ring ends (default hangup)"
     }
    }
   },
   "PutKeysDto": {
    "type": "object",
    "properties": {
     "signed_pre_key": {
      "$ref": "#/components/schemas/SignedPreKeyDto"
     },
     "kyber_last_resort": {
      "$ref": "#/components/schemas/KyberPreKeyDto"
     },
     "pre_keys": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/EcPreKeyDto"
      }
     },
     "kyber_pre_keys": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/KyberPreKeyDto"
      }
     }
    }
   },
   "OutgoingMessageDto": {
    "type": "object",
    "properties": {
     "device_id": {
      "type": "number",
      "minimum": 1,
      "maximum": 2147483647
     },
     "registration_id": {
      "type": "number",
      "minimum": 1,
      "maximum": 16380
     },
     "type": {
      "type": "number",
      "enum": [
       1,
       3,
       6,
       8
      ]
     },
     "content": {
      "type": "string",
      "minLength": 1,
      "maxLength": 350000,
      "pattern": "^[A-Za-z0-9+/_-]+={0,2}$"
     }
    },
    "required": [
     "device_id",
     "registration_id",
     "type",
     "content"
    ]
   },
   "SendMessagesDto": {
    "type": "object",
    "properties": {
     "call": {
      "type": "boolean",
      "description": "Wake with the call push (apns_voip / FCM {c:1}) instead of the message push"
     },
     "timestamp": {
      "type": "number",
      "minimum": 0
     },
     "online": {
      "type": "boolean"
     },
     "urgent": {
      "type": "boolean"
     },
     "messages": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/OutgoingMessageDto"
      }
     }
    },
    "required": [
     "timestamp",
     "messages"
    ]
   },
   "DiscoverableDto": {
    "type": "object",
    "properties": {
     "discoverable": {
      "type": "boolean"
     }
    },
    "required": [
     "discoverable"
    ]
   },
   "DirectoryLookupDto": {
    "type": "object",
    "properties": {
     "username": {
      "type": "string",
      "minLength": 3,
      "maxLength": 64
     }
    },
    "required": [
     "username"
    ]
   },
   "PutProfileDto": {
    "type": "object",
    "properties": {
     "uak": {
      "type": "string",
      "maxLength": 32,
      "pattern": "^[A-Za-z0-9+/_-]+={0,2}$",
      "description": "base64, 16 bytes"
     },
     "version": {
      "type": "string",
      "pattern": "^[A-Za-z0-9_-]{1,128}$"
     },
     "commitment": {
      "type": "string",
      "maxLength": 512,
      "pattern": "^[A-Za-z0-9+/_-]+={0,2}$"
     },
     "name_ct": {
      "type": "string",
      "maxLength": 2048,
      "pattern": "^[A-Za-z0-9+/_-]+={0,2}$"
     },
     "about_ct": {
      "type": "string",
      "maxLength": 4096,
      "pattern": "^[A-Za-z0-9+/_-]+={0,2}$"
     },
     "avatar_blob": {
      "type": "string",
      "maxLength": 64,
      "pattern": "^[A-Za-z0-9+/_-]+={0,2}$"
     },
     "unrestricted_unidentified_access": {
      "type": "boolean"
     }
    },
    "required": [
     "uak",
     "version",
     "commitment",
     "unrestricted_unidentified_access"
    ]
   },
   "CreateBlobDto": {
    "type": "object",
    "properties": {
     "size": {
      "type": "number",
      "description": "Exact ciphertext size in bytes (a whole number, at least 1)"
     },
     "purpose": {
      "type": "string",
      "enum": [
       "attachment",
       "avatar",
       "backup"
      ]
     },
     "resumable": {
      "type": "boolean",
      "description": "true: a resumable upload in parts (POST /e2ee/blobs/:id/parts, /complete) instead of one presigned PUT"
     }
    },
    "required": [
     "size",
     "purpose"
    ]
   },
   "BlobCreatedDto": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string"
     },
     "status": {
      "type": "string",
      "enum": [
       "pending"
      ]
     },
     "upload_url": {
      "type": "string",
      "description": "Single PUT: the presigned URL (PUT exactly `size` bytes, application/octet-stream)"
     },
     "upload_token": {
      "type": "string",
      "description": "Resumable: the write capability for parts, complete and abort"
     },
     "delete_token": {
      "type": "string",
      "nullable": true,
      "description": "The sender's delete capability (DELETE with X-Delete-Token)"
     },
     "size": {
      "type": "number"
     },
     "part_size": {
      "type": "number",
      "description": "Bytes per part (every part but the last)"
     },
     "parts": {
      "type": "number",
      "description": "Number of parts"
     },
     "expires": {
      "type": "number",
      "description": "Epoch ms: single PUT URL expiry, or the resumable upload's deadline"
     },
     "max_parallel": {
      "type": "number",
      "description": "Parts to send at once (advice)"
     }
    },
    "required": [
     "id",
     "status",
     "expires"
    ]
   },
   "BlobPartsDto": {
    "type": "object",
    "properties": {
     "upload_token": {
      "type": "string",
      "maxLength": 200,
      "description": "upload_token from POST /e2ee/blobs with resumable: true"
     },
     "parts": {
      "description": "Part numbers (1-based) to get upload URLs for, at most 100; empty: status only",
      "type": "array",
      "items": {
       "type": "number"
      }
     },
     "ttl_s": {
      "type": "number",
      "description": "Seconds the part URLs live, 300..86400 (default 3600), clipped to the upload deadline"
     },
     "md5": {
      "type": "object",
      "description": "Part number → base64 MD5 of that part; signed into its URL so storage refuses a corrupted body",
      "additionalProperties": {
       "type": "string"
      }
     }
    },
    "required": [
     "upload_token"
    ]
   },
   "BlobPartRefDto": {
    "type": "object",
    "properties": {
     "part": {
      "type": "number"
     },
     "size": {
      "type": "number"
     }
    },
    "required": [
     "part",
     "size"
    ]
   },
   "BlobPartUrlDto": {
    "type": "object",
    "properties": {
     "part": {
      "type": "number"
     },
     "size": {
      "type": "number"
     },
     "url": {
      "type": "string"
     },
     "method": {
      "type": "string",
      "enum": [
       "PUT"
      ]
     },
     "headers": {
      "type": "object",
      "additionalProperties": {
       "type": "string"
      }
     },
     "expires": {
      "type": "number",
      "description": "Epoch ms"
     }
    },
    "required": [
     "part",
     "size",
     "url",
     "method",
     "headers",
     "expires"
    ]
   },
   "BlobPartsResultDto": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string"
     },
     "status": {
      "type": "string",
      "enum": [
       "pending",
       "ready"
      ]
     },
     "size": {
      "type": "number"
     },
     "part_size": {
      "type": "number"
     },
     "parts": {
      "type": "number"
     },
     "uploaded": {
      "description": "Parts storage holds at their exact size",
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/BlobPartRefDto"
      }
     },
     "urls": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/BlobPartUrlDto"
      }
     },
     "expires": {
      "type": "number",
      "description": "Epoch ms: the upload's deadline"
     }
    },
    "required": [
     "id",
     "status",
     "size",
     "part_size",
     "parts",
     "uploaded",
     "urls",
     "expires"
    ]
   },
   "BlobCompleteDto": {
    "type": "object",
    "properties": {
     "upload_token": {
      "type": "string",
      "maxLength": 200,
      "description": "upload_token from POST /e2ee/blobs (required for a resumable upload; a single PUT needs none)"
     }
    }
   },
   "BlobReadyDto": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string"
     },
     "status": {
      "type": "string",
      "enum": [
       "ready"
      ]
     },
     "size": {
      "type": "number"
     },
     "expires": {
      "type": "number",
      "nullable": true,
      "description": "Epoch ms when the blob expires; null for a current backup or a referenced avatar"
     }
    },
    "required": [
     "id",
     "status",
     "size",
     "expires"
    ]
   },
   "BlobUploadDto": {
    "type": "object",
    "properties": {
     "upload_token": {
      "type": "string",
      "maxLength": 200,
      "description": "upload_token from POST /e2ee/blobs with resumable: true"
     }
    },
    "required": [
     "upload_token"
    ]
   },
   "BlobOkDto": {
    "type": "object",
    "properties": {
     "ok": {
      "type": "boolean"
     }
    },
    "required": [
     "ok"
    ]
   },
   "BackupDto": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string"
     },
     "status": {
      "type": "string",
      "enum": [
       "pending",
       "ready"
      ]
     },
     "size": {
      "type": "number"
     },
     "current": {
      "type": "boolean",
      "description": "The backup a new phone restores"
     },
     "created": {
      "type": "number",
      "nullable": true
     },
     "completed": {
      "type": "number",
      "nullable": true
     },
     "expires": {
      "type": "number",
      "nullable": true
     },
     "delete_token": {
      "type": "string",
      "nullable": true
     }
    },
    "required": [
     "id",
     "status",
     "size",
     "current",
     "created",
     "completed",
     "expires",
     "delete_token"
    ]
   },
   "BlobLinkDto": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string"
     },
     "url": {
      "type": "string",
      "description": "Download URL; takes Range (206/416), expires with 403"
     },
     "expires": {
      "type": "number",
      "description": "Epoch ms"
     },
     "size": {
      "type": "number"
     },
     "accept_ranges": {
      "type": "boolean"
     }
    },
    "required": [
     "id",
     "url",
     "expires",
     "size",
     "accept_ranges"
    ]
   },
   "PushCredentialsDto": {
    "type": "object",
    "properties": {
     "apns_key": {
      "type": "string",
      "maxLength": 4096,
      "description": "APNs .p8 key (PEM)"
     },
     "fcm_service_account": {
      "type": "string",
      "maxLength": 8192,
      "description": "FCM service-account JSON"
     },
     "alert_title": {
      "type": "string",
      "maxLength": 60,
      "description": "Wake alert title (default: channel title)"
     },
     "alert_body": {
      "type": "string",
      "maxLength": 120,
      "description": "Wake alert body (default: New message)"
     },
     "apns_key_id": {
      "type": "string",
      "pattern": "^[A-Z0-9]{10}$"
     },
     "apns_team_id": {
      "type": "string",
      "pattern": "^[A-Z0-9]{10}$"
     }
    }
   },
   "LiveDeviceDto": {
    "type": "object",
    "properties": {
     "account_id": {
      "type": "string",
      "pattern": "^[0-9a-fA-F-]{36}$"
     },
     "device_id": {
      "type": "number",
      "minimum": 1,
      "maximum": 2147483647
     }
    },
    "required": [
     "account_id",
     "device_id"
    ]
   },
   "GatewayLiveDto": {
    "type": "object",
    "properties": {
     "devices": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/LiveDeviceDto"
      }
     },
     "gone": {
      "description": "Devices that just disconnected (no longer live, wake pushes resume at once).",
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/LiveDeviceDto"
      }
     }
    },
    "required": [
     "devices"
    ]
   },
   "ProvisioningPutDto": {
    "type": "object",
    "properties": {
     "body": {
      "type": "string",
      "description": "The sealed provisioning message, base64url (at most 16384 bytes decoded)"
     }
    },
    "required": [
     "body"
    ]
   },
   "CandidateCountsDto": {
    "type": "object",
    "properties": {
     "host": {
      "type": "number",
      "minimum": 0,
      "maximum": 200
     },
     "srflx": {
      "type": "number",
      "minimum": 0,
      "maximum": 200
     },
     "prflx": {
      "type": "number",
      "minimum": 0,
      "maximum": 200
     },
     "relay": {
      "type": "number",
      "minimum": 0,
      "maximum": 200
     }
    }
   },
   "CallQualityDto": {
    "type": "object",
    "properties": {
     "call_id": {
      "type": "string",
      "description": "The call's id (the one the call was rung with)"
     },
     "platform": {
      "type": "string",
      "enum": [
       "ios",
       "android",
       "web",
       "desktop"
      ]
     },
     "direction": {
      "type": "string",
      "enum": [
       "outgoing",
       "incoming"
      ]
     },
     "local_candidates": {
      "description": "Local ICE candidates gathered, per type",
      "allOf": [
       {
        "$ref": "#/components/schemas/CandidateCountsDto"
       }
      ]
     },
     "remote_candidates": {
      "description": "Remote ICE candidates received, per type",
      "allOf": [
       {
        "$ref": "#/components/schemas/CandidateCountsDto"
       }
      ]
     },
     "selected_local": {
      "type": "string",
      "enum": [
       "host",
       "srflx",
       "prflx",
       "relay"
      ],
      "description": "Type of the local candidate of the selected pair"
     },
     "selected_remote": {
      "type": "string",
      "enum": [
       "host",
       "srflx",
       "prflx",
       "relay"
      ],
      "description": "Type of the remote candidate of the selected pair"
     },
     "selected_protocol": {
      "type": "string",
      "enum": [
       "udp",
       "tcp",
       "tls"
      ],
      "description": "Transport of the selected pair (tls: TURN over TLS)"
     },
     "rtt_ms": {
      "type": "number",
      "minimum": 0,
      "maximum": 60000,
      "description": "Round-trip time, milliseconds (median over the call)"
     },
     "jitter_ms": {
      "type": "number",
      "minimum": 0,
      "maximum": 10000,
      "description": "Jitter, milliseconds (median over the call)"
     },
     "packet_loss_pct": {
      "type": "number",
      "minimum": 0,
      "maximum": 100,
      "description": "Packets lost, percent of those expected (0 to 100)"
     },
     "codec": {
      "type": "string",
      "enum": [
       "opus",
       "pcmu",
       "pcma",
       "g722",
       "isac",
       "vp8",
       "vp9",
       "h264",
       "av1",
       "other"
      ]
     },
     "duration_s": {
      "type": "number",
      "minimum": 0,
      "maximum": 86400,
      "description": "Seconds the call was connected"
     },
     "setup_ms": {
      "type": "number",
      "minimum": 0,
      "maximum": 600000,
      "description": "Milliseconds from start to connected"
     },
     "audio_route": {
      "type": "string",
      "enum": [
       "receiver",
       "speaker",
       "wired",
       "bluetooth",
       "car",
       "airplay",
       "usb",
       "other"
      ],
      "description": "Where the audio played for most of the call"
     },
     "end_reason": {
      "type": "string",
      "enum": [
       "hangup",
       "remote_hangup",
       "failed",
       "dropped",
       "declined",
       "missed"
      ]
     },
     "video": {
      "type": "boolean",
      "description": "Video was on"
     }
    },
    "required": [
     "call_id"
    ]
   },
   "GifRenditionDto": {
    "type": "object",
    "properties": {
     "url": {
      "type": "string"
     },
     "w": {
      "type": "number"
     },
     "h": {
      "type": "number"
     }
    },
    "required": [
     "url",
     "w",
     "h"
    ]
   },
   "GifItemDto": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string"
     },
     "title": {
      "type": "string"
     },
     "width": {
      "type": "number"
     },
     "height": {
      "type": "number"
     },
     "preview": {
      "description": "Small animated GIF for grids",
      "allOf": [
       {
        "$ref": "#/components/schemas/GifRenditionDto"
       }
      ]
     },
     "full": {
      "description": "The GIF to send and show in a conversation",
      "allOf": [
       {
        "$ref": "#/components/schemas/GifRenditionDto"
       }
      ]
     },
     "mp4": {
      "description": "MP4 of the same GIF, smaller to load",
      "allOf": [
       {
        "$ref": "#/components/schemas/GifRenditionDto"
       }
      ]
     }
    },
    "required": [
     "id",
     "title",
     "width",
     "height",
     "preview",
     "full"
    ]
   },
   "GifPageDto": {
    "type": "object",
    "properties": {
     "items": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/GifItemDto"
      }
     },
     "next_offset": {
      "type": "number",
      "nullable": true,
      "description": "offset for the next page; null at the end"
     },
     "attribution": {
      "type": "string",
      "enum": [
       "giphy"
      ],
      "description": "Show \"Powered by GIPHY\" next to the results"
     }
    },
    "required": [
     "items",
     "next_offset",
     "attribution"
    ]
   },
   "GifSettingsDto": {
    "type": "object",
    "properties": {
     "giphy_api_key": {
      "type": "string",
      "maxLength": 128,
      "description": "The channel's Giphy API key (write-only; \"\" removes it)"
     },
     "enabled": {
      "type": "boolean",
      "description": "Turn GIFs on or off for the channel (default on)"
     },
     "rating": {
      "type": "string",
      "enum": [
       "g",
       "pg",
       "pg-13",
       "r",
       ""
      ],
      "description": "Default rating (default pg-13; \"\" resets)"
     },
     "max_rating": {
      "type": "string",
      "enum": [
       "g",
       "pg",
       "pg-13",
       "r",
       ""
      ],
      "description": "Highest rating any request may get (default pg-13; \"\" resets)"
     },
     "hourly_quota": {
      "type": "number",
      "nullable": true,
      "minimum": 1,
      "maximum": 1000000,
      "description": "Provider calls per rolling hour before answers come only from cache (default 80; null resets)"
     }
    }
   }
  }
 },
 "security": [
  {
   "bearer": []
  },
  {
   "access_token": []
  }
 ]
}
