{
  "openapi": "3.1.0",
  "info": {
    "title": "TehProf.kz Support API",
    "description": "AI-powered helpdesk & ticket management platform. Manage support tickets, contacts, analytics, channels, settings, automation, and Bitrix24 CRM integration over a single tenant-scoped API key.\n\nEvery request is authenticated with a tenant API key (Authorization: Bearer <key>). The tenant is resolved from the key; if tenant_id is provided it MUST match the key tenant, otherwise the call returns 403. Scopes on the key gate each action (see individual descriptions): read (default), write, tickets, webhooks, clients, otp.\n\nThe service contour of the chat gateway (channel provisioning / bot send / webhook registration) and the Zodchiy-only ticket-context/attachment actions are intentionally NOT part of this public contract. They require separate purpose-bound internal identities and cannot be called with customer API keys.",
    "version": "1.1.0",
    "contact": {
      "name": "TehProf.kz",
      "url": "https://support.tehprof.kz",
      "email": "support@tehprof.kz"
    }
  },
  "servers": [
    {
      "url": "https://support.tehprof.kz/api",
      "description": "Production API"
    }
  ],
  "paths": {
    "/mcp-internal.php?action=tenant_info": {
      "get": {
        "operationId": "getTenantInfo",
        "summary": "Get tenant information",
        "description": "Returns tenant details including plan, stats, and configuration. Scope: read. Requires Authorization: Bearer API key; tenant_id must match the key tenant if provided.",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tenant info",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer"
                        },
                        "name": {
                          "type": "string"
                        },
                        "plan": {
                          "type": "string"
                        },
                        "our_portal": {
                          "type": "string"
                        },
                        "bot_name": {
                          "type": "string"
                        },
                        "stats": {
                          "type": "object",
                          "properties": {
                            "ticket_count": {
                              "type": "integer"
                            },
                            "operator_count": {
                              "type": "integer"
                            },
                            "client_count": {
                              "type": "integer"
                            },
                            "channel_count": {
                              "type": "integer"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=get_tickets": {
      "get": {
        "operationId": "listTickets",
        "summary": "List support tickets",
        "description": "Returns a list of support tickets with optional filters by status, priority, operator, and search query. Scope: read (or tickets). Requires Authorization: Bearer API key; tenant_id must match the key tenant.",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "new",
                "estimated",
                "in_progress",
                "on_hold",
                "pending",
                "awaiting_manager",
                "done",
                "closed",
                "reopened",
                "cancelled"
              ]
            }
          },
          {
            "name": "priority",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "low",
                "normal",
                "high",
                "urgent",
                "estimate"
              ]
            }
          },
          {
            "name": "operator_id",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20,
              "maximum": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ticket list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "tickets": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Ticket"
                          }
                        },
                        "total": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=get_ticket": {
      "get": {
        "operationId": "getTicket",
        "summary": "Get ticket details",
        "description": "Returns full ticket details including messages and files. Scope: read (or tickets). Requires Authorization: Bearer API key; tenant_id must match the key tenant.",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "ticket_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ticket details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ticket": {
                          "$ref": "#/components/schemas/Ticket"
                        },
                        "messages": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/TicketMessage"
                          }
                        },
                        "files": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer"
                              },
                              "filename": {
                                "type": "string"
                              },
                              "filesize": {
                                "type": "integer"
                              },
                              "mime_type": {
                                "type": "string"
                              },
                              "created_at": {
                                "type": "string"
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=create_ticket": {
      "post": {
        "operationId": "createTicket",
        "summary": "Create a new ticket",
        "description": "Creates a new support ticket. Optionally syncs the client contact and its company by the tenant's own external keys, and deduplicates by external_ref (same key within the tenant returns the existing ticket). Scope: write. Requires Authorization: Bearer API key; tenant_id must match the key tenant.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tenant_id",
                  "subject"
                ],
                "properties": {
                  "tenant_id": {
                    "type": "integer"
                  },
                  "subject": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "priority": {
                    "type": "string",
                    "enum": [
                      "low",
                      "normal",
                      "high",
                      "urgent",
                      "estimate"
                    ]
                  },
                  "category": {
                    "type": "string"
                  },
                  "operator_id": {
                    "type": "integer",
                    "description": "Assign to this operator (internal user id)."
                  },
                  "external_ref": {
                    "type": "string",
                    "description": "Tenant's own idempotency key; a repeat call with the same value returns the existing ticket."
                  },
                  "client_name": {
                    "type": "string"
                  },
                  "client_email": {
                    "type": "string"
                  },
                  "client_phone": {
                    "type": "string"
                  },
                  "contact_external_id": {
                    "type": "string"
                  },
                  "company_external_id": {
                    "type": "string"
                  },
                  "company_bin": {
                    "type": "string"
                  },
                  "company_name": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created ticket (deduplicated=true when an existing ticket was returned)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer"
                        },
                        "status": {
                          "type": "string"
                        },
                        "company_id": {
                          "type": "integer",
                          "nullable": true
                        },
                        "contact_id": {
                          "type": "integer",
                          "nullable": true
                        },
                        "deduplicated": {
                          "type": "boolean"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=reply_ticket": {
      "post": {
        "operationId": "replyToTicket",
        "summary": "Reply to a ticket",
        "description": "Send a reply message to an existing ticket. Scope: write. Requires Authorization: Bearer API key; tenant_id must match the key tenant.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tenant_id",
                  "ticket_id",
                  "message"
                ],
                "properties": {
                  "tenant_id": {
                    "type": "integer"
                  },
                  "ticket_id": {
                    "type": "integer"
                  },
                  "message": {
                    "type": "string"
                  },
                  "is_internal": {
                    "type": "boolean",
                    "description": "Internal note (not shown to the client) when true."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reply sent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "message_id": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=update_ticket": {
      "post": {
        "operationId": "updateTicket",
        "summary": "Update a ticket",
        "description": "Update status, priority, and/or assigned operator of a ticket. Only the provided fields are changed. Status changes use the canonical ticket state machine and an invalid transition is rejected. Scope: write. Requires Authorization: Bearer API key; tenant_id must match the key tenant.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tenant_id",
                  "ticket_id"
                ],
                "properties": {
                  "tenant_id": {
                    "type": "integer"
                  },
                  "ticket_id": {
                    "type": "integer"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "new",
                      "estimated",
                      "in_progress",
                      "on_hold",
                      "pending",
                      "awaiting_manager",
                      "done",
                      "reopened",
                      "cancelled"
                    ]
                  },
                  "priority": {
                    "type": "string",
                    "enum": [
                      "low",
                      "normal",
                      "high",
                      "urgent",
                      "estimate"
                    ]
                  },
                  "operator_id": {
                    "type": "integer",
                    "description": "Internal user id; 0 unassigns."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Update result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "updated": {
                          "type": "boolean"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=analytics_dashboard": {
      "get": {
        "operationId": "getDashboard",
        "summary": "Get analytics dashboard",
        "description": "Returns support dashboard KPIs for a period: totals, open/resolved, by status and priority. Scope: read. Requires Authorization: Bearer API key; tenant_id must match the key tenant.",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "period",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "today",
                "week",
                "month",
                "quarter"
              ],
              "default": "week"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Dashboard data",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "period": {
                          "type": "string"
                        },
                        "since": {
                          "type": "string"
                        },
                        "summary": {
                          "type": "object",
                          "properties": {
                            "total_tickets": {
                              "type": "integer"
                            },
                            "open_tickets": {
                              "type": "integer"
                            },
                            "resolved_tickets": {
                              "type": "integer"
                            },
                            "critical_open": {
                              "type": "integer"
                            }
                          }
                        },
                        "by_status": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "status": {
                                "type": "string"
                              },
                              "cnt": {
                                "type": "integer"
                              }
                            }
                          }
                        },
                        "by_priority": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "priority": {
                                "type": "string"
                              },
                              "cnt": {
                                "type": "integer"
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=analytics_sla": {
      "get": {
        "operationId": "getSlaAnalytics",
        "summary": "Get SLA rules overview",
        "description": "Returns the tenant's configured SLA rules. Detailed SLA metrics are available in the admin panel. Scope: read. Requires Authorization: Bearer API key; tenant_id must match the key tenant.",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "SLA rules",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "sla_rules": {
                          "type": "array",
                          "items": {
                            "type": "object"
                          }
                        },
                        "note": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=analytics_operators": {
      "get": {
        "operationId": "getOperatorAnalytics",
        "summary": "Get per-operator analytics",
        "description": "Returns per-operator ticket counts (total and resolved) for the tenant. Scope: read. Requires Authorization: Bearer API key; tenant_id must match the key tenant.",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Operator stats",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "operators": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer"
                              },
                              "name": {
                                "type": "string"
                              },
                              "role": {
                                "type": "string"
                              },
                              "ticket_count": {
                                "type": "integer"
                              },
                              "resolved_count": {
                                "type": "integer"
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=get_settings": {
      "get": {
        "operationId": "getSettings",
        "summary": "Get tenant settings",
        "description": "Returns tenant settings by section: general, business_hours, channels, widget, sla (or all). Section 'sla' returns the tenant's SLA rule list in apply order (first match wins); built-in rules sit at the bottom as the fallback. Scope: read. Requires Authorization: Bearer API key; tenant_id must match the key tenant.",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "section",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "general",
                "business_hours",
                "channels",
                "widget",
                "sla"
              ],
              "default": "all"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Settings",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "general": {
                          "type": "object",
                          "properties": {
                            "name": {
                              "type": "string"
                            },
                            "domain": {
                              "type": "string",
                              "nullable": true
                            },
                            "plan": {
                              "type": "string"
                            },
                            "bot_name": {
                              "type": "string"
                            }
                          }
                        },
                        "business_hours": {
                          "type": "array",
                          "items": {
                            "type": "object"
                          }
                        },
                        "channels": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Channel"
                          }
                        },
                        "widgets": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer"
                              },
                              "name": {
                                "type": "string"
                              },
                              "api_key": {
                                "type": "string"
                              },
                              "active": {
                                "type": "integer"
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=update_settings": {
      "post": {
        "operationId": "updateSettings",
        "summary": "Update tenant settings",
        "description": "Update a settings section. 'general' supports company_name and bot_name. 'sla' takes the FULL desired rule list in values.rules — array order becomes apply order, rules without id are created, tenant rules missing from the list are deleted, built-in rules are never deleted (they move to the bottom). Other sections direct you to the admin panel. Scope: write. Requires Authorization: Bearer API key; tenant_id must match the key tenant.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tenant_id",
                  "section"
                ],
                "properties": {
                  "tenant_id": {
                    "type": "integer"
                  },
                  "section": {
                    "type": "string",
                    "enum": [
                      "general",
                      "sla"
                    ]
                  },
                  "values": {
                    "type": "object",
                    "properties": {
                      "company_name": {
                        "type": "string"
                      },
                      "bot_name": {
                        "type": "string"
                      },
                      "rules": {
                        "type": "array",
                        "description": "SLA section only: full desired rule list, in apply order.",
                        "items": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "integer",
                              "description": "Existing rule id; omit to create a new one"
                            },
                            "name": {
                              "type": "string"
                            },
                            "enabled": {
                              "type": "integer",
                              "enum": [
                                0,
                                1
                              ]
                            },
                            "response_minutes": {
                              "type": "integer",
                              "minimum": 15,
                              "maximum": 4320
                            },
                            "resolution_hours": {
                              "type": "integer",
                              "minimum": 1,
                              "maximum": 720
                            },
                            "use_business_hours": {
                              "type": "integer",
                              "enum": [
                                0,
                                1
                              ]
                            },
                            "escalate_after_min": {
                              "type": "integer",
                              "minimum": 0,
                              "maximum": 10080
                            },
                            "escalate_on": {
                              "type": "string",
                              "enum": [
                                "response",
                                "resolution",
                                "both"
                              ]
                            },
                            "any_ticket": {
                              "type": "boolean",
                              "description": "Required as true when creating a custom SLA rule with no conditions; explicit confirmation that the rule applies to every ticket."
                            },
                            "conditions": {
                              "type": "object",
                              "description": "Which tickets the rule applies to. For a new rule an empty object is accepted only together with any_ticket=true.",
                              "properties": {
                                "priority": {
                                  "type": "array",
                                  "items": {
                                    "type": "string",
                                    "enum": [
                                      "urgent",
                                      "high",
                                      "normal",
                                      "low"
                                    ]
                                  }
                                },
                                "company_ids": {
                                  "type": "array",
                                  "items": {
                                    "type": "string"
                                  }
                                },
                                "sources": {
                                  "type": "array",
                                  "items": {
                                    "type": "string"
                                  }
                                },
                                "categories": {
                                  "type": "array",
                                  "items": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Update result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "updated": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "note": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=list_operators": {
      "get": {
        "operationId": "listOperators",
        "summary": "List tenant operators",
        "description": "Returns the tenant's team members (operators) with role and active flag. Scope: read. Requires Authorization: Bearer API key; tenant_id must match the key tenant.",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Operators",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "operators": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Operator"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=list_channels": {
      "get": {
        "operationId": "listChannels",
        "summary": "List tenant channels",
        "description": "Returns the tenant's communication channels (WhatsApp, Telegram, Email, Widget, etc.) with type, name and active flag. Scope: read. Requires Authorization: Bearer API key; tenant_id must match the key tenant.",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Channels",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "channels": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Channel"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=channel_status": {
      "get": {
        "operationId": "getChannelStatus",
        "summary": "Get a channel's status",
        "description": "Returns the status and non-sensitive settings of a single channel by type. Secrets (line key, bot token, mailbox password, webhook verify token) are never returned. Scope: read. Requires Authorization: Bearer API key; tenant_id must match the key tenant.",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "channel_type",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "e.g. whatsapp, telegram_bot, email, widget"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Channel row",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "description": "Channel record (fields depend on channel type)."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=configure_channel": {
      "post": {
        "operationId": "configureChannel",
        "summary": "Configure a channel (read-only hint)",
        "description": "Placeholder for channel configuration over the API; full channel setup is performed in the admin panel. Returns a guidance note. Scope: write. Requires Authorization: Bearer API key; tenant_id must match the key tenant.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tenant_id"
                ],
                "properties": {
                  "tenant_id": {
                    "type": "integer"
                  },
                  "channel_type": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Guidance note",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "note": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=list_automation_rules": {
      "get": {
        "operationId": "listAutomationRules",
        "summary": "List automation rules",
        "description": "Returns the tenant's automation rules. Scope: read. Requires Authorization: Bearer API key; tenant_id must match the key tenant.",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "active_only",
            "in": "query",
            "schema": {
              "type": "boolean",
              "description": "Return only active rules when true."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Automation rules",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "rules": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/AutomationRule"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=create_automation_rule": {
      "post": {
        "operationId": "createAutomationRule",
        "summary": "Create an automation rule",
        "description": "Creates an automation rule that fires on an event with optional conditions and actions. Scope: write. Requires Authorization: Bearer API key; tenant_id must match the key tenant.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tenant_id",
                  "name",
                  "event"
                ],
                "properties": {
                  "tenant_id": {
                    "type": "integer"
                  },
                  "name": {
                    "type": "string"
                  },
                  "event": {
                    "type": "string",
                    "enum": [
                      "ticket_created",
                      "ticket_updated",
                      "message_added",
                      "sla_warning",
                      "time_elapsed"
                    ],
                    "description": "Trigger event."
                  },
                  "conditions": {
                    "type": "array",
                    "description": "Flat list of conditions evaluated with AND logic.",
                    "items": {
                      "type": "object"
                    }
                  },
                  "actions": {
                    "type": "array",
                    "items": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created rule id",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=toggle_automation_rule": {
      "post": {
        "operationId": "toggleAutomationRule",
        "summary": "Enable or disable an automation rule",
        "description": "Sets the active flag of an automation rule. Scope: write. Requires Authorization: Bearer API key; tenant_id must match the key tenant.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tenant_id",
                  "rule_id",
                  "active"
                ],
                "properties": {
                  "tenant_id": {
                    "type": "integer"
                  },
                  "rule_id": {
                    "type": "integer"
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Toggle result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "rule_id": {
                          "type": "integer"
                        },
                        "active": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=list_webhooks": {
      "get": {
        "operationId": "listWebhooks",
        "summary": "List outgoing webhooks",
        "description": "Returns the tenant's outgoing webhooks with delivery stats. Scope: read (or webhooks). Requires Authorization: Bearer API key; tenant_id must match the key tenant.",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Webhooks",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "webhooks": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Webhook"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=list_contacts": {
      "get": {
        "operationId": "listContacts",
        "summary": "List tenant contacts",
        "description": "Returns the tenant's contact directory (non-deleted, non-merged) with the tenant's own external_id. Bitrix and photo identifiers are never returned raw. Scope: clients. Requires Authorization: Bearer API key; tenant_id is derived from the key.",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string",
              "description": "Matches name, email, phone or external_id."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "maximum": 200
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Contacts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "contacts": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Contact"
                          }
                        },
                        "total": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=upsert_contact": {
      "post": {
        "operationId": "upsertContact",
        "summary": "Upsert one contact by external key",
        "description": "Idempotently syncs one contact (and its company) by the tenant's stable external id, then by phone, then by email. tenant_id is taken strictly from the key. Scope: clients. Provide at least one of contact_external_id, phone, email.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "tenant_id": {
                    "type": "integer"
                  },
                  "contact_external_id": {
                    "type": "string"
                  },
                  "external_id": {
                    "type": "string",
                    "description": "Alias for contact_external_id."
                  },
                  "name": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  },
                  "company_external_id": {
                    "type": "string"
                  },
                  "company_bin": {
                    "type": "string"
                  },
                  "company_name": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Upsert result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "contact_id": {
                          "type": "integer"
                        },
                        "company_id": {
                          "type": "integer",
                          "nullable": true
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "created",
                            "updated",
                            "skipped"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=upsert_contacts_bulk": {
      "post": {
        "operationId": "upsertContactsBulk",
        "summary": "Bulk-upsert the contact directory",
        "description": "Idempotently upserts up to 500 contacts (and their companies) by the tenant's external ids in one call. One bad record does not abort the batch. tenant_id is taken strictly from the key. Scope: clients.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "records"
                ],
                "properties": {
                  "tenant_id": {
                    "type": "integer"
                  },
                  "records": {
                    "type": "array",
                    "maxItems": 500,
                    "items": {
                      "type": "object",
                      "properties": {
                        "contact_external_id": {
                          "type": "string"
                        },
                        "external_id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "phone": {
                          "type": "string"
                        },
                        "email": {
                          "type": "string"
                        },
                        "company_external_id": {
                          "type": "string"
                        },
                        "company_bin": {
                          "type": "string"
                        },
                        "company_name": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Batch result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "processed": {
                          "type": "integer"
                        },
                        "created": {
                          "type": "integer"
                        },
                        "updated": {
                          "type": "integer"
                        },
                        "skipped": {
                          "type": "integer"
                        },
                        "errors": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "index": {
                                "type": "integer"
                              },
                              "external_id": {
                                "type": "string"
                              },
                              "error": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "results": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "index": {
                                "type": "integer"
                              },
                              "external_id": {
                                "type": "string"
                              },
                              "status": {
                                "type": "string"
                              },
                              "contact_id": {
                                "type": "integer",
                                "nullable": true
                              },
                              "company_id": {
                                "type": "integer",
                                "nullable": true
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=bitrix_contacts": {
      "get": {
        "operationId": "bitrixContacts",
        "summary": "List Bitrix24 contacts (CRM proxy)",
        "description": "Proxies crm.contact.list to the tenant's connected Bitrix24 portal. Scope: clients. Requires a connected Bitrix24 portal.",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20,
              "maximum": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Bitrix24 contacts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "ID": {
                            "type": "string"
                          },
                          "NAME": {
                            "type": "string"
                          },
                          "LAST_NAME": {
                            "type": "string"
                          },
                          "PHONE": {
                            "type": "array",
                            "items": {
                              "type": "object"
                            }
                          },
                          "EMAIL": {
                            "type": "array",
                            "items": {
                              "type": "object"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=bitrix_deals": {
      "get": {
        "operationId": "bitrixDeals",
        "summary": "List Bitrix24 deals (CRM proxy)",
        "description": "Proxies crm.deal.list to the tenant's connected Bitrix24 portal. Scope: clients. Requires a connected Bitrix24 portal.",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "stage",
            "in": "query",
            "schema": {
              "type": "string",
              "description": "STAGE_ID filter."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20,
              "maximum": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Bitrix24 deals",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "ID": {
                            "type": "string"
                          },
                          "TITLE": {
                            "type": "string"
                          },
                          "STAGE_ID": {
                            "type": "string"
                          },
                          "OPPORTUNITY": {
                            "type": "string"
                          },
                          "CURRENCY_ID": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=bitrix_tasks": {
      "get": {
        "operationId": "bitrixTasks",
        "summary": "List Bitrix24 tasks (CRM proxy)",
        "description": "Proxies tasks.task.list to the tenant's connected Bitrix24 portal. Scope: clients. Requires a connected Bitrix24 portal.",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "responsible_id",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20,
              "maximum": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Bitrix24 tasks",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "ID": {
                            "type": "string"
                          },
                          "TITLE": {
                            "type": "string"
                          },
                          "STATUS": {
                            "type": "string"
                          },
                          "RESPONSIBLE_ID": {
                            "type": "string"
                          },
                          "DEADLINE": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=bitrix_create_task": {
      "post": {
        "operationId": "bitrixCreateTask",
        "summary": "Create a Bitrix24 task (CRM proxy)",
        "description": "Proxies tasks.task.add to the tenant's connected Bitrix24 portal. Scope: clients. Requires a connected Bitrix24 portal.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tenant_id",
                  "title"
                ],
                "properties": {
                  "tenant_id": {
                    "type": "integer"
                  },
                  "title": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "responsible_id": {
                    "type": "integer"
                  },
                  "deadline": {
                    "type": "string",
                    "description": "Bitrix24 date, e.g. 2026-07-20T15:00:00."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created task id",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "task_id": {
                          "type": "integer",
                          "nullable": true
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=bitrix_users": {
      "get": {
        "operationId": "bitrixUsers",
        "summary": "List Bitrix24 users (CRM proxy)",
        "description": "Proxies user.get to the tenant's connected Bitrix24 portal. Scope: clients. Requires a connected Bitrix24 portal.",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "active_only",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Bitrix24 users",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "email": {
                            "type": "string"
                          },
                          "active": {
                            "type": "boolean"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=issue_client_token": {
      "post": {
        "operationId": "issueClientToken",
        "summary": "Issue a passwordless client token",
        "description": "Issues a short-lived client token (ctoken) for an end-user employee anchored on their Bitrix24 identity ({b24_user_id}@{portal_domain}). Idempotent per identity (same user_id is reused). The calling tenant becomes the support queue owner. Scope: clients (sensitive — exactly one narrow scope). tenant_id is derived strictly from the key.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "b24_user_id",
                  "portal_domain"
                ],
                "properties": {
                  "b24_user_id": {
                    "type": "string"
                  },
                  "portal_domain": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string",
                    "description": "Enables the email-collision identity guard when provided."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Issued token",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ctoken": {
                          "type": "string"
                        },
                        "user_id": {
                          "type": "integer"
                        },
                        "expires_in": {
                          "type": "integer",
                          "description": "Seconds (86400 = 24h)."
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=send_otp": {
      "post": {
        "operationId": "sendOtp",
        "summary": "Send a one-time verification code",
        "description": "OTP-as-a-service: generates a 6-digit code and delivers it to a phone via WhatsApp (Telegram fallback). Anti-abuse per target: 60s resend cooldown and 5 codes/hour. Returns an opaque session_id used by verify_otp. Scope: otp (sensitive — exactly one narrow scope). tenant_id is derived strictly from the key.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "phone"
                ],
                "properties": {
                  "tenant_id": {
                    "type": "integer"
                  },
                  "phone": {
                    "type": "string",
                    "description": "Digits; at least 7."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Code sent (or rate-limited via ok:false + error)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "session_id": {
                          "type": "string"
                        },
                        "channel": {
                          "type": "string"
                        },
                        "masked": {
                          "type": "string"
                        },
                        "sent": {
                          "type": "boolean"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp-internal.php?action=verify_otp": {
      "post": {
        "operationId": "verifyOtp",
        "summary": "Verify a one-time code",
        "description": "Verifies a 6-digit code against a session_id (constant-time compare). TTL 10 min, max 5 attempts. Scope: otp (sensitive — exactly one narrow scope). tenant_id is derived strictly from the key.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "session_id",
                  "code"
                ],
                "properties": {
                  "tenant_id": {
                    "type": "integer"
                  },
                  "session_id": {
                    "type": "string"
                  },
                  "code": {
                    "type": "string",
                    "pattern": "^\\d{6}$"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Verification result (invalid/expired codes return ok:false + error)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "verified": {
                          "type": "boolean"
                        },
                        "phone": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/help.php": {
      "get": {
        "operationId": "searchKnowledgeBase",
        "summary": "Search knowledge base",
        "description": "Search support documentation articles by query. Public knowledge base endpoint.",
        "parameters": [
          {
            "name": "action",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "const": "search"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Search results",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "slug": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "snippet": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Ticket": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "subject": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "priority": {
            "type": "string"
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          },
          "client_name": {
            "type": "string"
          },
          "operator_name": {
            "type": "string"
          }
        }
      },
      "TicketMessage": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "author_type": {
            "type": "string",
            "enum": [
              "support",
              "client",
              "system"
            ]
          },
          "author_name": {
            "type": "string"
          },
          "body": {
            "type": "string"
          },
          "created_at": {
            "type": "string"
          },
          "is_internal": {
            "type": "integer"
          }
        }
      },
      "Contact": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "phone": {
            "type": "string"
          },
          "position": {
            "type": "string"
          },
          "external_id": {
            "type": "string",
            "description": "The tenant's own external identifier for this contact."
          }
        }
      },
      "Operator": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "role": {
            "type": "string"
          },
          "active": {
            "type": "integer"
          }
        }
      },
      "Channel": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "type": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "active": {
            "type": "integer"
          },
          "created_at": {
            "type": "string"
          }
        }
      },
      "AutomationRule": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "event": {
            "type": "string"
          },
          "conditions": {
            "type": "string",
            "description": "JSON-encoded condition list."
          },
          "actions": {
            "type": "string",
            "description": "JSON-encoded action list."
          },
          "active": {
            "type": "integer"
          },
          "created_at": {
            "type": "string"
          }
        }
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "events": {
            "type": "string"
          },
          "active": {
            "type": "integer"
          },
          "fire_count": {
            "type": "integer"
          },
          "last_status": {
            "type": "string"
          },
          "last_fired_at": {
            "type": "string"
          }
        }
      }
    },
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Tenant API key from Support admin panel (Settings -> API Keys). Send as Authorization: Bearer <key>. The tenant is resolved from the key; tenant_id mismatch returns 403. Key scopes gate actions: read (default), write, tickets, webhooks, clients, otp."
      }
    }
  },
  "security": [
    {
      "ApiKeyAuth": []
    }
  ]
}
