{
  "openapi": "3.0.3",
  "info": {
    "title": "Visito M2M API",
    "version": "1.0.0",
    "description": "Tenant-scoped server-to-server API for channels, conversations, custom AI tools, and WhatsApp templates. Send operations are asynchronous and return queued acknowledgements."
  },
  "servers": [
    {
      "url": "https://api.visitoai.com/m2m/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Channels"
    },
    {
      "name": "Conversations"
    },
    {
      "name": "Custom tools"
    },
    {
      "name": "WhatsApp templates"
    }
  ],
  "paths": {
    "/channels": {
      "get": {
        "tags": [
          "Channels"
        ],
        "operationId": "listChannels",
        "summary": "List tenant channels",
        "description": "Requires `channels:read`.",
        "x-required-scope": "channels:read",
        "responses": {
          "200": {
            "description": "Tenant channels",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChannelsResponse"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/conversations": {
      "get": {
        "tags": [
          "Conversations"
        ],
        "operationId": "listConversations",
        "summary": "List the current conversation window",
        "description": "Requires `conversations:read`. This endpoint returns the first live window and does not currently accept a continuation cursor.",
        "x-required-scope": "conversations:read",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "view",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "needs_reply",
                "handoff"
              ],
              "default": "all"
            }
          },
          {
            "name": "replyState",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "failed"
              ],
              "default": "all"
            }
          },
          {
            "name": "policyStatus",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "active",
                "archived",
                "blocked"
              ],
              "default": "all"
            }
          },
          {
            "name": "responseMode",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "ai",
                "manual",
                "frozen"
              ],
              "default": "all"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current conversation window",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationsResponse"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/conversations/{conversationId}": {
      "get": {
        "tags": [
          "Conversations"
        ],
        "operationId": "getConversation",
        "summary": "Read conversation detail and messages",
        "description": "Requires `conversations:read`.",
        "x-required-scope": "conversations:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/ConversationId"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "before",
            "in": "query",
            "description": "Cursor from the previous detail response for older messages.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Conversation detail",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationDetailResponse"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/conversations/{conversationId}/reply": {
      "post": {
        "tags": [
          "Conversations"
        ],
        "operationId": "sendConversationReply",
        "summary": "Queue a reply to an existing conversation",
        "description": "Requires `conversations:write`. At least one of `text` or `mediaId` is required. M2M v1 does not expose a media-upload endpoint.",
        "x-required-scope": "conversations:write",
        "parameters": [
          {
            "$ref": "#/components/parameters/ConversationId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReplyRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Reply accepted and queued, not delivered",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueuedReply"
                }
              }
            }
          },
          "409": {
            "description": "Reply window closed or current state prevents the reply",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/tools": {
      "get": {
        "tags": [
          "Custom tools"
        ],
        "operationId": "listTools",
        "summary": "List custom AI tools",
        "description": "Requires `tools:read`.",
        "x-required-scope": "tools:read",
        "responses": {
          "200": {
            "description": "Custom tool definitions",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolsResponse"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "tags": [
          "Custom tools"
        ],
        "operationId": "createTool",
        "summary": "Create a custom AI tool",
        "description": "Requires `tools:write`. Authentication secrets are accepted on write but never returned.",
        "x-required-scope": "tools:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ToolCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Tool created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/tools/{toolId}": {
      "get": {
        "tags": [
          "Custom tools"
        ],
        "operationId": "getTool",
        "summary": "Read a custom AI tool",
        "description": "Requires `tools:read`.",
        "x-required-scope": "tools:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/ToolId"
          }
        ],
        "responses": {
          "200": {
            "description": "Custom tool definition",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "patch": {
        "tags": [
          "Custom tools"
        ],
        "operationId": "updateTool",
        "summary": "Update a custom AI tool",
        "description": "Requires `tools:write`. Omit `auth.value` to preserve an existing secret.",
        "x-required-scope": "tools:write",
        "parameters": [
          {
            "$ref": "#/components/parameters/ToolId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ToolPatchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "tags": [
          "Custom tools"
        ],
        "operationId": "deleteTool",
        "summary": "Delete a custom AI tool",
        "description": "Requires `tools:write`.",
        "x-required-scope": "tools:write",
        "parameters": [
          {
            "$ref": "#/components/parameters/ToolId"
          }
        ],
        "responses": {
          "200": {
            "description": "Delete result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolDeleteResponse"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/tools/{toolId}/test": {
      "post": {
        "tags": [
          "Custom tools"
        ],
        "operationId": "testTool",
        "summary": "Execute a developer test for a custom tool",
        "description": "Requires `tools:execute`.",
        "x-required-scope": "tools:execute",
        "parameters": [
          {
            "$ref": "#/components/parameters/ToolId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ToolTestRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool test result. An invocation failure is represented by `ok: false` in this response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolTestResponse"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/tools/logs": {
      "get": {
        "tags": [
          "Custom tools"
        ],
        "operationId": "listToolLogs",
        "summary": "List custom tool invocation logs",
        "description": "Requires `tools:logs:read`.",
        "x-required-scope": "tools:logs:read",
        "parameters": [
          {
            "name": "toolId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Invocation logs",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolLogsResponse"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/tools/logs/{logId}": {
      "get": {
        "tags": [
          "Custom tools"
        ],
        "operationId": "getToolLog",
        "summary": "Read one custom tool invocation log",
        "description": "Requires `tools:logs:read`.",
        "x-required-scope": "tools:logs:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/LogId"
          }
        ],
        "responses": {
          "200": {
            "description": "Invocation log",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolLogResponse"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/whatsapp-templates/{channelId}": {
      "get": {
        "tags": [
          "WhatsApp templates"
        ],
        "operationId": "listWhatsappTemplates",
        "summary": "List templates for a WhatsApp channel",
        "description": "Requires `whatsapp_templates:read`.",
        "x-required-scope": "whatsapp_templates:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/ChannelId"
          }
        ],
        "responses": {
          "200": {
            "description": "WhatsApp templates",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsappTemplatesResponse"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "post": {
        "tags": [
          "WhatsApp templates"
        ],
        "operationId": "createWhatsappTemplate",
        "summary": "Create a WhatsApp template for Meta review",
        "description": "Requires `whatsapp_templates:write`.",
        "x-required-scope": "whatsapp_templates:write",
        "parameters": [
          {
            "$ref": "#/components/parameters/ChannelId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WhatsappTemplateCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Template submitted to Meta",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhatsappTemplateResponse"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/whatsapp-templates/{channelId}/send": {
      "post": {
        "tags": [
          "WhatsApp templates"
        ],
        "operationId": "sendWhatsappTemplate",
        "summary": "Queue an approved WhatsApp template",
        "description": "Requires `whatsapp_templates:send`. The response acknowledges queued work, not delivery.",
        "x-required-scope": "whatsapp_templates:send",
        "parameters": [
          {
            "$ref": "#/components/parameters/ChannelId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WhatsappTemplateSendRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Template send accepted and queued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueuedTemplateSend"
                }
              }
            }
          },
          "429": {
            "description": "Rolling 24-hour channel limit reached. Inspect `error.details.retryAfterSeconds`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "Visito M2M API key",
        "description": "Server-side tenant-scoped credential created from Build > API Keys."
      }
    },
    "parameters": {
      "ConversationId": {
        "name": "conversationId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "ChannelId": {
        "name": "channelId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "ToolId": {
        "name": "toolId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "LogId": {
        "name": "logId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "description": "Stable key for one intended outbound operation. Reuse it only with an identical request.",
        "schema": {
          "type": "string",
          "minLength": 1
        }
      }
    },
    "responses": {
      "Error": {
        "description": "Structured error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "example": "M2M_AUTH_INSUFFICIENT_SCOPE"
              },
              "message": {
                "type": "string"
              },
              "details": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        }
      },
      "Channel": {
        "type": "object",
        "required": [
          "id",
          "tenantId",
          "propertyIds",
          "provider",
          "type",
          "active",
          "respondEnabled",
          "degraded",
          "identifiers",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "tenantId": {
            "type": "string"
          },
          "propertyId": {
            "type": "string"
          },
          "propertyIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "provider": {
            "type": "string",
            "enum": [
              "meta",
              "native"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "whatsapp",
              "instagram",
              "messenger",
              "webchat"
            ]
          },
          "name": {
            "type": "string"
          },
          "active": {
            "type": "boolean"
          },
          "respondEnabled": {
            "type": "boolean"
          },
          "degraded": {
            "type": "boolean"
          },
          "identifiers": {
            "type": "object",
            "properties": {
              "phoneNumberId": {
                "type": "string"
              },
              "phoneNumber": {
                "type": "string"
              },
              "wabaId": {
                "type": "string"
              },
              "igAccountId": {
                "type": "string"
              },
              "pageId": {
                "type": "string"
              }
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": true
      },
      "ChannelsResponse": {
        "type": "object",
        "required": [
          "channels"
        ],
        "properties": {
          "channels": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Channel"
            }
          }
        }
      },
      "ConversationParticipant": {
        "type": "object",
        "required": [
          "id"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "phone": {
            "type": "string"
          },
          "username": {
            "type": "string"
          },
          "avatarUrl": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "Conversation": {
        "type": "object",
        "required": [
          "conversationId",
          "tenantId",
          "channel",
          "participant",
          "unreadCount",
          "needsReply",
          "lastMessageAt",
          "lastMessageText",
          "lastMessageRole",
          "messageCount"
        ],
        "properties": {
          "conversationId": {
            "type": "string"
          },
          "conversationKey": {
            "type": "string"
          },
          "tenantId": {
            "type": "string"
          },
          "channel": {
            "type": "string",
            "enum": [
              "whatsapp",
              "instagram",
              "messenger",
              "webchat"
            ]
          },
          "participant": {
            "$ref": "#/components/schemas/ConversationParticipant"
          },
          "unreadCount": {
            "type": "integer"
          },
          "needsReply": {
            "type": "boolean"
          },
          "lastMessageAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastMessageText": {
            "type": "string"
          },
          "lastMessageRole": {
            "type": "string"
          },
          "latestReplyStatus": {
            "type": "string",
            "enum": [
              "queued",
              "sent",
              "failed",
              "blocked",
              "publish_failed"
            ]
          },
          "policyStatus": {
            "type": "string",
            "enum": [
              "active",
              "waiting_tool",
              "handoff_requested",
              "closed",
              "archived",
              "blocked"
            ]
          },
          "responseMode": {
            "type": "string",
            "enum": [
              "ai",
              "manual",
              "frozen"
            ]
          },
          "messageCount": {
            "type": "integer"
          }
        },
        "additionalProperties": true
      },
      "ConversationsResponse": {
        "type": "object",
        "required": [
          "conversations",
          "needsReplyCount",
          "handoffCount",
          "hasMore",
          "asOf",
          "version",
          "liveWindow"
        ],
        "properties": {
          "conversations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Conversation"
            }
          },
          "needsReplyCount": {
            "type": "integer"
          },
          "handoffCount": {
            "type": "integer"
          },
          "nextCursor": {
            "type": "string"
          },
          "hasMore": {
            "type": "boolean"
          },
          "asOf": {
            "type": "string",
            "format": "date-time"
          },
          "version": {
            "type": "integer"
          },
          "liveWindow": {
            "type": "object",
            "required": [
              "limit",
              "maxRows",
              "mode"
            ],
            "properties": {
              "limit": {
                "type": "integer"
              },
              "maxRows": {
                "type": "integer"
              },
              "mode": {
                "type": "string",
                "enum": [
                  "first_page_realtime",
                  "cursor_page"
                ]
              }
            }
          }
        }
      },
      "ConversationMessage": {
        "type": "object",
        "required": [
          "id",
          "role",
          "text",
          "at",
          "author",
          "tools",
          "media",
          "deliverySource"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "eventId": {
            "type": "string",
            "description": "Matches `requestEventId` from a queued send response."
          },
          "externalMessageId": {
            "type": "string"
          },
          "role": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "at": {
            "type": "string",
            "format": "date-time"
          },
          "status": {
            "type": "string"
          },
          "statusReason": {
            "type": "string"
          },
          "author": {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "user",
                  "ai",
                  "operator",
                  "system",
                  "native_channel"
                ]
              },
              "operatorId": {
                "type": "string"
              },
              "operatorName": {
                "type": "string"
              },
              "displayName": {
                "type": "string"
              }
            }
          },
          "tools": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "media": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "deliverySource": {
            "type": "string"
          },
          "deliveries": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "additionalProperties": true
      },
      "ConversationDetailResponse": {
        "type": "object",
        "required": [
          "conversation",
          "messages",
          "hasMore"
        ],
        "properties": {
          "conversation": {
            "$ref": "#/components/schemas/Conversation"
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConversationMessage"
            }
          },
          "nextCursor": {
            "type": "string"
          },
          "hasMore": {
            "type": "boolean"
          }
        }
      },
      "ReplyRequest": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "maxLength": 4096
          },
          "mediaId": {
            "type": "string",
            "description": "Existing Visito media asset for this conversation. M2M v1 does not provide upload."
          },
          "replyToExternalMessageId": {
            "type": "string"
          }
        },
        "anyOf": [
          {
            "required": [
              "text"
            ]
          },
          {
            "required": [
              "mediaId"
            ]
          }
        ],
        "additionalProperties": false
      },
      "QueuedReply": {
        "type": "object",
        "required": [
          "accepted",
          "replyId",
          "conversationId",
          "requestEventId",
          "correlationId",
          "status",
          "acceptedAt"
        ],
        "properties": {
          "accepted": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "replyId": {
            "type": "string"
          },
          "conversationId": {
            "type": "string"
          },
          "requestEventId": {
            "type": "string"
          },
          "correlationId": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued"
            ]
          },
          "acceptedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ToolEndpoint": {
        "type": "object",
        "required": [
          "url",
          "method"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "method": {
            "type": "string",
            "enum": [
              "GET",
              "POST"
            ]
          },
          "timeoutMs": {
            "type": "integer",
            "minimum": 500,
            "maximum": 30000
          }
        },
        "additionalProperties": false
      },
      "ToolAuthInput": {
        "type": "object",
        "required": [
          "type"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "none",
              "bearer",
              "api_key"
            ]
          },
          "headerName": {
            "type": "string"
          },
          "value": {
            "type": "string",
            "writeOnly": true
          }
        },
        "additionalProperties": false
      },
      "ToolCreateRequest": {
        "type": "object",
        "required": [
          "name",
          "description",
          "parameters",
          "endpoint"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "pattern": "^[a-zA-Z_][a-zA-Z0-9_]{0,63}$"
          },
          "description": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2000
          },
          "parameters": {
            "type": "object",
            "description": "JSON Schema for an object input.",
            "additionalProperties": true
          },
          "endpoint": {
            "$ref": "#/components/schemas/ToolEndpoint"
          },
          "auth": {
            "$ref": "#/components/schemas/ToolAuthInput"
          },
          "active": {
            "type": "boolean",
            "default": true
          },
          "readOnly": {
            "type": "boolean",
            "default": true
          },
          "allowInPlayground": {
            "type": "boolean",
            "default": false
          },
          "propertyIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "additionalProperties": false
      },
      "ToolPatchRequest": {
        "type": "object",
        "minProperties": 1,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "pattern": "^[a-zA-Z_][a-zA-Z0-9_]{0,63}$"
          },
          "description": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2000
          },
          "parameters": {
            "type": "object",
            "additionalProperties": true
          },
          "endpoint": {
            "type": "object",
            "properties": {
              "url": {
                "type": "string",
                "format": "uri"
              },
              "method": {
                "type": "string",
                "enum": [
                  "GET",
                  "POST"
                ]
              },
              "timeoutMs": {
                "type": "integer",
                "minimum": 500,
                "maximum": 30000
              }
            },
            "additionalProperties": false
          },
          "auth": {
            "$ref": "#/components/schemas/ToolAuthInput"
          },
          "active": {
            "type": "boolean"
          },
          "readOnly": {
            "type": "boolean"
          },
          "allowInPlayground": {
            "type": "boolean"
          },
          "propertyIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "additionalProperties": false
      },
      "Tool": {
        "type": "object",
        "required": [
          "toolId",
          "tenantId",
          "name",
          "description",
          "parameters",
          "endpoint",
          "auth",
          "active",
          "readOnly",
          "allowInPlayground",
          "propertyIds",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "toolId": {
            "type": "string"
          },
          "tenantId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "parameters": {
            "type": "object",
            "additionalProperties": true
          },
          "endpoint": {
            "$ref": "#/components/schemas/ToolEndpoint"
          },
          "auth": {
            "type": "object",
            "required": [
              "type",
              "configured"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "none",
                  "bearer",
                  "api_key"
                ]
              },
              "headerName": {
                "type": "string"
              },
              "secretLastFour": {
                "type": "string"
              },
              "configured": {
                "type": "boolean"
              }
            }
          },
          "active": {
            "type": "boolean"
          },
          "readOnly": {
            "type": "boolean"
          },
          "allowInPlayground": {
            "type": "boolean"
          },
          "propertyIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ToolsResponse": {
        "type": "object",
        "required": [
          "tools"
        ],
        "properties": {
          "tools": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Tool"
            }
          }
        }
      },
      "ToolResponse": {
        "type": "object",
        "required": [
          "tool"
        ],
        "properties": {
          "tool": {
            "$ref": "#/components/schemas/Tool"
          }
        }
      },
      "ToolDeleteResponse": {
        "type": "object",
        "required": [
          "ok",
          "toolId",
          "changed"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "toolId": {
            "type": "string"
          },
          "changed": {
            "type": "boolean"
          }
        }
      },
      "ToolTestRequest": {
        "type": "object",
        "properties": {
          "input": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "additionalProperties": false
      },
      "ToolInvocationError": {
        "type": "object",
        "required": [
          "code",
          "message",
          "retryable"
        ],
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "retryable": {
            "type": "boolean"
          }
        }
      },
      "ToolTestResponse": {
        "type": "object",
        "required": [
          "ok",
          "durationMs"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "output": {
            "type": "object",
            "additionalProperties": true
          },
          "error": {
            "$ref": "#/components/schemas/ToolInvocationError"
          },
          "durationMs": {
            "type": "integer"
          }
        }
      },
      "ToolLog": {
        "type": "object",
        "required": [
          "logId",
          "tenantId",
          "toolId",
          "toolName",
          "status",
          "method",
          "url",
          "startedAt"
        ],
        "properties": {
          "logId": {
            "type": "string"
          },
          "tenantId": {
            "type": "string"
          },
          "toolId": {
            "type": "string"
          },
          "toolName": {
            "type": "string"
          },
          "conversationId": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "processing",
              "completed",
              "failed"
            ]
          },
          "method": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "requestPayload": {
            "type": "object",
            "additionalProperties": true
          },
          "requestHeaders": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "responseStatus": {
            "type": "integer"
          },
          "responsePayload": {
            "nullable": true
          },
          "error": {
            "$ref": "#/components/schemas/ToolInvocationError"
          },
          "durationMs": {
            "type": "integer"
          },
          "startedAt": {
            "type": "string",
            "format": "date-time"
          },
          "completedAt": {
            "type": "string",
            "format": "date-time"
          },
          "failedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": true
      },
      "ToolLogsResponse": {
        "type": "object",
        "required": [
          "logs"
        ],
        "properties": {
          "logs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ToolLog"
            }
          },
          "hasMore": {
            "type": "boolean"
          },
          "nextCursor": {
            "type": "string"
          }
        }
      },
      "ToolLogResponse": {
        "type": "object",
        "required": [
          "log"
        ],
        "properties": {
          "log": {
            "$ref": "#/components/schemas/ToolLog"
          }
        }
      },
      "WhatsappTemplate": {
        "type": "object",
        "required": [
          "name",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "language": {
            "type": "string"
          },
          "category": {
            "type": "string",
            "enum": [
              "UTILITY",
              "MARKETING",
              "AUTHENTICATION"
            ]
          },
          "components": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "additionalProperties": true
      },
      "WhatsappTemplatesResponse": {
        "type": "object",
        "required": [
          "templates"
        ],
        "properties": {
          "templates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WhatsappTemplate"
            }
          }
        }
      },
      "WhatsappTemplateCreateRequest": {
        "type": "object",
        "required": [
          "template"
        ],
        "properties": {
          "template": {
            "type": "object",
            "required": [
              "name",
              "language",
              "category",
              "components"
            ],
            "properties": {
              "name": {
                "type": "string",
                "pattern": "^[a-z0-9_]+$"
              },
              "language": {
                "type": "string"
              },
              "category": {
                "type": "string",
                "enum": [
                  "UTILITY",
                  "MARKETING",
                  "AUTHENTICATION"
                ]
              },
              "components": {
                "type": "array",
                "minItems": 1,
                "items": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        },
        "additionalProperties": false
      },
      "WhatsappTemplateResponse": {
        "type": "object",
        "required": [
          "template"
        ],
        "properties": {
          "template": {
            "$ref": "#/components/schemas/WhatsappTemplate"
          }
        }
      },
      "WhatsappTemplateSendRequest": {
        "type": "object",
        "required": [
          "to",
          "template"
        ],
        "properties": {
          "to": {
            "type": "string",
            "maxLength": 32
          },
          "template": {
            "type": "object",
            "required": [
              "name",
              "language"
            ],
            "properties": {
              "name": {
                "type": "string"
              },
              "language": {
                "type": "object",
                "required": [
                  "code"
                ],
                "properties": {
                  "code": {
                    "type": "string"
                  }
                }
              },
              "components": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        },
        "additionalProperties": false
      },
      "QueuedTemplateSend": {
        "allOf": [
          {
            "$ref": "#/components/schemas/QueuedReply"
          },
          {
            "type": "object",
            "required": [
              "conversationKey"
            ],
            "properties": {
              "conversationKey": {
                "type": "string"
              }
            }
          }
        ]
      }
    }
  }
}