{
  "openapi": "3.1.0",
  "info": {
    "title": "Waix Public API",
    "version": "1.0.0",
    "description": "Публичный API Waix для гарантированной отправки WhatsApp-сообщений и чтения состояния доставки."
  },
  "servers": [{ "url": "https://whaa.ru/api/v1" }],
  "security": [{ "bearerAuth": [] }],
  "paths": {
    "/messages": {
      "post": {
        "summary": "Поставить сообщение в очередь",
        "operationId": "createMessage",
        "parameters": [{
          "name": "Idempotency-Key",
          "in": "header",
          "required": true,
          "description": "UUID, уникальный для логической отправки.",
          "schema": { "type": "string", "format": "uuid" }
        }],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateMessage" } } }
        },
        "responses": {
          "202": {
            "description": "Сообщение сохранено локально и поставлено в очередь.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/QueuedMessageResponse" } } }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "409": { "$ref": "#/components/responses/Conflict" },
          "422": { "$ref": "#/components/responses/ValidationError" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/messages/{id}": {
      "get": {
        "summary": "Получить сообщение и журнал попыток",
        "operationId": "getMessage",
        "parameters": [{ "$ref": "#/components/parameters/MessageId" }],
        "responses": {
          "200": { "description": "Текущее состояние сообщения.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MessageResponse" } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/messages/{id}/retry": {
      "post": {
        "summary": "Повторить неуспешное сообщение",
        "operationId": "retryMessage",
        "parameters": [{ "$ref": "#/components/parameters/MessageId" }],
        "requestBody": {
          "required": false,
          "content": { "application/json": { "schema": { "type": "object", "properties": { "confirm_outcome_unknown": { "type": "boolean", "default": false } }, "additionalProperties": false } } }
        },
        "responses": {
          "202": { "description": "Новая попытка поставлена в очередь.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MessageResponse" } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "Waix API key", "description": "Ключ с messages:read и/или messages:write." }
    },
    "parameters": {
      "MessageId": { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" }, "description": "Локальный ID Waix." }
    },
    "schemas": {
      "CommonMessageFields": {
        "type": "object",
        "required": ["connection_id", "to"],
        "properties": {
          "connection_id": { "type": "string", "format": "uuid" },
          "to": { "type": "string", "pattern": "^\\+?[0-9]{8,16}$" },
          "client_message_id": { "type": "string", "maxLength": 200 },
          "reply_to_message_id": { "type": "string", "format": "uuid" },
          "media_object_id": { "type": "string", "format": "uuid" }
        }
      },
      "TextMessage": {
        "allOf": [
          { "$ref": "#/components/schemas/CommonMessageFields" },
          { "type": "object", "required": ["type", "text"], "properties": { "type": { "const": "text" }, "text": { "type": "object", "required": ["body"], "properties": { "body": { "type": "string", "minLength": 1, "maxLength": 4096 }, "preview_url": { "type": "boolean", "default": false } }, "additionalProperties": false } } }
        ]
      },
      "LegacyTextMessage": {
        "allOf": [{ "$ref": "#/components/schemas/CommonMessageFields" }, { "type": "object", "required": ["body"], "properties": { "body": { "type": "string", "minLength": 1, "maxLength": 4096 } } }]
      },
      "MediaMessage": {
        "allOf": [
          { "$ref": "#/components/schemas/CommonMessageFields" },
          { "type": "object", "required": ["type", "media"], "properties": {
            "type": { "enum": ["image", "video", "audio", "document", "sticker"] },
            "media": { "type": "object", "properties": { "id": { "type": "string" }, "link": { "type": "string", "format": "uri", "pattern": "^https://" }, "caption": { "type": "string", "maxLength": 1024 }, "filename": { "type": "string", "maxLength": 240 }, "voice": { "type": "boolean" } }, "oneOf": [{ "required": ["id"], "not": { "required": ["link"] } }, { "required": ["link"], "not": { "required": ["id"] } }] }
          } }
        ]
      },
      "TemplateMessage": {
        "allOf": [
          { "$ref": "#/components/schemas/CommonMessageFields" },
          { "type": "object", "required": ["type", "template"], "properties": { "type": { "const": "template" }, "template": { "type": "object", "required": ["name", "language"], "properties": { "name": { "type": "string", "maxLength": 512 }, "language": { "type": "object", "required": ["code"], "properties": { "code": { "type": "string" } } }, "components": { "type": "array", "maxItems": 20, "items": { "type": "object", "additionalProperties": true } } } } } }
        ]
      },
      "InteractiveMessage": {
        "allOf": [
          { "$ref": "#/components/schemas/CommonMessageFields" },
          { "type": "object", "required": ["type", "interactive"], "properties": { "type": { "const": "interactive" }, "interactive": { "type": "object", "required": ["type", "body", "action"], "properties": { "type": { "enum": ["button", "list"] }, "body": { "type": "object", "required": ["text"], "properties": { "text": { "type": "string", "maxLength": 1024 } } }, "action": { "type": "object", "additionalProperties": true } } } } }
        ]
      },
      "ReactionMessage": {
        "allOf": [
          { "$ref": "#/components/schemas/CommonMessageFields" },
          { "type": "object", "required": ["type", "reaction", "reply_to_message_id"], "properties": { "type": { "const": "reaction" }, "reaction": { "type": "object", "required": ["emoji"], "properties": { "emoji": { "type": "string" } } } } }
        ]
      },
      "CreateMessage": { "oneOf": [{ "$ref": "#/components/schemas/TextMessage" }, { "$ref": "#/components/schemas/LegacyTextMessage" }, { "$ref": "#/components/schemas/MediaMessage" }, { "$ref": "#/components/schemas/TemplateMessage" }, { "$ref": "#/components/schemas/InteractiveMessage" }, { "$ref": "#/components/schemas/ReactionMessage" }] },
      "QueuedMessageResponse": { "type": "object", "required": ["data"], "properties": { "data": { "type": "object", "required": ["id", "status"], "properties": { "id": { "type": "string", "format": "uuid" }, "status": { "const": "queued" } } } } },
      "Message": {
        "type": "object",
        "required": ["id", "connection_id", "type", "status"],
        "properties": {
          "id": { "type": "string", "format": "uuid" }, "client_message_id": { "type": ["string", "null"] }, "connection_id": { "type": "string", "format": "uuid" }, "conversation_id": { "type": ["string", "null"], "format": "uuid" }, "to": { "type": ["string", "null"] }, "type": { "type": "string" }, "body": { "type": ["string", "null"] },
          "status": { "enum": ["queued", "processing", "accepted", "sent", "delivered", "read", "failed", "outcome_unknown"] }, "meta_message_id": { "type": ["string", "null"] }, "failure_category": { "type": ["string", "null"] }, "attempt_count": { "type": "integer", "minimum": 0 }, "media_object_id": { "type": ["string", "null"], "format": "uuid" }, "reply_to_message_id": { "type": ["string", "null"], "format": "uuid" },
          "queued_at": { "type": ["string", "null"], "format": "date-time" }, "processing_at": { "type": ["string", "null"], "format": "date-time" }, "accepted_at": { "type": ["string", "null"], "format": "date-time" }, "sent_at": { "type": ["string", "null"], "format": "date-time" }, "delivered_at": { "type": ["string", "null"], "format": "date-time" }, "read_at": { "type": ["string", "null"], "format": "date-time" }, "failed_at": { "type": ["string", "null"], "format": "date-time" }, "attempts": { "type": "array", "items": { "type": "object", "additionalProperties": true } }
        }
      },
      "MessageResponse": { "type": "object", "required": ["data"], "properties": { "data": { "$ref": "#/components/schemas/Message" } } },
      "Error": { "type": "object", "properties": { "error": { "type": "object", "properties": { "code": { "type": "string" }, "message": { "type": "string" }, "request_id": { "type": "string" } } } } }
    },
    "responses": {
      "BadRequest": { "description": "Некорректный запрос.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "Unauthorized": { "description": "Ключ отсутствует, истёк или отозван.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "Forbidden": { "description": "У ключа нет требуемого scope.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "NotFound": { "description": "Сообщение не найдено в организации ключа.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "Conflict": { "description": "Конфликт idempotency или недопустимый retry.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "ValidationError": { "description": "Payload не прошёл предметную проверку.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "RateLimited": { "description": "Превышен лимит запросов.", "headers": { "Retry-After": { "schema": { "type": "integer" } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
    }
  }
}
