{
  "openapi": "3.1.0",
  "info": {
    "title": "WhatsHooked API",
    "version": "1.0.0",
    "description": "WhatsApp webhook bridge API. Supports whatsmeow (WhatsApp Web) and Meta WhatsApp Business API accounts.\n\n**Authentication** — supply one of:\n- `x-api-key: <key>` header\n- `Authorization: Bearer <key>` header\n- HTTP Basic Auth (`username` / `password`)\n\nEndpoints marked **Business API only** require the target account to be configured with `type: \"business-api\"`."
  },
  "servers": [
    { "url": "", "description": "Same origin" }
  ],
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key"
      },
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer"
      },
      "basicAuth": {
        "type": "http",
        "scheme": "basic"
      }
    },
    "schemas": {
      "StatusOk": {
        "type": "object",
        "properties": {
          "status": { "type": "string", "example": "ok" }
        },
        "required": ["status"]
      },
      "StatusOkWithID": {
        "type": "object",
        "properties": {
          "status": { "type": "string", "example": "ok" },
          "account_id": { "type": "string" }
        }
      },
      "Error": {
        "type": "string",
        "description": "Plain-text error message"
      },
      "Hook": {
        "type": "object",
        "properties": {
          "id":             { "type": "string" },
          "name":          { "type": "string" },
          "url":           { "type": "string", "format": "uri" },
          "method":        { "type": "string", "enum": ["GET", "POST", "PUT", "PATCH"], "default": "POST" },
          "headers":       { "type": "object", "additionalProperties": { "type": "string" } },
          "active":        { "type": "boolean" },
          "events":        { "type": "array", "items": { "type": "string" } },
          "description":   { "type": "string" },
          "allow_insecure":{ "type": "boolean", "description": "Skip TLS certificate verification" }
        },
        "required": ["id", "name", "url", "active"]
      },
      "WhatsAppAccount": {
        "type": "object",
        "properties": {
          "id":           { "type": "string" },
          "type":         { "type": "string", "enum": ["whatsmeow", "business-api"], "default": "whatsmeow" },
          "phone_number": { "type": "string" },
          "session_path": { "type": "string" },
          "show_qr":      { "type": "boolean" },
          "disabled":     { "type": "boolean" },
          "business_api": { "$ref": "#/components/schemas/BusinessAPIConfig" }
        },
        "required": ["id", "type"]
      },
      "BusinessAPIConfig": {
        "type": "object",
        "properties": {
          "phone_number_id":      { "type": "string" },
          "access_token":         { "type": "string" },
          "waba_id":              { "type": "string", "description": "WhatsApp Business Account ID — resolved automatically at connect time from business_account_id if not set" },
          "business_account_id":  { "type": "string", "description": "Facebook Business Manager ID — used to resolve waba_id on first connect" },
          "api_version":          { "type": "string", "default": "v21.0" },
          "webhook_path":         { "type": "string" },
          "verify_token":         { "type": "string" }
        },
        "required": ["phone_number_id", "access_token"]
      },
      "TemplateComponent": {
        "type": "object",
        "description": "A component of a message template (HEADER, BODY, FOOTER, BUTTONS)",
        "properties": {
          "type":       { "type": "string" },
          "format":     { "type": "string" },
          "text":       { "type": "string" },
          "buttons":    { "type": "array", "items": { "type": "object" } },
          "parameters": { "type": "array", "items": { "type": "object" } }
        }
      },
      "TemplateMessageObject": {
        "type": "object",
        "properties": {
          "name":       { "type": "string", "description": "Template name" },
          "language":   { "type": "object", "properties": { "code": { "type": "string" } } },
          "components": { "type": "array", "items": { "$ref": "#/components/schemas/TemplateComponent" } }
        },
        "required": ["name", "language"]
      },
      "InteractiveObject": {
        "type": "object",
        "description": "WhatsApp interactive message (button, list, or flow)",
        "properties": {
          "type":   { "type": "string", "enum": ["button", "list", "flow"] },
          "header": { "type": "object" },
          "body":   { "type": "object", "properties": { "text": { "type": "string" } } },
          "footer": { "type": "object", "properties": { "text": { "type": "string" } } },
          "action": { "type": "object" }
        },
        "required": ["type", "body", "action"]
      },
      "SendContactObject": {
        "type": "object",
        "properties": {
          "name": {
            "type": "object",
            "properties": {
              "formatted_name": { "type": "string" },
              "first_name":     { "type": "string" },
              "last_name":      { "type": "string" }
            },
            "required": ["formatted_name"]
          },
          "phones": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "phone": { "type": "string" },
                "type":  { "type": "string" }
              }
            }
          }
        },
        "required": ["name"]
      },
      "ProductListSection": {
        "type": "object",
        "properties": {
          "title":    { "type": "string" },
          "product_items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "product_retailer_id": { "type": "string" }
              }
            }
          }
        },
        "required": ["title", "product_items"]
      },
      "CachedEvent": {
        "type": "object",
        "properties": {
          "id":        { "type": "string" },
          "timestamp": { "type": "string", "format": "date-time" },
          "event": {
            "type": "object",
            "properties": {
              "type":      { "type": "string" },
              "timestamp": { "type": "string", "format": "date-time" },
              "data":      { "type": "object", "additionalProperties": true }
            }
          }
        }
      }
    }
  },
  "security": [
    { "apiKey": [] },
    { "bearerAuth": [] },
    { "basicAuth": [] }
  ],
  "paths": {
    "/health": {
      "get": {
        "summary": "Health check",
        "operationId": "healthCheck",
        "security": [],
        "tags": ["System"],
        "responses": {
          "200": {
            "description": "Server is healthy",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": { "status": { "type": "string", "example": "healthy" } }
                }
              }
            }
          }
        }
      }
    },

    "/api/hooks": {
      "get": {
        "summary": "List all configured webhooks",
        "operationId": "listHooks",
        "tags": ["Webhooks"],
        "responses": {
          "200": {
            "description": "Array of hooks",
            "content": {
              "application/json": {
                "schema": { "type": "array", "items": { "$ref": "#/components/schemas/Hook" } }
              }
            }
          },
          "401": { "description": "Unauthorized", "content": { "text/plain": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/api/hooks/add": {
      "post": {
        "summary": "Add a new webhook",
        "operationId": "addHook",
        "tags": ["Webhooks"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/Hook" }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Hook created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status":  { "type": "string", "example": "ok" },
                    "hook_id": { "type": "string" }
                  }
                }
              }
            }
          },
          "400": { "description": "Bad request", "content": { "text/plain": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "Unauthorized" }
        }
      }
    },
    "/api/hooks/remove": {
      "post": {
        "summary": "Remove a webhook by ID",
        "operationId": "removeHook",
        "tags": ["Webhooks"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": { "id": { "type": "string" } },
                "required": ["id"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Hook removed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "404": { "description": "Hook not found" }
        }
      }
    },

    "/api/accounts": {
      "get": {
        "summary": "List all WhatsApp accounts",
        "operationId": "listAccounts",
        "tags": ["Accounts"],
        "responses": {
          "200": {
            "description": "Array of accounts",
            "content": {
              "application/json": {
                "schema": { "type": "array", "items": { "$ref": "#/components/schemas/WhatsAppAccount" } }
              }
            }
          },
          "401": { "description": "Unauthorized" }
        }
      }
    },
    "/api/accounts/add": {
      "post": {
        "summary": "Add and connect a new WhatsApp account",
        "operationId": "addAccount",
        "tags": ["Accounts"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/WhatsAppAccount" }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Account added",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status":     { "type": "string", "example": "ok" },
                    "account_id": { "type": "string" }
                  }
                }
              }
            }
          },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Failed to connect" }
        }
      }
    },
    "/api/accounts/update": {
      "post": {
        "summary": "Update an existing account configuration (reconnects if enabled)",
        "operationId": "updateAccount",
        "tags": ["Accounts"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/WhatsAppAccount" }
            }
          }
        },
        "responses": {
          "200": { "description": "Account updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOkWithID" } } } },
          "400": { "description": "Bad request / missing ID" },
          "401": { "description": "Unauthorized" },
          "404": { "description": "Account not found" },
          "500": { "description": "Failed to reconnect" }
        }
      }
    },
    "/api/accounts/remove": {
      "post": {
        "summary": "Remove and disconnect a WhatsApp account",
        "operationId": "removeAccount",
        "tags": ["Accounts"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": { "id": { "type": "string" } },
                "required": ["id"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Account removed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "404": { "description": "Account not found" }
        }
      }
    },
    "/api/accounts/disable": {
      "post": {
        "summary": "Disable and disconnect a WhatsApp account",
        "operationId": "disableAccount",
        "tags": ["Accounts"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": { "id": { "type": "string" } },
                "required": ["id"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Account disabled", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOkWithID" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "404": { "description": "Account not found" },
          "500": { "description": "Failed to save config" }
        }
      }
    },
    "/api/accounts/enable": {
      "post": {
        "summary": "Enable and reconnect a disabled WhatsApp account",
        "operationId": "enableAccount",
        "tags": ["Accounts"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": { "id": { "type": "string" } },
                "required": ["id"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Account enabled", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOkWithID" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "404": { "description": "Account not found" },
          "500": { "description": "Failed to connect or save config" }
        }
      }
    },

    "/api/send": {
      "post": {
        "summary": "Send a text message",
        "operationId": "sendMessage",
        "tags": ["Send"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id": { "type": "string" },
                  "to":         { "type": "string", "description": "Phone number or WhatsApp JID" },
                  "text":       { "type": "string" }
                },
                "required": ["account_id", "to", "text"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Message sent", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request / invalid JID" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Send failed" }
        }
      }
    },
    "/api/send/image": {
      "post": {
        "summary": "Send an image",
        "operationId": "sendImage",
        "tags": ["Send"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id": { "type": "string" },
                  "to":         { "type": "string" },
                  "caption":    { "type": "string" },
                  "mime_type":  { "type": "string", "default": "image/jpeg" },
                  "image_data": { "type": "string", "format": "byte", "description": "Base64-encoded image" }
                },
                "required": ["account_id", "to", "image_data"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Image sent", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Send failed" }
        }
      }
    },
    "/api/send/video": {
      "post": {
        "summary": "Send a video",
        "operationId": "sendVideo",
        "tags": ["Send"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id": { "type": "string" },
                  "to":         { "type": "string" },
                  "caption":    { "type": "string" },
                  "mime_type":  { "type": "string", "default": "video/mp4" },
                  "video_data": { "type": "string", "format": "byte", "description": "Base64-encoded video" }
                },
                "required": ["account_id", "to", "video_data"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Video sent", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Send failed" }
        }
      }
    },
    "/api/send/document": {
      "post": {
        "summary": "Send a document",
        "operationId": "sendDocument",
        "tags": ["Send"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id":    { "type": "string" },
                  "to":            { "type": "string" },
                  "caption":       { "type": "string" },
                  "mime_type":     { "type": "string", "default": "application/octet-stream" },
                  "filename":      { "type": "string", "default": "document" },
                  "document_data": { "type": "string", "format": "byte", "description": "Base64-encoded document" }
                },
                "required": ["account_id", "to", "document_data"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Document sent", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Send failed" }
        }
      }
    },
    "/api/send/audio": {
      "post": {
        "summary": "Send an audio message (Business API only)",
        "operationId": "sendAudio",
        "tags": ["Send"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id": { "type": "string" },
                  "to":         { "type": "string" },
                  "audio_data": { "type": "string", "format": "byte", "description": "Base64-encoded audio" },
                  "mime_type":  { "type": "string", "default": "audio/mpeg" }
                },
                "required": ["account_id", "to", "audio_data"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Audio sent", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Send failed" }
        }
      }
    },
    "/api/send/sticker": {
      "post": {
        "summary": "Send a sticker (Business API only)",
        "operationId": "sendSticker",
        "tags": ["Send"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id":   { "type": "string" },
                  "to":           { "type": "string" },
                  "sticker_data": { "type": "string", "format": "byte", "description": "Base64-encoded WebP sticker" },
                  "mime_type":    { "type": "string", "default": "image/webp" }
                },
                "required": ["account_id", "to", "sticker_data"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Sticker sent", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Send failed" }
        }
      }
    },
    "/api/send/location": {
      "post": {
        "summary": "Send a location (Business API only)",
        "operationId": "sendLocation",
        "tags": ["Send"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id": { "type": "string" },
                  "to":         { "type": "string" },
                  "latitude":   { "type": "number", "format": "double" },
                  "longitude":  { "type": "number", "format": "double" },
                  "name":       { "type": "string" },
                  "address":    { "type": "string" }
                },
                "required": ["account_id", "to", "latitude", "longitude"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Location sent", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Send failed" }
        }
      }
    },
    "/api/send/contacts": {
      "post": {
        "summary": "Send contact card(s) (Business API only)",
        "operationId": "sendContacts",
        "tags": ["Send"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id": { "type": "string" },
                  "to":         { "type": "string" },
                  "contacts":   { "type": "array", "minItems": 1, "items": { "$ref": "#/components/schemas/SendContactObject" } }
                },
                "required": ["account_id", "to", "contacts"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Contacts sent", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Send failed" }
        }
      }
    },
    "/api/send/interactive": {
      "post": {
        "summary": "Send an interactive message — buttons, list, or flow (Business API only)",
        "operationId": "sendInteractive",
        "tags": ["Send"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id":   { "type": "string" },
                  "to":           { "type": "string" },
                  "interactive":  { "$ref": "#/components/schemas/InteractiveObject" }
                },
                "required": ["account_id", "to", "interactive"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Interactive message sent", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Send failed" }
        }
      }
    },
    "/api/send/template": {
      "post": {
        "summary": "Send a template message (Business API only)",
        "operationId": "sendTemplate",
        "tags": ["Send"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id": { "type": "string" },
                  "to":         { "type": "string" },
                  "template":   { "$ref": "#/components/schemas/TemplateMessageObject" }
                },
                "required": ["account_id", "to", "template"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Template message sent", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Send failed" }
        }
      }
    },
    "/api/send/flow": {
      "post": {
        "summary": "Send a WhatsApp Flow message (Business API only)",
        "operationId": "sendFlow",
        "tags": ["Send"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id":    { "type": "string" },
                  "to":            { "type": "string" },
                  "flow_id":       { "type": "string" },
                  "flow_token":    { "type": "string" },
                  "header_text":   { "type": "string" },
                  "body_text":     { "type": "string" },
                  "footer_text":   { "type": "string" },
                  "button_text":   { "type": "string" },
                  "screen":        { "type": "string" },
                  "flow_data":     { "type": "object", "additionalProperties": true }
                },
                "required": ["account_id", "to", "flow_id", "flow_token", "body_text", "button_text"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Flow message sent", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Send failed" }
        }
      }
    },
    "/api/send/reaction": {
      "post": {
        "summary": "Send a reaction emoji to a message (Business API only)",
        "operationId": "sendReaction",
        "tags": ["Send"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id": { "type": "string" },
                  "to":         { "type": "string" },
                  "message_id": { "type": "string" },
                  "emoji":      { "type": "string" }
                },
                "required": ["account_id", "to", "message_id", "emoji"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Reaction sent", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Send failed" }
        }
      }
    },
    "/api/send/catalog": {
      "post": {
        "summary": "Send a catalog message sharing the full product catalog (Business API only)",
        "operationId": "sendCatalog",
        "tags": ["Send", "Catalog"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id":                    { "type": "string" },
                  "to":                            { "type": "string" },
                  "body_text":                     { "type": "string" },
                  "thumbnail_product_retailer_id": { "type": "string" }
                },
                "required": ["account_id", "to", "body_text"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Catalog message sent", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Send failed" }
        }
      }
    },
    "/api/send/product": {
      "post": {
        "summary": "Send a single-product interactive message (Business API only)",
        "operationId": "sendSingleProduct",
        "tags": ["Send", "Catalog"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id":          { "type": "string" },
                  "to":                  { "type": "string" },
                  "catalog_id":          { "type": "string" },
                  "product_retailer_id": { "type": "string" },
                  "body_text":           { "type": "string" },
                  "footer_text":         { "type": "string" }
                },
                "required": ["account_id", "to", "catalog_id", "product_retailer_id", "body_text"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Product message sent", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Send failed" }
        }
      }
    },
    "/api/send/product-list": {
      "post": {
        "summary": "Send a multi-product list message up to 30 products across 10 sections (Business API only)",
        "operationId": "sendProductList",
        "tags": ["Send", "Catalog"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id":   { "type": "string" },
                  "to":           { "type": "string" },
                  "header_text":  { "type": "string" },
                  "body_text":    { "type": "string" },
                  "footer_text":  { "type": "string" },
                  "catalog_id":   { "type": "string" },
                  "sections":     { "type": "array", "minItems": 1, "items": { "$ref": "#/components/schemas/ProductListSection" } }
                },
                "required": ["account_id", "to", "catalog_id", "header_text", "body_text", "sections"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Product list sent", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Send failed" }
        }
      }
    },

    "/api/messages/read": {
      "post": {
        "summary": "Mark a received message as read (Business API only)",
        "operationId": "markAsRead",
        "tags": ["Messages"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id": { "type": "string" },
                  "message_id": { "type": "string" }
                },
                "required": ["account_id", "message_id"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Message marked as read", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Failed" }
        }
      }
    },

    "/api/templates": {
      "post": {
        "summary": "List message templates for an account (Business API only)",
        "operationId": "listTemplates",
        "tags": ["Templates"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": { "account_id": { "type": "string" } },
                "required": ["account_id"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Template list from Meta API", "content": { "application/json": { "schema": { "type": "object" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Meta API error" }
        }
      }
    },
    "/api/templates/upload": {
      "post": {
        "summary": "Create a new message template (Business API only)",
        "operationId": "uploadTemplate",
        "tags": ["Templates"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id":  { "type": "string" },
                  "name":        { "type": "string" },
                  "language":    { "type": "string", "description": "BCP-47 language code e.g. en_US" },
                  "category":    { "type": "string", "enum": ["AUTHENTICATION", "MARKETING", "UTILITY"] },
                  "components":  { "type": "array", "items": { "$ref": "#/components/schemas/TemplateComponent" } }
                },
                "required": ["account_id", "name", "language", "category"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Template created", "content": { "application/json": { "schema": { "type": "object" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Meta API error" }
        }
      }
    },
    "/api/templates/delete": {
      "post": {
        "summary": "Delete a message template (Business API only)",
        "operationId": "deleteTemplate",
        "tags": ["Templates"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id": { "type": "string" },
                  "name":       { "type": "string" },
                  "language":   { "type": "string" }
                },
                "required": ["account_id", "name", "language"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Template deleted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Meta API error" }
        }
      }
    },

    "/api/flows": {
      "post": {
        "summary": "List WhatsApp Flows for an account (Business API only)",
        "operationId": "listFlows",
        "tags": ["Flows"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": { "account_id": { "type": "string" } },
                "required": ["account_id"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Flow list from Meta API", "content": { "application/json": { "schema": { "type": "object" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Meta API error" }
        }
      }
    },
    "/api/flows/create": {
      "post": {
        "summary": "Create a new WhatsApp Flow (Business API only)",
        "operationId": "createFlow",
        "tags": ["Flows"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id": { "type": "string" },
                  "name":       { "type": "string" },
                  "categories": { "type": "array", "items": { "type": "string" } }
                },
                "required": ["account_id", "name", "categories"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Flow created", "content": { "application/json": { "schema": { "type": "object" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Meta API error" }
        }
      }
    },
    "/api/flows/get": {
      "post": {
        "summary": "Get details of a specific Flow (Business API only)",
        "operationId": "getFlow",
        "tags": ["Flows"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id": { "type": "string" },
                  "flow_id":    { "type": "string" }
                },
                "required": ["account_id", "flow_id"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Flow details", "content": { "application/json": { "schema": { "type": "object" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Meta API error" }
        }
      }
    },
    "/api/flows/upload": {
      "post": {
        "summary": "Upload a Flow asset JSON (Business API only)",
        "operationId": "uploadFlowAsset",
        "tags": ["Flows"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id":  { "type": "string" },
                  "flow_id":     { "type": "string" },
                  "asset_name":  { "type": "string" },
                  "asset_data":  { "type": "string", "description": "JSON string of the flow asset" }
                },
                "required": ["account_id", "flow_id", "asset_name", "asset_data"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Asset uploaded", "content": { "application/json": { "schema": { "type": "object" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Meta API error" }
        }
      }
    },
    "/api/flows/publish": {
      "post": {
        "summary": "Publish a Flow (Business API only)",
        "operationId": "publishFlow",
        "tags": ["Flows"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id": { "type": "string" },
                  "flow_id":    { "type": "string" }
                },
                "required": ["account_id", "flow_id"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Flow published", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Meta API error" }
        }
      }
    },
    "/api/flows/deprecate": {
      "post": {
        "summary": "Deprecate a Flow (Business API only)",
        "operationId": "deprecateFlow",
        "tags": ["Flows"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id": { "type": "string" },
                  "flow_id":    { "type": "string" }
                },
                "required": ["account_id", "flow_id"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Flow deprecated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Meta API error" }
        }
      }
    },
    "/api/flows/delete": {
      "post": {
        "summary": "Delete a Flow (Business API only)",
        "operationId": "deleteFlow",
        "tags": ["Flows"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id": { "type": "string" },
                  "flow_id":    { "type": "string" }
                },
                "required": ["account_id", "flow_id"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Flow deleted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Meta API error" }
        }
      }
    },

    "/api/phone-numbers": {
      "post": {
        "summary": "List phone numbers on the business account (Business API only)",
        "operationId": "listPhoneNumbers",
        "tags": ["Phone Numbers"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": { "account_id": { "type": "string" } },
                "required": ["account_id"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Phone number list", "content": { "application/json": { "schema": { "type": "object" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Meta API error" }
        }
      }
    },
    "/api/phone-numbers/request-code": {
      "post": {
        "summary": "Request a verification code for a phone number (Business API only)",
        "operationId": "requestVerificationCode",
        "tags": ["Phone Numbers"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id":      { "type": "string" },
                  "phone_number_id": { "type": "string" },
                  "code_method":     { "type": "string", "enum": ["SMS", "VOICE"] },
                  "language":        { "type": "string", "pattern": "^[a-z]{2,3}(_[A-Z]{2})?$", "default": "en_US", "example": "en_US", "description": "BCP-47 locale e.g. en_US, pt_BR — defaults to en_US if omitted or invalid" }
                },
                "required": ["account_id", "phone_number_id", "code_method"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Verification code requested", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Meta API error" }
        }
      }
    },
    "/api/phone-numbers/verify-code": {
      "post": {
        "summary": "Verify a phone number with the received OTP code (Business API only)",
        "operationId": "verifyCode",
        "tags": ["Phone Numbers"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id":      { "type": "string" },
                  "phone_number_id": { "type": "string" },
                  "code":            { "type": "string", "pattern": "^\\d{4,8}$", "example": "123456", "description": "4–8 digit OTP received via SMS or VOICE" }
                },
                "required": ["account_id", "phone_number_id", "code"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Code verified", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request / invalid code format" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Meta API error" }
        }
      }
    },
    "/api/phone-numbers/register": {
      "post": {
        "summary": "Register a phone number with the WhatsApp Cloud API (Business API only)",
        "operationId": "registerPhoneNumber",
        "tags": ["Phone Numbers"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id":      { "type": "string" },
                  "phone_number_id": { "type": "string" },
                  "pin":             { "type": "string", "pattern": "^\\d{4,8}$", "example": "123456", "description": "Two-step verification PIN (4–8 digits)" }
                },
                "required": ["account_id", "phone_number_id", "pin"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Phone number registered", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request / invalid PIN format" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Meta API error" }
        }
      }
    },

    "/api/catalogs": {
      "post": {
        "summary": "List product catalogs (Business API only)",
        "operationId": "listCatalogs",
        "tags": ["Catalog"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": { "account_id": { "type": "string" } },
                "required": ["account_id"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Catalog list", "content": { "application/json": { "schema": { "type": "object" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Meta API error" }
        }
      }
    },
    "/api/catalogs/products": {
      "post": {
        "summary": "List products in a catalog (Business API only)",
        "operationId": "listProducts",
        "tags": ["Catalog"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id": { "type": "string" },
                  "catalog_id": { "type": "string" }
                },
                "required": ["account_id", "catalog_id"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Product list", "content": { "application/json": { "schema": { "type": "object" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Meta API error" }
        }
      }
    },

    "/api/business-profile": {
      "post": {
        "summary": "Get the WhatsApp Business profile (Business API only)",
        "operationId": "getBusinessProfile",
        "tags": ["Business Profile"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": { "account_id": { "type": "string" } },
                "required": ["account_id"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Business profile", "content": { "application/json": { "schema": { "type": "object" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Meta API error" }
        }
      }
    },
    "/api/business-profile/update": {
      "post": {
        "summary": "Update the WhatsApp Business profile (Business API only)",
        "operationId": "updateBusinessProfile",
        "tags": ["Business Profile"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id":      { "type": "string" },
                  "about":           { "type": "string" },
                  "address":         { "type": "string" },
                  "description":     { "type": "string" },
                  "email":           { "type": "string" },
                  "vertical":        { "type": "string" },
                  "websites":        { "type": "array", "items": { "type": "string" } }
                },
                "required": ["account_id"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Profile updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Meta API error" }
        }
      }
    },

    "/api/media/upload": {
      "post": {
        "summary": "Upload a media file to Meta (Business API only)",
        "operationId": "uploadMedia",
        "tags": ["Media"],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id": { "type": "string" },
                  "file":       { "type": "string", "format": "binary" },
                  "type":       { "type": "string", "description": "MIME type" }
                },
                "required": ["account_id", "file"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Upload response from Meta", "content": { "application/json": { "schema": { "type": "object" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Upload failed" }
        }
      }
    },
    "/api/media-delete": {
      "post": {
        "summary": "Delete a media file from Meta (Business API only)",
        "operationId": "deleteMediaFile",
        "tags": ["Media"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id": { "type": "string" },
                  "media_id":   { "type": "string" }
                },
                "required": ["account_id", "media_id"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Media deleted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatusOk" } } } },
          "400": { "description": "Bad request" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Delete failed" }
        }
      }
    },

    "/api/cache": {
      "get": {
        "summary": "List cached events",
        "operationId": "getCachedEvents",
        "tags": ["Cache"],
        "parameters": [
          {
            "name": "event_type",
            "in": "query",
            "required": false,
            "schema": { "type": "string" },
            "description": "Filter by event type"
          }
        ],
        "responses": {
          "200": {
            "description": "Cached events",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "cached_events": { "type": "array", "items": { "$ref": "#/components/schemas/CachedEvent" } },
                    "count":         { "type": "integer" }
                  }
                }
              }
            }
          },
          "401": { "description": "Unauthorized" },
          "503": { "description": "Message cache not enabled" }
        }
      },
      "delete": {
        "summary": "Clear all cached events",
        "operationId": "clearCache",
        "tags": ["Cache"],
        "parameters": [
          {
            "name": "confirm",
            "in": "query",
            "required": true,
            "schema": { "type": "boolean" },
            "description": "Must be true to confirm clearing"
          }
        ],
        "responses": {
          "200": {
            "description": "Cache cleared",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": { "type": "boolean" },
                    "cleared": { "type": "integer" },
                    "message": { "type": "string" }
                  }
                }
              }
            }
          },
          "400": { "description": "Missing confirm=true" },
          "401": { "description": "Unauthorized" },
          "503": { "description": "Cache not enabled" }
        }
      }
    },
    "/api/cache/stats": {
      "get": {
        "summary": "Get cache statistics",
        "operationId": "getCacheStats",
        "tags": ["Cache"],
        "responses": {
          "200": {
            "description": "Cache stats (enabled=false when cache is disabled)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "enabled":       { "type": "boolean" },
                    "total_count":   { "type": "integer" },
                    "by_event_type": { "type": "object", "additionalProperties": { "type": "integer" } }
                  }
                }
              }
            }
          },
          "401": { "description": "Unauthorized" }
        }
      }
    },
    "/api/cache/replay": {
      "post": {
        "summary": "Replay all cached events to all active webhooks",
        "operationId": "replayCachedEvents",
        "tags": ["Cache"],
        "responses": {
          "200": {
            "description": "Replay result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success":          { "type": "boolean" },
                    "replayed":         { "type": "integer" },
                    "delivered":        { "type": "integer" },
                    "failed":           { "type": "integer" },
                    "remaining_cached": { "type": "integer" }
                  }
                }
              }
            }
          },
          "401": { "description": "Unauthorized" },
          "503": { "description": "Cache not enabled" }
        }
      }
    },
    "/api/cache/event": {
      "get": {
        "summary": "Get a specific cached event by ID",
        "operationId": "getCachedEvent",
        "tags": ["Cache"],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": { "description": "Cached event", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CachedEvent" } } } },
          "400": { "description": "Missing id" },
          "401": { "description": "Unauthorized" },
          "404": { "description": "Event not found" },
          "503": { "description": "Cache not enabled" }
        }
      },
      "delete": {
        "summary": "Delete a specific cached event by ID",
        "operationId": "deleteCachedEvent",
        "tags": ["Cache"],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "Event deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success":  { "type": "boolean" },
                    "event_id": { "type": "string" },
                    "message":  { "type": "string" }
                  }
                }
              }
            }
          },
          "400": { "description": "Missing id" },
          "401": { "description": "Unauthorized" },
          "404": { "description": "Event not found" },
          "503": { "description": "Cache not enabled" }
        }
      }
    },
    "/api/cache/event/replay": {
      "post": {
        "summary": "Replay a single cached event",
        "operationId": "replayCachedEvent",
        "tags": ["Cache"],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": false,
            "schema": { "type": "string" },
            "description": "Event ID — can also be supplied in the JSON body"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": { "id": { "type": "string" } }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Event replayed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success":  { "type": "boolean" },
                    "event_id": { "type": "string" },
                    "message":  { "type": "string" }
                  }
                }
              }
            }
          },
          "400": { "description": "Missing id" },
          "401": { "description": "Unauthorized" },
          "500": { "description": "Replay failed" },
          "503": { "description": "Cache not enabled" }
        }
      }
    }
  },
  "tags": [
    { "name": "System",           "description": "Health and status" },
    { "name": "Webhooks",         "description": "Manage outbound webhook registrations" },
    { "name": "Accounts",         "description": "Manage WhatsApp accounts" },
    { "name": "Send",             "description": "Send messages via WhatsApp" },
    { "name": "Messages",         "description": "Message operations (read receipts)" },
    { "name": "Templates",        "description": "WhatsApp Business message templates (Business API only)" },
    { "name": "Flows",            "description": "WhatsApp Flows management (Business API only)" },
    { "name": "Phone Numbers",    "description": "Phone number verification (Business API only)" },
    { "name": "Catalog",          "description": "Product catalog and commerce (Business API only)" },
    { "name": "Business Profile", "description": "WhatsApp Business profile (Business API only)" },
    { "name": "Media",            "description": "Media file management (Business API only)" },
    { "name": "Cache",            "description": "Message cache management" }
  ]
}
