{
  "openapi": "3.0.3",
  "info": {
    "title": "ApiPay — Public API",
    "description": "API для интеграции с Kaspi Pay QR",
    "version": "2.0.0",
    "contact": {
      "name": "ApiPay.kz Support",
      "url": "https://wa.me/77085167489"
    }
  },
  "servers": [
    {
      "url": "https://bpapi.bazarbay.site/api/v1",
      "description": "Production API"
    }
  ],
  "tags": [
    {
      "name": "Public API / Счета",
      "description": "\nСоздание и управление счетами Kaspi Pay."
    },
    {
      "name": "Public API / Подписки",
      "description": "\nУправление подписками (рекуррентными платежами)."
    },
    {
      "name": "Public API / Возвраты",
      "description": ""
    },
    {
      "name": "Public API / Каталог",
      "description": ""
    },
    {
      "name": "Public API / Клиенты",
      "description": "Точечная проверка номеров клиентов перед созданием счёта/подписки."
    }
  ],
  "components": {
    "securitySchemes": {
      "default": {
        "type": "apiKey",
        "name": "X-API-Key",
        "in": "header",
        "description": "Передайте ваш API ключ в заголовке `X-API-Key`. Ключ можно получить в личном кабинете."
      }
    }
  },
  "security": [
    {
      "default": []
    }
  ],
  "paths": {
    "/invoices": {
      "get": {
        "summary": "Список счетов",
        "operationId": "",
        "description": "Возвращает пагинированный список счетов с возможностью фильтрации.",
        "parameters": [
          {
            "in": "query",
            "name": "search",
            "description": "Поиск по описанию, телефону, external_order_id.",
            "x-description-kk": "Сипаттама, телефон, external_order_id бойынша іздеу.",
            "x-description-en": "Search by description, phone, or external_order_id.",
            "example": "order-123",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Поиск по описанию, телефону, external_order_id.",
              "x-description-kk": "Сипаттама, телефон, external_order_id бойынша іздеу.",
              "x-description-en": "Search by description, phone, or external_order_id.",
              "example": "order-123"
            }
          },
          {
            "in": "query",
            "name": "status",
            "description": "Фильтр по статусу.",
            "x-description-kk": "Мәртебе бойынша сүзу.",
            "x-description-en": "Filter by status.",
            "example": [
              "paid",
              "pending"
            ],
            "required": false,
            "schema": {
              "type": "array",
              "description": "Фильтр по статусу.",
              "x-description-kk": "Мәртебе бойынша сүзу.",
              "x-description-en": "Filter by status.",
              "example": [
                "paid",
                "pending"
              ],
              "items": {
                "type": "string"
              }
            }
          },
          {
            "in": "query",
            "name": "date_from",
            "description": "Дата начала (Y-m-d).",
            "x-description-kk": "Басталу күні (Y-m-d).",
            "x-description-en": "Start date (Y-m-d).",
            "example": "2026-01-01",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Дата начала (Y-m-d).",
              "x-description-kk": "Басталу күні (Y-m-d).",
              "x-description-en": "Start date (Y-m-d).",
              "example": "2026-01-01"
            }
          },
          {
            "in": "query",
            "name": "date_to",
            "description": "Дата окончания (Y-m-d).",
            "x-description-kk": "Аяқталу күні (Y-m-d).",
            "x-description-en": "End date (Y-m-d).",
            "example": "2026-12-31",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Дата окончания (Y-m-d).",
              "x-description-kk": "Аяқталу күні (Y-m-d).",
              "x-description-en": "End date (Y-m-d).",
              "example": "2026-12-31"
            }
          },
          {
            "in": "query",
            "name": "sort_by",
            "description": "Сортировка: id, amount, client_name, status, created_at, paid_at.",
            "x-description-kk": "Сұрыптау: id, amount, client_name, status, created_at, paid_at.",
            "x-description-en": "Sort by: id, amount, client_name, status, created_at, paid_at.",
            "example": "created_at",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Сортировка: id, amount, client_name, status, created_at, paid_at.",
              "x-description-kk": "Сұрыптау: id, amount, client_name, status, created_at, paid_at.",
              "x-description-en": "Sort by: id, amount, client_name, status, created_at, paid_at.",
              "example": "created_at"
            }
          },
          {
            "in": "query",
            "name": "sort_order",
            "description": "Порядок: asc, desc.",
            "x-description-kk": "Реті: asc, desc.",
            "x-description-en": "Order: asc, desc.",
            "example": "desc",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Порядок: asc, desc.",
              "x-description-kk": "Реті: asc, desc.",
              "x-description-en": "Order: asc, desc.",
              "example": "desc"
            }
          },
          {
            "in": "query",
            "name": "per_page",
            "description": "Кол-во на страницу (1-100).",
            "x-description-kk": "Бір беттегі саны (1-100).",
            "x-description-en": "Items per page (1-100).",
            "example": 10,
            "required": false,
            "schema": {
              "type": "integer",
              "description": "Кол-во на страницу (1-100).",
              "x-description-kk": "Бір беттегі саны (1-100).",
              "x-description-en": "Items per page (1-100).",
              "example": 10
            }
          },
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "current_page": 1,
                    "data": [
                      {
                        "id": 1,
                        "amount": "5000.00",
                        "description": "Оплата заказа",
                        "external_order_id": "order-123",
                        "status": "paid",
                        "kaspi_invoice_id": "ABC123",
                        "phone": "77001234567",
                        "client_name": "Иван Иванов",
                        "client_comment": null,
                        "is_sandbox": false,
                        "is_recurring": false,
                        "subtotal": null,
                        "discount_sum": null,
                        "discount_percentage": null,
                        "total_refunded": "0.00",
                        "is_fully_refunded": false,
                        "error_message": null,
                        "error_code": null,
                        "paid_at": "2026-02-26T10:30:00+06:00",
                        "created_at": "2026-02-26T10:25:00+06:00",
                        "items": []
                      }
                    ],
                    "total": 1
                  },
                  "properties": {
                    "current_page": {
                      "description": "Номер текущей страницы.",
                      "x-description-kk": "Ағымдағы беттің нөмірі.",
                      "x-description-en": "Current page number.",
                      "type": "integer",
                      "example": 1
                    },
                    "data": {
                      "description": "Массив записей результата.",
                      "x-description-kk": "Нәтиже жазбаларының массиві.",
                      "x-description-en": "Array of result records.",
                      "type": "array",
                      "example": [
                        {
                          "id": 1,
                          "amount": "5000.00",
                          "description": "Оплата заказа",
                          "external_order_id": "order-123",
                          "status": "paid",
                          "kaspi_invoice_id": "ABC123",
                          "phone": "77001234567",
                          "client_name": "Иван Иванов",
                          "client_comment": null,
                          "is_sandbox": false,
                          "is_recurring": false,
                          "subtotal": null,
                          "discount_sum": null,
                          "discount_percentage": null,
                          "total_refunded": "0.00",
                          "is_fully_refunded": false,
                          "error_message": null,
                          "error_code": null,
                          "paid_at": "2026-02-26T10:30:00+06:00",
                          "created_at": "2026-02-26T10:25:00+06:00",
                          "items": []
                        }
                      ],
                      "items": {
                        "description": "Позиции (товары) объекта.",
                        "x-description-kk": "Нысан позициялары (тауарлар).",
                        "x-description-en": "Line items (products) of the object.",
                        "type": "object",
                        "properties": {
                          "id": {
                            "description": "ID записи.",
                            "x-description-kk": "Жазбаның ID-і.",
                            "x-description-en": "Record ID.",
                            "type": "integer",
                            "example": 1
                          },
                          "amount": {
                            "description": "Сумма в тенге.",
                            "x-description-kk": "Теңгемен сома.",
                            "x-description-en": "Amount in tenge.",
                            "type": "string",
                            "example": "5000.00"
                          },
                          "description": {
                            "description": "Описание.",
                            "x-description-kk": "Сипаттама.",
                            "x-description-en": "Description.",
                            "type": "string",
                            "example": "Оплата заказа"
                          },
                          "external_order_id": {
                            "description": "Внешний ID заказа.",
                            "x-description-kk": "Тапсырыстың сыртқы ID-і.",
                            "x-description-en": "External order ID.",
                            "type": "string",
                            "example": "order-123"
                          },
                          "status": {
                            "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                            "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                            "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                            "type": "string",
                            "example": "paid"
                          },
                          "kaspi_invoice_id": {
                            "description": "ID счёта в системе Kaspi.",
                            "x-description-kk": "Kaspi жүйесіндегі шот ID-і.",
                            "x-description-en": "Invoice ID in the Kaspi system.",
                            "type": "string",
                            "example": "ABC123"
                          },
                          "phone": {
                            "description": "Номер телефона клиента.",
                            "x-description-kk": "Клиенттің телефон нөмірі.",
                            "x-description-en": "Client phone number.",
                            "type": "string",
                            "example": "77001234567"
                          },
                          "client_name": {
                            "description": "Имя клиента.",
                            "x-description-kk": "Клиенттің аты.",
                            "x-description-en": "Client name.",
                            "type": "string",
                            "example": "Иван Иванов"
                          },
                          "client_comment": {
                            "description": "Комментарий клиента (может быть null).",
                            "x-description-kk": "Клиенттің пікірі (null болуы мүмкін).",
                            "x-description-en": "Client's comment (may be null).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "is_sandbox": {
                            "description": "Признак тестового (sandbox) объекта.",
                            "x-description-kk": "Тестілік (sandbox) нысан белгісі.",
                            "x-description-en": "Whether the object is a sandbox (test) object.",
                            "type": "boolean",
                            "example": false
                          },
                          "is_recurring": {
                            "description": "Признак счёта по подписке.",
                            "x-description-kk": "Жазылым бойынша шот белгісі.",
                            "x-description-en": "Whether the invoice belongs to a subscription.",
                            "type": "boolean",
                            "example": false
                          },
                          "subtotal": {
                            "description": "Сумма до скидки (может быть null).",
                            "x-description-kk": "Жеңілдікке дейінгі сома (null болуы мүмкін).",
                            "x-description-en": "Subtotal before discount (may be null).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "discount_sum": {
                            "description": "Сумма скидки (может быть null).",
                            "x-description-kk": "Жеңілдік сомасы (null болуы мүмкін).",
                            "x-description-en": "Discount amount (may be null).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "discount_percentage": {
                            "description": "Процент скидки (может быть null).",
                            "x-description-kk": "Жеңілдік пайызы (null болуы мүмкін).",
                            "x-description-en": "Discount percentage (may be null).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "total_refunded": {
                            "description": "Суммарно возвращено по счёту.",
                            "x-description-kk": "Шот бойынша жалпы қайтарылды.",
                            "x-description-en": "Total amount refunded for the invoice.",
                            "type": "string",
                            "example": "0.00"
                          },
                          "is_fully_refunded": {
                            "description": "Признак полного возврата.",
                            "x-description-kk": "Толық қайтару белгісі.",
                            "x-description-en": "Whether the invoice is fully refunded.",
                            "type": "boolean",
                            "example": false
                          },
                          "error_message": {
                            "description": "Текст ошибки (null если ошибок нет).",
                            "x-description-kk": "Қате мәтіні (қате болмаса null).",
                            "x-description-en": "Error text (null if there is no error).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "paid_at": {
                            "description": "Дата и время оплаты (null если не оплачено).",
                            "x-description-kk": "Төлем күні мен уақыты (төленбесе null).",
                            "x-description-en": "Date and time of payment (null if unpaid).",
                            "type": "string",
                            "example": "2026-02-26T10:30:00+06:00"
                          },
                          "created_at": {
                            "description": "Дата и время создания.",
                            "x-description-kk": "Жасалған күні мен уақыты.",
                            "x-description-en": "Date and time of creation.",
                            "type": "string",
                            "example": "2026-02-26T10:25:00+06:00"
                          },
                          "items": {
                            "description": "Позиции (товары) объекта.",
                            "x-description-kk": "Нысан позициялары (тауарлар).",
                            "x-description-en": "Line items (products) of the object.",
                            "type": "array",
                            "example": []
                          }
                        }
                      }
                    },
                    "total": {
                      "description": "Общее количество записей.",
                      "x-description-kk": "Жазбалардың жалпы саны.",
                      "x-description-en": "Total number of records.",
                      "type": "integer",
                      "example": 1
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Ошибка валидации",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "message": "Validation failed",
                    "errors": {
                      "status": [
                        "The selected status is invalid."
                      ]
                    }
                  },
                  "properties": {
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Validation failed"
                    },
                    "errors": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                          "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                          "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                          "type": "array",
                          "example": [
                            "The selected status is invalid."
                          ],
                          "items": {
                            "description": "Позиции (товары) объекта.",
                            "x-description-kk": "Нысан позициялары (тауарлар).",
                            "x-description-en": "Line items (products) of the object.",
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Счета"
        ]
      },
      "post": {
        "summary": "Создать счёт",
        "operationId": "",
        "description": "Создаёт новый счёт для оплаты через Kaspi Pay.\nДля организаций с каталогом используйте `cart_items` вместо `amount`.",
        "parameters": [
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "id": 1,
                    "amount": "5000.00",
                    "status": "processing",
                    "paid_at": null,
                    "phone": "77001234567",
                    "created_at": "2026-02-26T10:25:00+06:00"
                  },
                  "properties": {
                    "id": {
                      "description": "ID записи.",
                      "x-description-kk": "Жазбаның ID-і.",
                      "x-description-en": "Record ID.",
                      "type": "integer",
                      "example": 1
                    },
                    "amount": {
                      "description": "Сумма в тенге.",
                      "x-description-kk": "Теңгемен сома.",
                      "x-description-en": "Amount in tenge.",
                      "type": "string",
                      "example": "5000.00"
                    },
                    "status": {
                      "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                      "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                      "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                      "type": "string",
                      "example": "processing"
                    },
                    "paid_at": {
                      "description": "Дата и время оплаты (null если не оплачено).",
                      "x-description-kk": "Төлем күні мен уақыты (төленбесе null).",
                      "x-description-en": "Date and time of payment (null if unpaid).",
                      "type": "string",
                      "example": null,
                      "nullable": true
                    },
                    "phone": {
                      "description": "Номер телефона клиента.",
                      "x-description-kk": "Клиенттің телефон нөмірі.",
                      "x-description-en": "Client phone number.",
                      "type": "string",
                      "example": "77001234567"
                    },
                    "created_at": {
                      "description": "Дата и время создания.",
                      "x-description-kk": "Жасалған күні мен уақыты.",
                      "x-description-en": "Date and time of creation.",
                      "type": "string",
                      "example": "2026-02-26T10:25:00+06:00"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "description": "Нет организации",
                      "type": "object",
                      "example": {
                        "error": "Organization not found or not verified",
                        "message": "Please verify an organization before creating invoices."
                      },
                      "properties": {
                        "error": {
                          "type": "string",
                          "example": "Organization not found or not verified"
                        },
                        "message": {
                          "description": "Текстовое сообщение о результате операции.",
                          "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                          "x-description-en": "Text message describing the operation result.",
                          "type": "string",
                          "example": "Please verify an organization before creating invoices."
                        }
                      }
                    },
                    {
                      "description": "Сессия не настроена",
                      "type": "object",
                      "example": {
                        "error": "kaspi_session_not_configured",
                        "message": "Kaspi session is not configured. Please contact support."
                      },
                      "properties": {
                        "error": {
                          "type": "string",
                          "example": "kaspi_session_not_configured"
                        },
                        "message": {
                          "description": "Текстовое сообщение о результате операции.",
                          "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                          "x-description-en": "Text message describing the operation result.",
                          "type": "string",
                          "example": "Kaspi session is not configured. Please contact support."
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "422": {
            "description": "Ошибка валидации",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "message": "Validation failed",
                    "errors": {
                      "phone_number": [
                        "Phone number must be in format 8XXXXXXXXXX (11 digits starting with 8)"
                      ]
                    }
                  },
                  "properties": {
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Validation failed"
                    },
                    "errors": {
                      "type": "object",
                      "properties": {
                        "phone_number": {
                          "description": "Номер телефона подписчика.",
                          "x-description-kk": "Жазылушының телефон нөмірі.",
                          "x-description-en": "Subscriber phone number.",
                          "type": "array",
                          "example": [
                            "Phone number must be in format 8XXXXXXXXXX (11 digits starting with 8)"
                          ],
                          "items": {
                            "description": "Позиции (товары) объекта.",
                            "x-description-kk": "Нысан позициялары (тауарлар).",
                            "x-description-en": "Line items (products) of the object.",
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Сессия невалидна",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "kaspi_session_invalid",
                    "message": "Kaspi session is invalid or expired. Please contact support."
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "kaspi_session_invalid"
                    },
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Kaspi session is invalid or expired. Please contact support."
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Счета"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "phone_number": {
                    "type": "string",
                    "description": "Номер телефона. Формат: 8XXXXXXXXXX.",
                    "x-description-kk": "Телефон нөмірі. Формат: 8XXXXXXXXXX.",
                    "x-description-en": "Phone number. Format: 8XXXXXXXXXX.",
                    "example": "87001234567"
                  },
                  "description": {
                    "type": "string",
                    "description": "Описание счёта (до 500 символов).",
                    "x-description-kk": "Шот сипаттамасы (500 таңбаға дейін).",
                    "x-description-en": "Invoice description (up to 500 characters).",
                    "example": "Оплата заказа №123",
                    "maxLength": 500,
                    "nullable": true
                  },
                  "external_order_id": {
                    "type": "string",
                    "description": "Внешний ID заказа.",
                    "x-description-kk": "Тапсырыстың сыртқы ID-і.",
                    "x-description-en": "External order ID.",
                    "example": "order-123",
                    "nullable": true
                  },
                  "amount": {
                    "type": "number",
                    "description": "Сумма (обязательна без cart_items).",
                    "x-description-kk": "Сома (cart_items болмаса міндетті).",
                    "x-description-en": "Amount (required when cart_items is not provided).",
                    "example": 5000
                  },
                  "cart_items": {
                    "type": "array",
                    "description": "Товары корзины (для организаций с каталогом).",
                    "x-description-kk": "Себет тауарлары (каталогы бар ұйымдар үшін).",
                    "x-description-en": "Cart items (for organizations with a catalog).",
                    "example": [
                      []
                    ],
                    "items": {
                      "type": "object",
                      "properties": {
                        "catalog_item_id": {
                          "type": "integer",
                          "description": "ID товара из каталога.",
                          "x-description-kk": "Каталогтағы тауардың ID-і.",
                          "x-description-en": "Catalog item ID.",
                          "example": 1
                        },
                        "count": {
                          "type": "integer",
                          "description": "Количество.",
                          "x-description-kk": "Саны.",
                          "x-description-en": "Quantity.",
                          "example": 2
                        },
                        "price": {
                          "type": "number",
                          "nullable": true,
                          "description": "Переопределённая цена за единицу. Если не указана — используется selling_price из каталога.",
                          "x-description-kk": "Бірлік үшін қайта анықталған баға. Көрсетілмесе — каталогтан selling_price қолданылады.",
                          "x-description-en": "Overridden unit price. If omitted, selling_price from the catalog is used.",
                          "example": 4500
                        }
                      },
                      "required": [
                        "catalog_item_id",
                        "count"
                      ]
                    }
                  },
                  "discount_percentage": {
                    "type": "number",
                    "description": "Скидка на весь чек, 1-99% (только с cart_items).",
                    "x-description-kk": "Бүкіл чекке жеңілдік, 1-99% (тек cart_items-пен).",
                    "x-description-en": "Discount on the whole check, 1-99% (only with cart_items).",
                    "example": 10
                  }
                },
                "required": [
                  "phone_number"
                ]
              }
            }
          }
        }
      }
    },
    "/invoices/{id}": {
      "get": {
        "summary": "Просмотр счёта",
        "operationId": "",
        "description": "Возвращает детальную информацию о счёте, включая товары.",
        "parameters": [
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "id": 1,
                    "amount": "5000.00",
                    "description": "Оплата заказа",
                    "external_order_id": "order-123",
                    "status": "paid",
                    "kaspi_invoice_id": "INV-123",
                    "phone": "77001234567",
                    "client_name": "Иван Иванов",
                    "client_comment": null,
                    "is_sandbox": false,
                    "is_recurring": false,
                    "subtotal": null,
                    "discount_sum": null,
                    "discount_percentage": null,
                    "total_refunded": "0.00",
                    "is_fully_refunded": false,
                    "error_message": null,
                    "error_code": null,
                    "paid_at": "2026-02-26T10:30:00+06:00",
                    "created_at": "2026-02-26T10:25:00+06:00",
                    "items": []
                  },
                  "properties": {
                    "id": {
                      "description": "ID записи.",
                      "x-description-kk": "Жазбаның ID-і.",
                      "x-description-en": "Record ID.",
                      "type": "integer",
                      "example": 1
                    },
                    "amount": {
                      "description": "Сумма в тенге.",
                      "x-description-kk": "Теңгемен сома.",
                      "x-description-en": "Amount in tenge.",
                      "type": "string",
                      "example": "5000.00"
                    },
                    "description": {
                      "description": "Описание.",
                      "x-description-kk": "Сипаттама.",
                      "x-description-en": "Description.",
                      "type": "string",
                      "example": "Оплата заказа"
                    },
                    "external_order_id": {
                      "description": "Внешний ID заказа.",
                      "x-description-kk": "Тапсырыстың сыртқы ID-і.",
                      "x-description-en": "External order ID.",
                      "type": "string",
                      "example": "order-123"
                    },
                    "status": {
                      "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                      "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                      "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                      "type": "string",
                      "example": "paid"
                    },
                    "kaspi_invoice_id": {
                      "description": "ID счёта в системе Kaspi.",
                      "x-description-kk": "Kaspi жүйесіндегі шот ID-і.",
                      "x-description-en": "Invoice ID in the Kaspi system.",
                      "type": "string",
                      "example": "INV-123"
                    },
                    "phone": {
                      "description": "Номер телефона клиента.",
                      "x-description-kk": "Клиенттің телефон нөмірі.",
                      "x-description-en": "Client phone number.",
                      "type": "string",
                      "example": "77001234567"
                    },
                    "client_name": {
                      "description": "Имя клиента.",
                      "x-description-kk": "Клиенттің аты.",
                      "x-description-en": "Client name.",
                      "type": "string",
                      "example": "Иван Иванов"
                    },
                    "client_comment": {
                      "description": "Комментарий клиента (может быть null).",
                      "x-description-kk": "Клиенттің пікірі (null болуы мүмкін).",
                      "x-description-en": "Client's comment (may be null).",
                      "type": "string",
                      "example": null,
                      "nullable": true
                    },
                    "is_sandbox": {
                      "description": "Признак тестового (sandbox) объекта.",
                      "x-description-kk": "Тестілік (sandbox) нысан белгісі.",
                      "x-description-en": "Whether the object is a sandbox (test) object.",
                      "type": "boolean",
                      "example": false
                    },
                    "is_recurring": {
                      "description": "Признак счёта по подписке.",
                      "x-description-kk": "Жазылым бойынша шот белгісі.",
                      "x-description-en": "Whether the invoice belongs to a subscription.",
                      "type": "boolean",
                      "example": false
                    },
                    "subtotal": {
                      "description": "Сумма до скидки (может быть null).",
                      "x-description-kk": "Жеңілдікке дейінгі сома (null болуы мүмкін).",
                      "x-description-en": "Subtotal before discount (may be null).",
                      "type": "string",
                      "example": null,
                      "nullable": true
                    },
                    "discount_sum": {
                      "description": "Сумма скидки (может быть null).",
                      "x-description-kk": "Жеңілдік сомасы (null болуы мүмкін).",
                      "x-description-en": "Discount amount (may be null).",
                      "type": "string",
                      "example": null,
                      "nullable": true
                    },
                    "discount_percentage": {
                      "description": "Процент скидки (может быть null).",
                      "x-description-kk": "Жеңілдік пайызы (null болуы мүмкін).",
                      "x-description-en": "Discount percentage (may be null).",
                      "type": "string",
                      "example": null,
                      "nullable": true
                    },
                    "total_refunded": {
                      "description": "Суммарно возвращено по счёту.",
                      "x-description-kk": "Шот бойынша жалпы қайтарылды.",
                      "x-description-en": "Total amount refunded for the invoice.",
                      "type": "string",
                      "example": "0.00"
                    },
                    "is_fully_refunded": {
                      "description": "Признак полного возврата.",
                      "x-description-kk": "Толық қайтару белгісі.",
                      "x-description-en": "Whether the invoice is fully refunded.",
                      "type": "boolean",
                      "example": false
                    },
                    "error_message": {
                      "description": "Текст ошибки (null если ошибок нет).",
                      "x-description-kk": "Қате мәтіні (қате болмаса null).",
                      "x-description-en": "Error text (null if there is no error).",
                      "type": "string",
                      "example": null,
                      "nullable": true
                    },
                    "error_code": {
                      "description": "Стабильный snake_case-код ошибки из каталога (раздел «Коды ошибок»). null, если ошибок нет. Стройте логику по этому коду, а не по тексту error_message.",
                      "x-description-kk": "Каталогтан тұрақты snake_case қате коды («Қате кодтары» бөлімі). Қате болмаса — null. Логиканы error_message мәтіні бойынша емес, осы код бойынша құрыңыз.",
                      "x-description-en": "Stable snake_case error code from the catalog (see «Error codes» section). null if there is no error. Build your logic around this code, not the error_message text.",
                      "type": "string",
                      "example": null,
                      "nullable": true
                    },
                    "paid_at": {
                      "description": "Дата и время оплаты (null если не оплачено).",
                      "x-description-kk": "Төлем күні мен уақыты (төленбесе null).",
                      "x-description-en": "Date and time of payment (null if unpaid).",
                      "type": "string",
                      "example": "2026-02-26T10:30:00+06:00"
                    },
                    "created_at": {
                      "description": "Дата и время создания.",
                      "x-description-kk": "Жасалған күні мен уақыты.",
                      "x-description-en": "Date and time of creation.",
                      "type": "string",
                      "example": "2026-02-26T10:25:00+06:00"
                    },
                    "items": {
                      "description": "Позиции (товары) объекта.",
                      "x-description-kk": "Нысан позициялары (тауарлар).",
                      "x-description-en": "Line items (products) of the object.",
                      "type": "array",
                      "example": []
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "Invoice not found"
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Invoice not found"
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Счета"
        ]
      },
      "parameters": [
        {
          "in": "path",
          "name": "id",
          "description": "ID счёта.",
          "example": 1,
          "required": true,
          "schema": {
            "type": "integer"
          }
        }
      ]
    },
    "/invoices/{id}/cancel": {
      "post": {
        "summary": "Отменить счёт",
        "operationId": "",
        "description": "Отменяет счёт в статусе pending или processing. Для production счетов отмена выполняется асинхронно (статус 202).\n\nПосле ответа 202 счёт переходит в статус `cancelling` — НЕ считайте его отменённым сразу. Итог придёт вебхуком `invoice.status_changed` (`cancelled` — отмена прошла, либо `error` — отменить не удалось). Если Kaspi отказал в отмене (как правило, счёт уже оплачен), счёт тихо вернётся в `pending`, а реальный статус (обычно `paid`) доставит синхронизация в течение нескольких минут. Дождитесь вебхука или опросите `GET /invoices/{id}`.",
        "parameters": [
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "message": "Invoice cancelled successfully",
                    "invoice": {
                      "id": 1,
                      "amount": "5000.00",
                      "status": "cancelled",
                      "phone": "77001234567",
                      "created_at": "2026-02-26T10:25:00+06:00"
                    }
                  },
                  "properties": {
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Invoice cancelled successfully"
                    },
                    "invoice": {
                      "description": "Связанный счёт.",
                      "x-description-kk": "Байланысты шот.",
                      "x-description-en": "Related invoice.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "description": "ID записи.",
                          "x-description-kk": "Жазбаның ID-і.",
                          "x-description-en": "Record ID.",
                          "type": "integer",
                          "example": 1
                        },
                        "amount": {
                          "description": "Сумма в тенге.",
                          "x-description-kk": "Теңгемен сома.",
                          "x-description-en": "Amount in tenge.",
                          "type": "string",
                          "example": "5000.00"
                        },
                        "status": {
                          "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                          "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                          "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                          "type": "string",
                          "example": "cancelled"
                        },
                        "phone": {
                          "description": "Номер телефона клиента.",
                          "x-description-kk": "Клиенттің телефон нөмірі.",
                          "x-description-en": "Client phone number.",
                          "type": "string",
                          "example": "77001234567"
                        },
                        "created_at": {
                          "description": "Дата и время создания.",
                          "x-description-kk": "Жасалған күні мен уақыты.",
                          "x-description-en": "Date and time of creation.",
                          "type": "string",
                          "example": "2026-02-26T10:25:00+06:00"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "Асинхронная отмена",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "message": "Invoice cancellation queued",
                    "invoice_id": 1
                  },
                  "properties": {
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Invoice cancellation queued"
                    },
                    "invoice_id": {
                      "description": "ID связанного счёта.",
                      "x-description-kk": "Байланысты шоттың ID-і.",
                      "x-description-en": "Related invoice ID.",
                      "type": "integer",
                      "example": 1
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "Invoice cannot be cancelled",
                    "message": "Only pending or processing invoices can be cancelled"
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Invoice cannot be cancelled"
                    },
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Only pending or processing invoices can be cancelled"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "Invoice not found"
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Invoice not found"
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Счета"
        ]
      },
      "parameters": [
        {
          "in": "path",
          "name": "id",
          "description": "ID счёта.",
          "example": 1,
          "required": true,
          "schema": {
            "type": "integer"
          }
        }
      ]
    },
    "/invoices/{id}/refund": {
      "post": {
        "summary": "Возврат по счёту",
        "operationId": "",
        "description": "Создаёт возврат по оплаченному счёту. Поддерживает полный и частичный возврат,\nа также поэлементный возврат через `return_items`.\n\nОтвет 201 означает, что возврат принят и поставлен в очередь (статус `pending`). Итог придёт вебхуком `invoice.refunded` (`completed` — возврат проведён, либо `failed` — возврат не удался, причина в `refund.error_code`). Дождитесь вебхука или опросите `GET /invoices/{id}/refunds`.",
        "parameters": [
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "message": "Refund created and queued for processing",
                    "refund": {
                      "id": 1,
                      "invoice_id": 1,
                      "user_id": 1,
                      "api_key_id": 1,
                      "amount": "2500.00",
                      "kaspi_refund_id": null,
                      "kaspi_status": null,
                      "status": "pending",
                      "reason": "Брак товара",
                      "initiated_by": "api_key",
                      "error_message": null,
                      "created_at": "2026-02-26T11:00:00+06:00"
                    },
                    "invoice": {
                      "id": 1,
                      "amount": "5000.00",
                      "total_refunded": "0.00",
                      "available_for_refund": 5000,
                      "pending_refund_amount": 2500
                    }
                  },
                  "properties": {
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Refund created and queued for processing"
                    },
                    "refund": {
                      "description": "Объект возврата.",
                      "x-description-kk": "Қайтару нысаны.",
                      "x-description-en": "Refund object.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "description": "ID записи.",
                          "x-description-kk": "Жазбаның ID-і.",
                          "x-description-en": "Record ID.",
                          "type": "integer",
                          "example": 1
                        },
                        "invoice_id": {
                          "description": "ID связанного счёта.",
                          "x-description-kk": "Байланысты шоттың ID-і.",
                          "x-description-en": "Related invoice ID.",
                          "type": "integer",
                          "example": 1
                        },
                        "user_id": {
                          "description": "ID пользователя, инициировавшего операцию.",
                          "x-description-kk": "Операцияны бастаған пайдаланушының ID-і.",
                          "x-description-en": "ID of the user who initiated the operation.",
                          "type": "integer",
                          "example": 1
                        },
                        "api_key_id": {
                          "description": "ID API-ключа.",
                          "x-description-kk": "API-кілттің ID-і.",
                          "x-description-en": "API key ID.",
                          "type": "integer",
                          "example": 1
                        },
                        "amount": {
                          "description": "Сумма в тенге.",
                          "x-description-kk": "Теңгемен сома.",
                          "x-description-en": "Amount in tenge.",
                          "type": "string",
                          "example": "2500.00"
                        },
                        "kaspi_refund_id": {
                          "description": "ID возврата в системе Kaspi (null до обработки).",
                          "x-description-kk": "Kaspi жүйесіндегі қайтару ID-і (өңдеуге дейін null).",
                          "x-description-en": "Refund ID in the Kaspi system (null until processed).",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "kaspi_status": {
                          "description": "Статус возврата в системе Kaspi (null до обработки).",
                          "x-description-kk": "Kaspi жүйесіндегі қайтару мәртебесі (өңдеуге дейін null).",
                          "x-description-en": "Refund status in the Kaspi system (null until processed).",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "status": {
                          "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                          "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                          "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                          "type": "string",
                          "example": "pending"
                        },
                        "reason": {
                          "description": "Причина возврата.",
                          "x-description-kk": "Қайтару себебі.",
                          "x-description-en": "Refund reason.",
                          "type": "string",
                          "example": "Брак товара"
                        },
                        "initiated_by": {
                          "description": "Источник инициации: api_key или dashboard.",
                          "x-description-kk": "Бастау көзі: api_key немесе dashboard.",
                          "x-description-en": "Initiation source: api_key or dashboard.",
                          "type": "string",
                          "example": "api_key"
                        },
                        "error_message": {
                          "description": "Текст ошибки (null если ошибок нет).",
                          "x-description-kk": "Қате мәтіні (қате болмаса null).",
                          "x-description-en": "Error text (null if there is no error).",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "created_at": {
                          "description": "Дата и время создания.",
                          "x-description-kk": "Жасалған күні мен уақыты.",
                          "x-description-en": "Date and time of creation.",
                          "type": "string",
                          "example": "2026-02-26T11:00:00+06:00"
                        }
                      }
                    },
                    "invoice": {
                      "description": "Связанный счёт.",
                      "x-description-kk": "Байланысты шот.",
                      "x-description-en": "Related invoice.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "description": "ID записи.",
                          "x-description-kk": "Жазбаның ID-і.",
                          "x-description-en": "Record ID.",
                          "type": "integer",
                          "example": 1
                        },
                        "amount": {
                          "description": "Сумма в тенге.",
                          "x-description-kk": "Теңгемен сома.",
                          "x-description-en": "Amount in tenge.",
                          "type": "string",
                          "example": "5000.00"
                        },
                        "total_refunded": {
                          "description": "Суммарно возвращено по счёту.",
                          "x-description-kk": "Шот бойынша жалпы қайтарылды.",
                          "x-description-en": "Total amount refunded for the invoice.",
                          "type": "string",
                          "example": "0.00"
                        },
                        "available_for_refund": {
                          "description": "Доступная для возврата сумма.",
                          "x-description-kk": "Қайтаруға қолжетімді сома.",
                          "x-description-en": "Amount available for refund.",
                          "type": "integer",
                          "example": 5000
                        },
                        "pending_refund_amount": {
                          "description": "Сумма возвратов в обработке.",
                          "x-description-kk": "Өңделудегі қайтарулар сомасы.",
                          "x-description-en": "Amount of refunds being processed.",
                          "type": "integer",
                          "example": 2500
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Не подлежит возврату",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "Invoice is not refundable",
                    "message": "Only paid invoices that are not fully refunded can be refunded"
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Invoice is not refundable"
                    },
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Only paid invoices that are not fully refunded can be refunded"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "Invoice not found"
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Invoice not found"
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Счета"
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "amount": {
                    "type": "number",
                    "description": "Сумма возврата (без return_items; по умолчанию — вся доступная сумма).",
                    "x-description-kk": "Қайтару сомасы (return_items болмаса; әдепкіде — барлық қолжетімді сома).",
                    "x-description-en": "Refund amount (without return_items; defaults to the full available amount).",
                    "example": 2500,
                    "nullable": true
                  },
                  "reason": {
                    "type": "string",
                    "description": "Причина возврата.",
                    "x-description-kk": "Қайтару себебі.",
                    "x-description-en": "Refund reason.",
                    "example": "Брак товара",
                    "nullable": true
                  },
                  "return_items": {
                    "type": "array",
                    "description": "Товары для возврата (вместо amount). На каждую позицию укажите РОВНО одно из полей: `count` (целые штуки) ЛИБО `amount` (произвольная сумма по позиции). Указание обоих или ни одного — ошибка 422.",
                    "x-description-kk": "Қайтаруға арналған тауарлар (amount орнына). Әр позицияға ДӘЛ біреуін көрсетіңіз: `count` (бүтін дана) НЕМЕСЕ `amount` (позиция бойынша еркін сома). Екеуін де немесе ешқайсысын көрсету — 422 қатесі.",
                    "x-description-en": "Items to refund (instead of amount). For each position provide EXACTLY one of: `count` (whole units) OR `amount` (arbitrary sum per position). Supplying both or neither is a 422 error.",
                    "example": [
                      {
                        "catalog_item_id": 612506,
                        "amount": 19750
                      },
                      {
                        "catalog_item_id": 99,
                        "count": 2
                      }
                    ],
                    "items": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "catalog_item_id": {
                          "type": "integer",
                          "description": "ID товара из каталога.",
                          "x-description-kk": "Каталогтағы тауардың ID-і.",
                          "x-description-en": "Catalog item ID.",
                          "example": 1
                        },
                        "count": {
                          "type": "integer",
                          "description": "Количество для возврата целыми штуками (сумма = price × count). Взаимоисключимо с amount.",
                          "x-description-kk": "Бүтін данамен қайтару саны (сома = price × count). amount-пен өзара ерекшеленеді.",
                          "x-description-en": "Quantity to refund in whole units (amount = price × count). Mutually exclusive with amount.",
                          "example": 1
                        },
                        "amount": {
                          "type": "number",
                          "description": "Произвольная сумма возврата по позиции (0.01 … 9 999 999.99), не больше остатка по позиции. Взаимоисключимо с count.",
                          "x-description-kk": "Позиция бойынша еркін қайтару сомасы (0.01 … 9 999 999.99), позиция қалдығынан аспайды. count-пен өзара ерекшеленеді.",
                          "x-description-en": "Arbitrary refund amount for the position (0.01 … 9 999 999.99), not exceeding the position remainder. Mutually exclusive with count.",
                          "example": 19750,
                          "nullable": true
                        }
                      },
                      "required": [
                        "catalog_item_id"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      },
      "parameters": [
        {
          "in": "path",
          "name": "id",
          "description": "ID счёта.",
          "example": 1,
          "required": true,
          "schema": {
            "type": "integer"
          }
        }
      ]
    },
    "/invoices/{id}/refunds": {
      "get": {
        "summary": "Список возвратов по счёту",
        "operationId": "",
        "description": "Возвращает все возвраты по конкретному счёту.",
        "parameters": [
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "invoice": {
                      "id": 1,
                      "amount": "5000.00",
                      "total_refunded": "2500.00",
                      "available_for_refund": 2500,
                      "is_fully_refunded": false
                    },
                    "refunds": [
                      {
                        "id": 1,
                        "invoice_id": 1,
                        "user_id": 1,
                        "api_key_id": 1,
                        "amount": "2500.00",
                        "kaspi_refund_id": null,
                        "kaspi_status": null,
                        "status": "completed",
                        "reason": "Брак товара",
                        "initiated_by": "api_key",
                        "error_message": null,
                        "error_code": null,
                        "created_at": "2026-02-26T11:00:00+06:00",
                        "items": []
                      }
                    ],
                    "total": 1
                  },
                  "properties": {
                    "invoice": {
                      "description": "Связанный счёт.",
                      "x-description-kk": "Байланысты шот.",
                      "x-description-en": "Related invoice.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "description": "ID записи.",
                          "x-description-kk": "Жазбаның ID-і.",
                          "x-description-en": "Record ID.",
                          "type": "integer",
                          "example": 1
                        },
                        "amount": {
                          "description": "Сумма в тенге.",
                          "x-description-kk": "Теңгемен сома.",
                          "x-description-en": "Amount in tenge.",
                          "type": "string",
                          "example": "5000.00"
                        },
                        "total_refunded": {
                          "description": "Суммарно возвращено по счёту.",
                          "x-description-kk": "Шот бойынша жалпы қайтарылды.",
                          "x-description-en": "Total amount refunded for the invoice.",
                          "type": "string",
                          "example": "2500.00"
                        },
                        "available_for_refund": {
                          "description": "Доступная для возврата сумма.",
                          "x-description-kk": "Қайтаруға қолжетімді сома.",
                          "x-description-en": "Amount available for refund.",
                          "type": "integer",
                          "example": 2500
                        },
                        "is_fully_refunded": {
                          "description": "Признак полного возврата.",
                          "x-description-kk": "Толық қайтару белгісі.",
                          "x-description-en": "Whether the invoice is fully refunded.",
                          "type": "boolean",
                          "example": false
                        }
                      }
                    },
                    "refunds": {
                      "description": "Список возвратов.",
                      "x-description-kk": "Қайтарулар тізімі.",
                      "x-description-en": "List of refunds.",
                      "type": "array",
                      "example": [
                        {
                          "id": 1,
                          "invoice_id": 1,
                          "user_id": 1,
                          "api_key_id": 1,
                          "amount": "2500.00",
                          "kaspi_refund_id": null,
                          "kaspi_status": null,
                          "status": "completed",
                          "reason": "Брак товара",
                          "initiated_by": "api_key",
                          "error_message": null,
                          "error_code": null,
                          "created_at": "2026-02-26T11:00:00+06:00",
                          "items": []
                        }
                      ],
                      "items": {
                        "description": "Позиции (товары) объекта.",
                        "x-description-kk": "Нысан позициялары (тауарлар).",
                        "x-description-en": "Line items (products) of the object.",
                        "type": "object",
                        "properties": {
                          "id": {
                            "description": "ID записи.",
                            "x-description-kk": "Жазбаның ID-і.",
                            "x-description-en": "Record ID.",
                            "type": "integer",
                            "example": 1
                          },
                          "invoice_id": {
                            "description": "ID связанного счёта.",
                            "x-description-kk": "Байланысты шоттың ID-і.",
                            "x-description-en": "Related invoice ID.",
                            "type": "integer",
                            "example": 1
                          },
                          "user_id": {
                            "description": "ID пользователя, инициировавшего операцию.",
                            "x-description-kk": "Операцияны бастаған пайдаланушының ID-і.",
                            "x-description-en": "ID of the user who initiated the operation.",
                            "type": "integer",
                            "example": 1
                          },
                          "api_key_id": {
                            "description": "ID API-ключа.",
                            "x-description-kk": "API-кілттің ID-і.",
                            "x-description-en": "API key ID.",
                            "type": "integer",
                            "example": 1
                          },
                          "amount": {
                            "description": "Сумма в тенге.",
                            "x-description-kk": "Теңгемен сома.",
                            "x-description-en": "Amount in tenge.",
                            "type": "string",
                            "example": "2500.00"
                          },
                          "kaspi_refund_id": {
                            "description": "ID возврата в системе Kaspi (null до обработки).",
                            "x-description-kk": "Kaspi жүйесіндегі қайтару ID-і (өңдеуге дейін null).",
                            "x-description-en": "Refund ID in the Kaspi system (null until processed).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "kaspi_status": {
                            "description": "Статус возврата в системе Kaspi (null до обработки).",
                            "x-description-kk": "Kaspi жүйесіндегі қайтару мәртебесі (өңдеуге дейін null).",
                            "x-description-en": "Refund status in the Kaspi system (null until processed).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "status": {
                            "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                            "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                            "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                            "type": "string",
                            "example": "completed"
                          },
                          "reason": {
                            "description": "Причина возврата.",
                            "x-description-kk": "Қайтару себебі.",
                            "x-description-en": "Refund reason.",
                            "type": "string",
                            "example": "Брак товара"
                          },
                          "initiated_by": {
                            "description": "Источник инициации: api_key или dashboard.",
                            "x-description-kk": "Бастау көзі: api_key немесе dashboard.",
                            "x-description-en": "Initiation source: api_key or dashboard.",
                            "type": "string",
                            "example": "api_key"
                          },
                          "error_message": {
                            "description": "Текст ошибки (null если ошибок нет).",
                            "x-description-kk": "Қате мәтіні (қате болмаса null).",
                            "x-description-en": "Error text (null if there is no error).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "error_code": {
                            "description": "Стабильный snake_case-код ошибки возврата из каталога (раздел «Коды ошибок»). Заполнен только при status=failed (например refund_window_expired); иначе null. Стройте логику по этому коду, а не по тексту error_message.",
                            "x-description-kk": "Каталогтан тұрақты snake_case қайтару қатесінің коды («Қате кодтары» бөлімі). Тек status=failed болғанда толтырылады (мысалы refund_window_expired); өзге жағдайда null. Логиканы error_message мәтіні бойынша емес, осы код бойынша құрыңыз.",
                            "x-description-en": "Stable snake_case refund error code from the catalog (see «Error codes» section). Set only when status=failed (e.g. refund_window_expired); otherwise null. Build your logic around this code, not the error_message text.",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "created_at": {
                            "description": "Дата и время создания.",
                            "x-description-kk": "Жасалған күні мен уақыты.",
                            "x-description-en": "Date and time of creation.",
                            "type": "string",
                            "example": "2026-02-26T11:00:00+06:00"
                          },
                          "items": {
                            "description": "Позиции (товары) объекта.",
                            "x-description-kk": "Нысан позициялары (тауарлар).",
                            "x-description-en": "Line items (products) of the object.",
                            "type": "array",
                            "example": []
                          }
                        }
                      }
                    },
                    "total": {
                      "description": "Общее количество записей.",
                      "x-description-kk": "Жазбалардың жалпы саны.",
                      "x-description-en": "Total number of records.",
                      "type": "integer",
                      "example": 1
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "Invoice not found"
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Invoice not found"
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Счета"
        ]
      },
      "parameters": [
        {
          "in": "path",
          "name": "id",
          "description": "ID счёта.",
          "example": 1,
          "required": true,
          "schema": {
            "type": "integer"
          }
        }
      ]
    },
    "/invoices/qr": {
      "post": {
        "summary": "Создать QR-счёт",
        "operationId": "",
        "description": "Создаёт счёт для оплаты по QR-коду на экране кассы (без номера телефона клиента).\nПокупатель сканирует QR приложением Kaspi и оплачивает.\nЖизненный цикл QR-счёта — минуты (не 24 часа): точный момент истечения диктует Kaspi, его справочно отдаёт `qr_expires_at`. Терминальный статус (`paid`/`expired`/`cancelled`) определяется по webhook от Kaspi, а НЕ по локальному отсчёту `qr_expires_at` — не терминализуйте QR на своей стороне по таймеру. Отмена и возврат через API для QR не предполагаются как штатный сценарий.\nТело запроса зависит от настройки организации: для `has_catalog=false` — `amount`, для `has_catalog=true` — `cart_items`.\n\n**QR-счета сосуществуют.** Создание нового QR на той же кассе (`kaspi_connection_id`) НЕ отменяет прежние — старый QR остаётся `pending` и мониторится до своего собственного терминала (`paid`, если клиент оплатил именно его, или `expired`). Supersede-вебхука `cancelled` с текстом `\"Заменён новым QR-счётом #N\"` больше НЕ существует. Поскольку QR оплачиваемы независимо, реагируйте на `paid`/`cancelled`/`expired` по каждому `invoice.id` ОТДЕЛЬНО: если клиент оплатит несколько QR — придёт несколько `paid`. Phone-инвойсы (`is_qr_token=false`) живут в Kaspi 24 часа. В sandbox-режиме scope — per-organization + `is_sandbox=true` (одна касса).\n\n**Параллельные запросы.** Лимита/блокировки на параллельность нет. Два параллельных `POST /invoices/qr` на одну кассу теперь оба получают `201` + `status: pending`. Ответ `409 superseded` остался только как defensive-ветка и на практике недостижим — не стройте на нём логику.\n\n**Событие `invoice.qr_scanned`.** Когда клиент отсканировал QR и оказался на экране оплаты, прилетает аддитивный webhook `invoice.qr_scanned` (`status` остаётся `pending`, маркер `qr_substate: \"scanned\"`). Шлётся один раз и транзиентно — после него возможны и `paid`, и `cancelled` (клиент свернул/закрыл приложение). По QR `cancelled` = реальная отмена клиентом.",
        "parameters": [
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "QR создан. Сервер вернул готовую ссылку и PNG-изображение.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "id": 63474,
                    "amount": "100.00",
                    "status": "pending",
                    "paid_at": null,
                    "phone": null,
                    "created_at": "2026-05-09T07:27:37+00:00",
                    "is_qr_token": true,
                    "qr_token_url": "https://qr.kaspi.kz/5180629155669855245469327791577114170390",
                    "qr_image_url": "https://bpapi.bazarbay.site/storage/qr/3f41ee95-5fb1-41b6-8f90-d2ac7aebcb42.png",
                    "qr_expires_at": "2026-05-09T07:32:38+00:00"
                  },
                  "properties": {
                    "id": {
                      "type": "integer",
                      "description": "ID счёта в нашей системе. Используется в GET /invoices/{id} и в webhook-уведомлениях.",
                      "x-description-kk": "Біздің жүйедегі шот ID-і. GET /invoices/{id} және webhook-хабарламаларда қолданылады.",
                      "x-description-en": "Invoice ID in our system. Used in GET /invoices/{id} and in webhook notifications.",
                      "example": 63474
                    },
                    "amount": {
                      "description": "Сумма в тенге.",
                      "x-description-kk": "Теңгемен сома.",
                      "x-description-en": "Amount in tenge.",
                      "type": "string",
                      "example": "100.00"
                    },
                    "status": {
                      "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                      "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                      "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                      "type": "string",
                      "example": "pending"
                    },
                    "paid_at": {
                      "description": "Дата и время оплаты (null если не оплачено).",
                      "x-description-kk": "Төлем күні мен уақыты (төленбесе null).",
                      "x-description-en": "Date and time of payment (null if unpaid).",
                      "type": "string",
                      "example": null,
                      "nullable": true
                    },
                    "phone": {
                      "type": "string",
                      "description": "Всегда null для QR-счетов.",
                      "x-description-kk": "QR-шоттар үшін әрқашан null.",
                      "x-description-en": "Always null for QR invoices.",
                      "example": null,
                      "nullable": true
                    },
                    "created_at": {
                      "description": "Дата и время создания.",
                      "x-description-kk": "Жасалған күні мен уақыты.",
                      "x-description-en": "Date and time of creation.",
                      "type": "string",
                      "format": "date-time",
                      "example": "2026-05-09T07:27:37+00:00"
                    },
                    "is_qr_token": {
                      "type": "boolean",
                      "description": "Признак QR-счёта. Также возвращается в GET /invoices/{id} и в webhook-теле.",
                      "x-description-kk": "QR-шот белгісі. GET /invoices/{id} және webhook денесінде де қайтарылады.",
                      "x-description-en": "QR invoice flag. Also returned in GET /invoices/{id} and in the webhook body.",
                      "example": true
                    },
                    "qr_token_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "Прямая ссылка от Kaspi (qr.kaspi.kz/...). Та же информация, что закодирована в PNG. Можно перерисовать QR на стороне клиента, если нужен другой стиль/размер.",
                      "x-description-kk": "Kaspi-ден тікелей сілтеме (qr.kaspi.kz/...). PNG-де кодталған дәл сол ақпарат. Қажет болса, басқа стиль/өлшем үшін QR-ды клиент жағында қайта салуға болады.",
                      "x-description-en": "Direct link from Kaspi (qr.kaspi.kz/...). The same data encoded in the PNG. You can re-render the QR on the client side if you need a different style/size.",
                      "example": "https://qr.kaspi.kz/5180629155669855245469327791577114170390"
                    },
                    "qr_image_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "Готовый PNG 600×600 с логотипом Kaspi в центре (ECC=High). Доступен без авторизации, живёт qr_expires_at + 60 сек, после чего возвращает 404.",
                      "x-description-kk": "Ортасында Kaspi логотипі бар дайын PNG 600×600 (ECC=High). Авторизациясыз қолжетімді, qr_expires_at + 60 сек өмір сүреді, содан кейін 404 қайтарады.",
                      "x-description-en": "A ready 600×600 PNG with the Kaspi logo in the center (ECC=High). Available without authorization, lives until qr_expires_at + 60 sec, after which it returns 404.",
                      "example": "https://bpapi.bazarbay.site/storage/qr/3f41ee95-5fb1-41b6-8f90-d2ac7aebcb42.png"
                    },
                    "qr_expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Справочное время истечения QR в UTC — берётся из ответа Kaspi (ExpireDate). Жизненный цикл QR — минуты; точное значение задаёт Kaspi. НЕ используйте для локальной терминализации — реальный терминал (expired/paid/cancelled) приходит вебхуком, а не по этому таймеру. Для sandbox и если Kaspi не вернул значение — fallback несколько минут.",
                      "x-description-kk": "QR аяқталу уақыты (UTC, анықтамалық) — Kaspi жауабынан алынады (ExpireDate). QR өмірлік циклі — минуттар; нақты мәнді Kaspi белгілейді. Қолдық терминализация үшін ПАЙДАЛАНБАҢЫЗ — нақты терминал (expired/paid/cancelled) осы таймер бойынша емес, вебхукпен келеді. Sandbox үшін және Kaspi мән қайтармаса — fallback бірнеше минут.",
                      "x-description-en": "QR expiry time in UTC (informational) — taken from the Kaspi response (ExpireDate). The QR lifecycle is minutes; the exact value is set by Kaspi. Do NOT use it for local termination — the real terminal (expired/paid/cancelled) arrives via webhook, not by this timer. For sandbox and when Kaspi returns no value — a few-minute fallback.",
                      "example": "2026-05-09T07:32:38+00:00"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request: organization_required, kaspi_session_not_configured, sandbox_invoice_limit, \"Organization not found or not verified\"",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "description": "Нет организации",
                      "type": "object",
                      "example": {
                        "error": "organization_required",
                        "message": "API key has no organization. Create a sandbox organization or register a real one."
                      },
                      "properties": {
                        "error": {
                          "type": "string",
                          "example": "organization_required"
                        },
                        "message": {
                          "description": "Текстовое сообщение о результате операции.",
                          "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                          "x-description-en": "Text message describing the operation result.",
                          "type": "string",
                          "example": "API key has no organization. Create a sandbox organization or register a real one."
                        }
                      }
                    },
                    {
                      "description": "Сессия Kaspi не настроена",
                      "type": "object",
                      "example": {
                        "error": "kaspi_session_not_configured",
                        "message": "Kaspi session is not configured. Please contact support."
                      },
                      "properties": {
                        "error": {
                          "type": "string",
                          "example": "kaspi_session_not_configured"
                        },
                        "message": {
                          "description": "Текстовое сообщение о результате операции.",
                          "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                          "x-description-en": "Text message describing the operation result.",
                          "type": "string",
                          "example": "Kaspi session is not configured. Please contact support."
                        }
                      }
                    },
                    {
                      "description": "Превышен sandbox-лимит",
                      "type": "object",
                      "example": {
                        "error": "sandbox_invoice_limit",
                        "message": "Sandbox invoice limit exceeded."
                      },
                      "properties": {
                        "error": {
                          "type": "string",
                          "example": "sandbox_invoice_limit"
                        },
                        "message": {
                          "description": "Текстовое сообщение о результате операции.",
                          "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                          "x-description-en": "Text message describing the operation result.",
                          "type": "string",
                          "example": "Sandbox invoice limit exceeded."
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "409": {
            "description": "superseded — defensive-ветка, на практике недостижима: параллельные запросы на одну кассу теперь оба получают 201 + pending, QR-счета сосуществуют. Оставлена для обратной совместимости; не стройте на ней логику.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "superseded",
                    "message": "QR-счёт был заменён более поздним запросом",
                    "invoice_id": 123,
                    "status": "cancelled"
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "superseded"
                    },
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "QR-счёт был заменён более поздним запросом"
                    },
                    "invoice_id": {
                      "description": "ID связанного счёта.",
                      "x-description-kk": "Байланысты шоттың ID-і.",
                      "x-description-en": "Related invoice ID.",
                      "type": "integer",
                      "example": 123
                    },
                    "status": {
                      "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                      "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                      "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                      "type": "string",
                      "example": "cancelled"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Ошибка валидации. Возможные коды error: connection_ambiguous (несколько активных касс, основная не выбрана — передайте kaspi_connection_id); либо стандартные ошибки полей запроса (включая \"This organization requires cart items.\" и \"This organization does not support catalog.\")",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "description": "Несколько активных касс — выбор кассы неоднозначен",
                      "type": "object",
                      "example": {
                        "error": "connection_ambiguous",
                        "message": "Organization has multiple active connections. Please specify kaspi_connection_id."
                      },
                      "properties": {
                        "error": {
                          "type": "string",
                          "example": "connection_ambiguous"
                        },
                        "message": {
                          "description": "Текстовое сообщение о результате операции.",
                          "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                          "x-description-en": "Text message describing the operation result.",
                          "type": "string",
                          "example": "Organization has multiple active connections. Please specify kaspi_connection_id."
                        }
                      }
                    },
                    {
                      "description": "Стандартная ошибка валидации поля",
                      "type": "object",
                      "example": {
                        "message": "Validation failed",
                        "errors": {
                          "amount": [
                            "The amount must be between 0.01 and 99999999.99."
                          ]
                        }
                      },
                      "properties": {
                        "message": {
                          "description": "Текстовое сообщение о результате операции.",
                          "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                          "x-description-en": "Text message describing the operation result.",
                          "type": "string",
                          "example": "Validation failed"
                        },
                        "errors": {
                          "type": "object",
                          "properties": {
                            "amount": {
                              "description": "Сумма в тенге.",
                              "x-description-kk": "Теңгемен сома.",
                              "x-description-en": "Amount in tenge.",
                              "type": "array",
                              "example": [
                                "The amount must be between 0.01 and 99999999.99."
                              ],
                              "items": {
                                "description": "Позиции (товары) объекта.",
                                "x-description-kk": "Нысан позициялары (тауарлар).",
                                "x-description-en": "Line items (products) of the object.",
                                "type": "string"
                              }
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "qr_rate_limit — превышен лимит 60 QR-запросов в минуту на организацию",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "qr_rate_limit",
                    "message": "QR rate limit exceeded. Try again in a minute."
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "qr_rate_limit"
                    },
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "QR rate limit exceeded. Try again in a minute."
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "qr_render_failed — не удалось отрисовать PNG",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "qr_render_failed",
                    "message": "Failed to render QR image."
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "qr_render_failed"
                    },
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Failed to render QR image."
                    }
                  }
                }
              }
            }
          },
          "502": {
            "description": "kaspi_error — Kaspi API вернул ошибку",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "kaspi_error",
                    "message": "Kaspi API error."
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "kaspi_error"
                    },
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Kaspi API error."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "kaspi_session_invalid — сессия Kaspi истекла",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "kaspi_session_invalid",
                    "message": "Kaspi session is invalid or expired. Please contact support."
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "kaspi_session_invalid"
                    },
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Kaspi session is invalid or expired. Please contact support."
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Счета"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Тело зависит от has_catalog: либо amount (без каталога), либо cart_items (с каталогом).",
                "x-description-kk": "Дене has_catalog-қа байланысты: amount (каталогсыз) немесе cart_items (каталогпен).",
                "x-description-en": "The body depends on has_catalog: either amount (no catalog) or cart_items (with catalog).",
                "properties": {
                  "amount": {
                    "type": "number",
                    "description": "Сумма (только если has_catalog=false). От 0.01 до 99 999 999.99 ₸.",
                    "x-description-kk": "Сома (тек has_catalog=false болғанда). 0.01-ден 99 999 999.99 ₸-ге дейін.",
                    "x-description-en": "Amount (only when has_catalog=false). From 0.01 to 99,999,999.99 ₸.",
                    "example": 5000
                  },
                  "description": {
                    "type": "string",
                    "description": "Описание (используется как наименование позиции в QR-чеке Kaspi). Не более 100 символов.",
                    "x-description-kk": "Сипаттама (Kaspi QR-чегінде позиция атауы ретінде қолданылады). 100 таңбадан аспауы керек.",
                    "x-description-en": "Description (used as the line item name in the Kaspi QR receipt). Maximum 100 characters.",
                    "example": "Заказ №123",
                    "maxLength": 100,
                    "nullable": true
                  },
                  "external_order_id": {
                    "type": "string",
                    "description": "Внешний ID заказа.",
                    "x-description-kk": "Тапсырыстың сыртқы ID-і.",
                    "x-description-en": "External order ID.",
                    "example": "order-123",
                    "maxLength": 255,
                    "nullable": true
                  },
                  "cart_items": {
                    "type": "array",
                    "description": "Товары корзины (только для организаций с каталогом, has_catalog=true). От 1 до 100 позиций.",
                    "x-description-kk": "Себет тауарлары (тек каталогы бар ұйымдар үшін, has_catalog=true). 1-ден 100 позицияға дейін.",
                    "x-description-en": "Cart items (only for organizations with a catalog, has_catalog=true). From 1 to 100 items.",
                    "example": [
                      {
                        "catalog_item_id": 608400,
                        "count": 2,
                        "price": 1500
                      }
                    ],
                    "items": {
                      "type": "object",
                      "properties": {
                        "catalog_item_id": {
                          "type": "integer",
                          "description": "ID товара из каталога организации.",
                          "x-description-kk": "Ұйым каталогындағы тауардың ID-і.",
                          "x-description-en": "Item ID from the organization catalog.",
                          "example": 608400
                        },
                        "count": {
                          "type": "integer",
                          "description": "Количество.",
                          "x-description-kk": "Саны.",
                          "x-description-en": "Quantity.",
                          "example": 2
                        },
                        "price": {
                          "type": "number",
                          "nullable": true,
                          "description": "Override цены позиции. Если отличается от каталожной — позиция автоматически переходит в FAST_SALE.",
                          "x-description-kk": "Позиция бағасын қайта анықтау. Каталогтағыдан өзгеше болса — позиция автоматты түрде FAST_SALE-ге ауысады.",
                          "x-description-en": "Override the item price. If it differs from the catalog price, the item automatically switches to FAST_SALE.",
                          "example": 1500
                        }
                      },
                      "required": [
                        "catalog_item_id",
                        "count"
                      ]
                    }
                  },
                  "discount_percentage": {
                    "type": "number",
                    "description": "Скидка на весь чек, 1-99% (только с cart_items).",
                    "x-description-kk": "Бүкіл чекке жеңілдік, 1-99% (тек cart_items-пен).",
                    "x-description-en": "Discount on the whole check, 1-99% (only with cart_items).",
                    "example": 10
                  },
                  "kaspi_connection_id": {
                    "type": "integer",
                    "description": "ID кассира (KaspiConnection), на которого выписать QR-счёт. Опционально. Если не указан и у организации есть primary-касса — берётся она. Если у организации >1 активной кассы и primary не выбрана — вернётся `422 connection_ambiguous`. Нужен для multi-cashier-сценариев.",
                    "x-description-kk": "QR-шот жазылатын кассирдің (KaspiConnection) ID-і. Міндетті емес. Көрсетілмесе және ұйымда primary-касса болса — сол алынады. Ұйымда >1 белсенді касса болып, primary таңдалмаса — `422 connection_ambiguous` қайтарылады. Multi-cashier сценарийлеріне қажет.",
                    "x-description-en": "ID of the cashier (KaspiConnection) the QR invoice is issued for. Optional. If omitted and the organization has a primary cashier, that one is used. If the organization has more than one active cashier and no primary is selected, `422 connection_ambiguous` is returned. Needed for multi-cashier scenarios.",
                    "example": 42,
                    "nullable": true
                  },
                  "simulate": {
                    "type": "string",
                    "enum": [
                      "paid",
                      "cancelled",
                      "expired"
                    ],
                    "description": "Только для sandbox-организаций: создать счёт сразу в нужном терминальном статусе с мгновенной отправкой webhook. Для production-организаций игнорируется молча. Неизвестные значения → 422.",
                    "x-description-kk": "Тек sandbox-ұйымдар үшін: шотты бірден қажетті терминалдық мәртебеде жасап, webhook-ты дереу жіберу. Production-ұйымдар үшін үнсіз еленбейді. Белгісіз мәндер → 422.",
                    "x-description-en": "For sandbox organizations only: create the invoice directly in the desired terminal status and send the webhook instantly. Silently ignored for production organizations. Unknown values → 422.",
                    "example": "paid",
                    "nullable": true
                  }
                }
              }
            }
          }
        }
      }
    },
    "/clients/check": {
      "post": {
        "summary": "Проверить номер клиента в Kaspi",
        "operationId": "",
        "description": "Точечно проверяет, зарегистрирован ли номер в Kaspi, и возвращает имя клиента (если есть). Удобно перед созданием счёта/подписки — чтобы не выставлять счёт на номер без Kaspi.\n\nНомер нормализуется: первая цифра `7` или `+7` заменяется на `8`; пробелы, дефисы и плюсы удаляются. Поддерживаются форматы `77XXXXXXXXX`, `87XXXXXXXXX`, `+77XXXXXXXXX`, с пробелами/дефисами — на выходе всегда `8XXXXXXXXXX` (11 цифр).\n\n**Запрещено использовать эндпоинт для массового перебора номеров (enumeration).** Допустимо только разовое подтверждение в контексте уже известного клиента (перед созданием счёта/подписки или возвратом). На стороне сервера работает многослойная система детекции аномалий — учитываются распределение запросов, шаблоны номеров, поведенческие сигналы и совокупность других факторов (конкретные пороги намеренно не публикуем). При срабатывании детектора API-ключ деактивируется без предупреждения, организация блокируется до ручной проверки, данные передаются в Kaspi. Эта защита введена в интересах пользователей Kaspi — пожалуйста, используйте эндпоинт по назначению.",
        "parameters": [
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Номер проверен. Поле has_kaspi показывает, есть ли клиент в Kaspi.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "phone": "87001234567",
                    "has_kaspi": true,
                    "client_name": "Иван И."
                  },
                  "properties": {
                    "phone": {
                      "type": "string",
                      "description": "Номер в нормализованном виде (8XXXXXXXXXX, 11 цифр).",
                      "x-description-kk": "Нормаланған түрдегі нөмір (8XXXXXXXXXX, 11 цифр).",
                      "x-description-en": "Phone in normalized form (8XXXXXXXXXX, 11 digits).",
                      "example": "87001234567"
                    },
                    "has_kaspi": {
                      "type": "boolean",
                      "description": "true — у клиента установлено приложение Kaspi и он зарегистрирован. false — клиент не найден или у него нет Kaspi (создавать счёт на этот номер нельзя — он упадёт в error).",
                      "x-description-kk": "true — клиентте Kaspi қосымшасы орнатылған және ол тіркелген. false — клиент табылмады немесе оның Kaspi-і жоқ (бұл нөмірге шот жасауға болмайды — ол error-ге түседі).",
                      "x-description-en": "true — the client has the Kaspi app installed and is registered. false — the client was not found or has no Kaspi (you cannot create an invoice for this number — it will fail with error).",
                      "example": true
                    },
                    "client_name": {
                      "type": "string",
                      "description": "Имя клиента из Kaspi в формате «Имя Ф.». null если has_kaspi=false.",
                      "x-description-kk": "Kaspi-дегі клиент аты «Аты Т.» форматында. has_kaspi=false болса null.",
                      "x-description-en": "Client name from Kaspi in the format \"FirstName L.\" null if has_kaspi=false.",
                      "example": "Иван И.",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — API-ключ отсутствует или невалиден.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "Invalid API key",
                    "message": "The provided API key is invalid or inactive"
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Invalid API key"
                    },
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "The provided API key is invalid or inactive"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validation failed — phone пустой, отсутствует или не нормализуется к 11 цифрам.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "Validation failed",
                    "field": "phone",
                    "message": "Phone must be normalizable to 8XXXXXXXXXX (11 digits)."
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Validation failed"
                    },
                    "field": {
                      "type": "string",
                      "example": "phone"
                    },
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Phone must be normalizable to 8XXXXXXXXXX (11 digits)."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests — превышен лимит этого эндпоинта (POST /clients/check): 60 запросов/мин и 10 000 запросов/сутки на API-ключ. Дополнительно действует общий лимит Public API 200 запросов/мин на API-ключ. Смотрите Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "message": "Too Many Requests"
                  },
                  "properties": {
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Too Many Requests"
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Клиенты"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "phone": {
                    "type": "string",
                    "description": "Телефон клиента. Принимает форматы 77XXXXXXXXX, 87XXXXXXXXX, +77XXXXXXXXX, с пробелами/дефисами. После нормализации должен дать 11 цифр.",
                    "x-description-kk": "Клиенттің телефоны. 77XXXXXXXXX, 87XXXXXXXXX, +77XXXXXXXXX форматтарын, бос орындар/дефистермен қабылдайды. Нормалаудан кейін 11 цифр болуы керек.",
                    "x-description-en": "Client's phone. Accepts formats 77XXXXXXXXX, 87XXXXXXXXX, +77XXXXXXXXX, with spaces/hyphens. Must normalize to 11 digits.",
                    "example": "77001234567"
                  }
                },
                "required": [
                  "phone"
                ]
              }
            }
          }
        }
      }
    },
    "/invoices/status/check": {
      "post": {
        "summary": "Проверить статусы счетов",
        "operationId": "",
        "description": "Диспатчит задачи проверки статусов для указанных счетов через Kaspi API.",
        "parameters": [
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "invoices": [
                      {
                        "id": 1,
                        "status": "paid",
                        "kaspi_invoice_id": "ABC123",
                        "amount": "5000.00",
                        "error_message": null,
                        "updated_at": "2026-02-26T10:30:00+06:00"
                      }
                    ]
                  },
                  "properties": {
                    "invoices": {
                      "description": "Список счетов с актуальными статусами.",
                      "x-description-kk": "Өзекті мәртебелері бар шоттар тізімі.",
                      "x-description-en": "List of invoices with up-to-date statuses.",
                      "type": "array",
                      "example": [
                        {
                          "id": 1,
                          "status": "paid",
                          "kaspi_invoice_id": "ABC123",
                          "amount": "5000.00",
                          "error_message": null,
                          "updated_at": "2026-02-26T10:30:00+06:00"
                        }
                      ],
                      "items": {
                        "description": "Позиции (товары) объекта.",
                        "x-description-kk": "Нысан позициялары (тауарлар).",
                        "x-description-en": "Line items (products) of the object.",
                        "type": "object",
                        "properties": {
                          "id": {
                            "description": "ID записи.",
                            "x-description-kk": "Жазбаның ID-і.",
                            "x-description-en": "Record ID.",
                            "type": "integer",
                            "example": 1
                          },
                          "status": {
                            "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                            "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                            "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                            "type": "string",
                            "example": "paid"
                          },
                          "kaspi_invoice_id": {
                            "description": "ID счёта в системе Kaspi.",
                            "x-description-kk": "Kaspi жүйесіндегі шот ID-і.",
                            "x-description-en": "Invoice ID in the Kaspi system.",
                            "type": "string",
                            "example": "ABC123"
                          },
                          "amount": {
                            "description": "Сумма в тенге.",
                            "x-description-kk": "Теңгемен сома.",
                            "x-description-en": "Amount in tenge.",
                            "type": "string",
                            "example": "5000.00"
                          },
                          "error_message": {
                            "description": "Текст ошибки (null если ошибок нет).",
                            "x-description-kk": "Қате мәтіні (қате болмаса null).",
                            "x-description-en": "Error text (null if there is no error).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "updated_at": {
                            "description": "Дата и время последнего обновления.",
                            "x-description-kk": "Соңғы жаңарту күні мен уақыты.",
                            "x-description-en": "Date and time of the last update.",
                            "type": "string",
                            "example": "2026-02-26T10:30:00+06:00"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Ошибка валидации",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "message": "Validation failed",
                    "errors": {
                      "invoice_ids": [
                        "The invoice ids field is required."
                      ]
                    }
                  },
                  "properties": {
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Validation failed"
                    },
                    "errors": {
                      "type": "object",
                      "properties": {
                        "invoice_ids": {
                          "type": "array",
                          "example": [
                            "The invoice ids field is required."
                          ],
                          "items": {
                            "description": "Позиции (товары) объекта.",
                            "x-description-kk": "Нысан позициялары (тауарлар).",
                            "x-description-en": "Line items (products) of the object.",
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Счета"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "invoice_ids": {
                    "type": "array",
                    "description": "Массив ID счетов.",
                    "x-description-kk": "Шоттар ID-лерінің массиві.",
                    "x-description-en": "Array of invoice IDs.",
                    "example": [
                      1,
                      2,
                      3
                    ],
                    "items": {
                      "type": "integer"
                    }
                  }
                },
                "required": [
                  "invoice_ids"
                ]
              }
            }
          }
        }
      }
    },
    "/subscriptions": {
      "get": {
        "summary": "Список подписок",
        "operationId": "",
        "description": "Возвращает пагинированный список подписок с возможностью фильтрации.",
        "parameters": [
          {
            "in": "query",
            "name": "status",
            "description": "Фильтр по статусу (active, paused, cancelled, expired).",
            "x-description-kk": "Мәртебе бойынша сүзу (active, paused, cancelled, expired).",
            "x-description-en": "Filter by status (active, paused, cancelled, expired).",
            "example": "active",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Фильтр по статусу (active, paused, cancelled, expired).",
              "x-description-kk": "Мәртебе бойынша сүзу (active, paused, cancelled, expired).",
              "x-description-en": "Filter by status (active, paused, cancelled, expired).",
              "example": "active"
            }
          },
          {
            "in": "query",
            "name": "external_subscriber_id",
            "description": "Фильтр по внешнему ID подписчика.",
            "x-description-kk": "Жазылушының сыртқы ID-і бойынша сүзу.",
            "x-description-en": "Filter by external subscriber ID.",
            "example": "client-42",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Фильтр по внешнему ID подписчика.",
              "x-description-kk": "Жазылушының сыртқы ID-і бойынша сүзу.",
              "x-description-en": "Filter by external subscriber ID.",
              "example": "client-42"
            }
          },
          {
            "in": "query",
            "name": "phone_number",
            "description": "Фильтр по номеру телефона (8XXXXXXXXXX).",
            "x-description-kk": "Телефон нөмірі бойынша сүзу (8XXXXXXXXXX).",
            "x-description-en": "Filter by phone number (8XXXXXXXXXX).",
            "example": "87001234567",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Фильтр по номеру телефона (8XXXXXXXXXX).",
              "x-description-kk": "Телефон нөмірі бойынша сүзу (8XXXXXXXXXX).",
              "x-description-en": "Filter by phone number (8XXXXXXXXXX).",
              "example": "87001234567"
            }
          },
          {
            "in": "query",
            "name": "per_page",
            "description": "Кол-во на страницу (по умолчанию 20).",
            "x-description-kk": "Бір беттегі саны (әдепкіде 20).",
            "x-description-en": "Items per page (default 20).",
            "example": 20,
            "required": false,
            "schema": {
              "type": "integer",
              "description": "Кол-во на страницу (по умолчанию 20).",
              "x-description-kk": "Бір беттегі саны (әдепкіде 20).",
              "x-description-en": "Items per page (default 20).",
              "example": 20
            }
          },
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "current_page": 1,
                    "data": [
                      {
                        "id": 1,
                        "subscriber_name": "Иван Петров",
                        "phone_number": "87001234567",
                        "external_subscriber_id": "client-42",
                        "amount": "5000.00",
                        "cart_items": null,
                        "description": "Ежемесячная подписка",
                        "billing_period": "monthly",
                        "billing_period_label": "Ежемесячно",
                        "billing_day": 15,
                        "billing_day_label": "15 числа",
                        "status": "active",
                        "status_label": "Активна",
                        "status_color": "green",
                        "started_at": "2026-01-15T00:00:00+00:00",
                        "next_billing_at": "2026-03-15T00:00:00+00:00",
                        "next_billing_in_days": 17,
                        "next_billing_label": "через 17 дней",
                        "paused_at": null,
                        "cancelled_at": null,
                        "failed_attempts": 0,
                        "max_retry_attempts": 3,
                        "retry_interval_hours": 24,
                        "grace_period_days": 3,
                        "in_grace_period": false,
                        "is_sandbox": false,
                        "metadata": null,
                        "created_at": "2026-01-10T12:00:00+00:00",
                        "updated_at": "2026-02-15T10:30:00+00:00"
                      }
                    ],
                    "total": 1
                  },
                  "properties": {
                    "current_page": {
                      "description": "Номер текущей страницы.",
                      "x-description-kk": "Ағымдағы беттің нөмірі.",
                      "x-description-en": "Current page number.",
                      "type": "integer",
                      "example": 1
                    },
                    "data": {
                      "description": "Массив записей результата.",
                      "x-description-kk": "Нәтиже жазбаларының массиві.",
                      "x-description-en": "Array of result records.",
                      "type": "array",
                      "example": [
                        {
                          "id": 1,
                          "subscriber_name": "Иван Петров",
                          "phone_number": "87001234567",
                          "external_subscriber_id": "client-42",
                          "amount": "5000.00",
                          "cart_items": null,
                          "description": "Ежемесячная подписка",
                          "billing_period": "monthly",
                          "billing_period_label": "Ежемесячно",
                          "billing_day": 15,
                          "billing_day_label": "15 числа",
                          "status": "active",
                          "status_label": "Активна",
                          "status_color": "green",
                          "started_at": "2026-01-15T00:00:00+00:00",
                          "next_billing_at": "2026-03-15T00:00:00+00:00",
                          "next_billing_in_days": 17,
                          "next_billing_label": "через 17 дней",
                          "paused_at": null,
                          "cancelled_at": null,
                          "failed_attempts": 0,
                          "max_retry_attempts": 3,
                          "retry_interval_hours": 24,
                          "grace_period_days": 3,
                          "in_grace_period": false,
                          "is_sandbox": false,
                          "metadata": null,
                          "created_at": "2026-01-10T12:00:00+00:00",
                          "updated_at": "2026-02-15T10:30:00+00:00"
                        }
                      ],
                      "items": {
                        "description": "Позиции (товары) объекта.",
                        "x-description-kk": "Нысан позициялары (тауарлар).",
                        "x-description-en": "Line items (products) of the object.",
                        "type": "object",
                        "properties": {
                          "id": {
                            "description": "ID записи.",
                            "x-description-kk": "Жазбаның ID-і.",
                            "x-description-en": "Record ID.",
                            "type": "integer",
                            "example": 1
                          },
                          "subscriber_name": {
                            "description": "Имя подписчика.",
                            "x-description-kk": "Жазылушының аты.",
                            "x-description-en": "Subscriber name.",
                            "type": "string",
                            "example": "Иван Петров"
                          },
                          "phone_number": {
                            "description": "Номер телефона подписчика.",
                            "x-description-kk": "Жазылушының телефон нөмірі.",
                            "x-description-en": "Subscriber phone number.",
                            "type": "string",
                            "example": "87001234567"
                          },
                          "external_subscriber_id": {
                            "description": "Внешний ID подписчика.",
                            "x-description-kk": "Жазылушының сыртқы ID-і.",
                            "x-description-en": "External subscriber ID.",
                            "type": "string",
                            "example": "client-42"
                          },
                          "amount": {
                            "description": "Сумма в тенге.",
                            "x-description-kk": "Теңгемен сома.",
                            "x-description-en": "Amount in tenge.",
                            "type": "string",
                            "example": "5000.00"
                          },
                          "cart_items": {
                            "description": "Корзина товаров подписки (null без каталога).",
                            "x-description-kk": "Жазылым тауарларының себеті (каталогсыз null).",
                            "x-description-en": "Subscription cart items (null without a catalog).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "description": {
                            "description": "Описание.",
                            "x-description-kk": "Сипаттама.",
                            "x-description-en": "Description.",
                            "type": "string",
                            "example": "Ежемесячная подписка"
                          },
                          "billing_period": {
                            "description": "Период биллинга: daily, weekly, biweekly, monthly, quarterly, yearly.",
                            "x-description-kk": "Биллинг кезеңі: daily, weekly, biweekly, monthly, quarterly, yearly.",
                            "x-description-en": "Billing period: daily, weekly, biweekly, monthly, quarterly, yearly.",
                            "type": "string",
                            "example": "monthly"
                          },
                          "billing_period_label": {
                            "description": "Локализованное название периода биллинга.",
                            "x-description-kk": "Биллинг кезеңінің локализацияланған атауы.",
                            "x-description-en": "Localized billing period label.",
                            "type": "string",
                            "example": "Ежемесячно"
                          },
                          "billing_day": {
                            "description": "День биллинга (1-28).",
                            "x-description-kk": "Биллинг күні (1-28).",
                            "x-description-en": "Billing day (1-28).",
                            "type": "integer",
                            "example": 15
                          },
                          "billing_day_label": {
                            "description": "Локализованное обозначение дня биллинга.",
                            "x-description-kk": "Биллинг күнінің локализацияланған белгісі.",
                            "x-description-en": "Localized billing day label.",
                            "type": "string",
                            "example": "15 числа"
                          },
                          "status": {
                            "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                            "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                            "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                            "type": "string",
                            "example": "active"
                          },
                          "status_label": {
                            "description": "Локализованное название статуса.",
                            "x-description-kk": "Мәртебенің локализацияланған атауы.",
                            "x-description-en": "Localized status label.",
                            "type": "string",
                            "example": "Активна"
                          },
                          "status_color": {
                            "description": "Цвет статуса для UI.",
                            "x-description-kk": "UI үшін мәртебе түсі.",
                            "x-description-en": "Status color for the UI.",
                            "type": "string",
                            "example": "green"
                          },
                          "started_at": {
                            "description": "Дата начала подписки.",
                            "x-description-kk": "Жазылымның басталу күні.",
                            "x-description-en": "Subscription start date.",
                            "type": "string",
                            "example": "2026-01-15T00:00:00+00:00"
                          },
                          "next_billing_at": {
                            "description": "Дата следующего списания (null если нет).",
                            "x-description-kk": "Келесі есептен шығару күні (болмаса null).",
                            "x-description-en": "Next billing date (null if none).",
                            "type": "string",
                            "example": "2026-03-15T00:00:00+00:00"
                          },
                          "next_billing_in_days": {
                            "description": "Количество дней до следующего списания.",
                            "x-description-kk": "Келесі есептен шығаруға дейінгі күн саны.",
                            "x-description-en": "Number of days until the next billing.",
                            "type": "integer",
                            "example": 17
                          },
                          "next_billing_label": {
                            "description": "Текстовое обозначение следующего списания.",
                            "x-description-kk": "Келесі есептен шығарудың мәтіндік белгісі.",
                            "x-description-en": "Text label for the next billing.",
                            "type": "string",
                            "example": "через 17 дней"
                          },
                          "paused_at": {
                            "description": "Дата приостановки (null если активна).",
                            "x-description-kk": "Тоқтату күні (белсенді болса null).",
                            "x-description-en": "Date the subscription was paused (null if active).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "cancelled_at": {
                            "description": "Дата отмены (null если не отменена).",
                            "x-description-kk": "Бас тарту күні (тоқтатылмаса null).",
                            "x-description-en": "Date the subscription was cancelled (null if not cancelled).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "failed_attempts": {
                            "description": "Количество неудачных попыток списания.",
                            "x-description-kk": "Сәтсіз есептен шығару әрекеттерінің саны.",
                            "x-description-en": "Number of failed billing attempts.",
                            "type": "integer",
                            "example": 0
                          },
                          "max_retry_attempts": {
                            "description": "Макс. число повторных попыток.",
                            "x-description-kk": "Қайталау әрекеттерінің макс. саны.",
                            "x-description-en": "Max number of retry attempts.",
                            "type": "integer",
                            "example": 3
                          },
                          "retry_interval_hours": {
                            "description": "Интервал между повторами в часах.",
                            "x-description-kk": "Қайталаулар арасындағы интервал, сағатпен.",
                            "x-description-en": "Interval between retries in hours.",
                            "type": "integer",
                            "example": 24
                          },
                          "grace_period_days": {
                            "description": "Льготный период в днях.",
                            "x-description-kk": "Жеңілдік кезеңі, күнмен.",
                            "x-description-en": "Grace period in days.",
                            "type": "integer",
                            "example": 3
                          },
                          "in_grace_period": {
                            "description": "Признак нахождения в льготном периоде.",
                            "x-description-kk": "Жеңілдік кезеңінде болу белгісі.",
                            "x-description-en": "Whether the subscription is in the grace period.",
                            "type": "boolean",
                            "example": false
                          },
                          "is_sandbox": {
                            "description": "Признак тестового (sandbox) объекта.",
                            "x-description-kk": "Тестілік (sandbox) нысан белгісі.",
                            "x-description-en": "Whether the object is a sandbox (test) object.",
                            "type": "boolean",
                            "example": false
                          },
                          "metadata": {
                            "description": "Произвольные метаданные.",
                            "x-description-kk": "Еркін метадеректер.",
                            "x-description-en": "Arbitrary metadata.",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "created_at": {
                            "description": "Дата и время создания.",
                            "x-description-kk": "Жасалған күні мен уақыты.",
                            "x-description-en": "Date and time of creation.",
                            "type": "string",
                            "example": "2026-01-10T12:00:00+00:00"
                          },
                          "updated_at": {
                            "description": "Дата и время последнего обновления.",
                            "x-description-kk": "Соңғы жаңарту күні мен уақыты.",
                            "x-description-en": "Date and time of the last update.",
                            "type": "string",
                            "example": "2026-02-15T10:30:00+00:00"
                          }
                        }
                      }
                    },
                    "total": {
                      "description": "Общее количество записей.",
                      "x-description-kk": "Жазбалардың жалпы саны.",
                      "x-description-en": "Total number of records.",
                      "type": "integer",
                      "example": 1
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Подписки"
        ]
      },
      "post": {
        "summary": "Создать подписку",
        "operationId": "",
        "description": "Создаёт новую рекуррентную подписку. Первый счёт выставляется автоматически.",
        "parameters": [
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "message": "Subscription created",
                    "subscription": {
                      "id": 1,
                      "subscriber_name": "Иван Петров",
                      "phone_number": "87001234567",
                      "external_subscriber_id": "client-42",
                      "amount": "5000.00",
                      "cart_items": null,
                      "description": "Ежемесячная подписка",
                      "billing_period": "monthly",
                      "billing_period_label": "Ежемесячно",
                      "billing_day": 15,
                      "billing_day_label": "15 числа",
                      "status": "active",
                      "status_label": "Активна",
                      "status_color": "green",
                      "started_at": "2026-03-01T00:00:00+00:00",
                      "next_billing_at": "2026-03-01T00:00:00+00:00",
                      "next_billing_in_days": 3,
                      "next_billing_label": "через 3 дня",
                      "paused_at": null,
                      "cancelled_at": null,
                      "failed_attempts": 0,
                      "max_retry_attempts": 3,
                      "retry_interval_hours": 24,
                      "grace_period_days": 3,
                      "in_grace_period": false,
                      "is_sandbox": false,
                      "metadata": {
                        "source": "website"
                      },
                      "created_at": "2026-02-26T12:00:00+00:00",
                      "updated_at": "2026-02-26T12:00:00+00:00"
                    }
                  },
                  "properties": {
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Subscription created"
                    },
                    "subscription": {
                      "description": "Объект подписки.",
                      "x-description-kk": "Жазылым нысаны.",
                      "x-description-en": "Subscription object.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "description": "ID записи.",
                          "x-description-kk": "Жазбаның ID-і.",
                          "x-description-en": "Record ID.",
                          "type": "integer",
                          "example": 1
                        },
                        "subscriber_name": {
                          "description": "Имя подписчика.",
                          "x-description-kk": "Жазылушының аты.",
                          "x-description-en": "Subscriber name.",
                          "type": "string",
                          "example": "Иван Петров"
                        },
                        "phone_number": {
                          "description": "Номер телефона подписчика.",
                          "x-description-kk": "Жазылушының телефон нөмірі.",
                          "x-description-en": "Subscriber phone number.",
                          "type": "string",
                          "example": "87001234567"
                        },
                        "external_subscriber_id": {
                          "description": "Внешний ID подписчика.",
                          "x-description-kk": "Жазылушының сыртқы ID-і.",
                          "x-description-en": "External subscriber ID.",
                          "type": "string",
                          "example": "client-42"
                        },
                        "amount": {
                          "description": "Сумма в тенге.",
                          "x-description-kk": "Теңгемен сома.",
                          "x-description-en": "Amount in tenge.",
                          "type": "string",
                          "example": "5000.00"
                        },
                        "cart_items": {
                          "description": "Корзина товаров подписки (null без каталога).",
                          "x-description-kk": "Жазылым тауарларының себеті (каталогсыз null).",
                          "x-description-en": "Subscription cart items (null without a catalog).",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "description": {
                          "description": "Описание.",
                          "x-description-kk": "Сипаттама.",
                          "x-description-en": "Description.",
                          "type": "string",
                          "example": "Ежемесячная подписка"
                        },
                        "billing_period": {
                          "description": "Период биллинга: daily, weekly, biweekly, monthly, quarterly, yearly.",
                          "x-description-kk": "Биллинг кезеңі: daily, weekly, biweekly, monthly, quarterly, yearly.",
                          "x-description-en": "Billing period: daily, weekly, biweekly, monthly, quarterly, yearly.",
                          "type": "string",
                          "example": "monthly"
                        },
                        "billing_period_label": {
                          "description": "Локализованное название периода биллинга.",
                          "x-description-kk": "Биллинг кезеңінің локализацияланған атауы.",
                          "x-description-en": "Localized billing period label.",
                          "type": "string",
                          "example": "Ежемесячно"
                        },
                        "billing_day": {
                          "description": "День биллинга (1-28).",
                          "x-description-kk": "Биллинг күні (1-28).",
                          "x-description-en": "Billing day (1-28).",
                          "type": "integer",
                          "example": 15
                        },
                        "billing_day_label": {
                          "description": "Локализованное обозначение дня биллинга.",
                          "x-description-kk": "Биллинг күнінің локализацияланған белгісі.",
                          "x-description-en": "Localized billing day label.",
                          "type": "string",
                          "example": "15 числа"
                        },
                        "status": {
                          "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                          "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                          "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                          "type": "string",
                          "example": "active"
                        },
                        "status_label": {
                          "description": "Локализованное название статуса.",
                          "x-description-kk": "Мәртебенің локализацияланған атауы.",
                          "x-description-en": "Localized status label.",
                          "type": "string",
                          "example": "Активна"
                        },
                        "status_color": {
                          "description": "Цвет статуса для UI.",
                          "x-description-kk": "UI үшін мәртебе түсі.",
                          "x-description-en": "Status color for the UI.",
                          "type": "string",
                          "example": "green"
                        },
                        "started_at": {
                          "description": "Дата начала подписки.",
                          "x-description-kk": "Жазылымның басталу күні.",
                          "x-description-en": "Subscription start date.",
                          "type": "string",
                          "example": "2026-03-01T00:00:00+00:00"
                        },
                        "next_billing_at": {
                          "description": "Дата следующего списания (null если нет).",
                          "x-description-kk": "Келесі есептен шығару күні (болмаса null).",
                          "x-description-en": "Next billing date (null if none).",
                          "type": "string",
                          "example": "2026-03-01T00:00:00+00:00"
                        },
                        "next_billing_in_days": {
                          "description": "Количество дней до следующего списания.",
                          "x-description-kk": "Келесі есептен шығаруға дейінгі күн саны.",
                          "x-description-en": "Number of days until the next billing.",
                          "type": "integer",
                          "example": 3
                        },
                        "next_billing_label": {
                          "description": "Текстовое обозначение следующего списания.",
                          "x-description-kk": "Келесі есептен шығарудың мәтіндік белгісі.",
                          "x-description-en": "Text label for the next billing.",
                          "type": "string",
                          "example": "через 3 дня"
                        },
                        "paused_at": {
                          "description": "Дата приостановки (null если активна).",
                          "x-description-kk": "Тоқтату күні (белсенді болса null).",
                          "x-description-en": "Date the subscription was paused (null if active).",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "cancelled_at": {
                          "description": "Дата отмены (null если не отменена).",
                          "x-description-kk": "Бас тарту күні (тоқтатылмаса null).",
                          "x-description-en": "Date the subscription was cancelled (null if not cancelled).",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "failed_attempts": {
                          "description": "Количество неудачных попыток списания.",
                          "x-description-kk": "Сәтсіз есептен шығару әрекеттерінің саны.",
                          "x-description-en": "Number of failed billing attempts.",
                          "type": "integer",
                          "example": 0
                        },
                        "max_retry_attempts": {
                          "description": "Макс. число повторных попыток.",
                          "x-description-kk": "Қайталау әрекеттерінің макс. саны.",
                          "x-description-en": "Max number of retry attempts.",
                          "type": "integer",
                          "example": 3
                        },
                        "retry_interval_hours": {
                          "description": "Интервал между повторами в часах.",
                          "x-description-kk": "Қайталаулар арасындағы интервал, сағатпен.",
                          "x-description-en": "Interval between retries in hours.",
                          "type": "integer",
                          "example": 24
                        },
                        "grace_period_days": {
                          "description": "Льготный период в днях.",
                          "x-description-kk": "Жеңілдік кезеңі, күнмен.",
                          "x-description-en": "Grace period in days.",
                          "type": "integer",
                          "example": 3
                        },
                        "in_grace_period": {
                          "description": "Признак нахождения в льготном периоде.",
                          "x-description-kk": "Жеңілдік кезеңінде болу белгісі.",
                          "x-description-en": "Whether the subscription is in the grace period.",
                          "type": "boolean",
                          "example": false
                        },
                        "is_sandbox": {
                          "description": "Признак тестового (sandbox) объекта.",
                          "x-description-kk": "Тестілік (sandbox) нысан белгісі.",
                          "x-description-en": "Whether the object is a sandbox (test) object.",
                          "type": "boolean",
                          "example": false
                        },
                        "metadata": {
                          "description": "Произвольные метаданные.",
                          "x-description-kk": "Еркін метадеректер.",
                          "x-description-en": "Arbitrary metadata.",
                          "type": "object",
                          "properties": {
                            "source": {
                              "description": "Пример ключа метаданных (источник).",
                              "x-description-kk": "Метадерек кілтінің мысалы (көзі).",
                              "x-description-en": "Example metadata key (source).",
                              "type": "string",
                              "example": "website"
                            }
                          }
                        },
                        "created_at": {
                          "description": "Дата и время создания.",
                          "x-description-kk": "Жасалған күні мен уақыты.",
                          "x-description-en": "Date and time of creation.",
                          "type": "string",
                          "example": "2026-02-26T12:00:00+00:00"
                        },
                        "updated_at": {
                          "description": "Дата и время последнего обновления.",
                          "x-description-kk": "Соңғы жаңарту күні мен уақыты.",
                          "x-description-en": "Date and time of the last update.",
                          "type": "string",
                          "example": "2026-02-26T12:00:00+00:00"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Sandbox без организации",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "Subscriptions require a verified organization",
                    "message": "Subscriptions are linked to real clients and organizations. Add and verify an organization to create subscriptions. You can view mock subscriptions via GET /api/v1/subscriptions.",
                    "is_sandbox": true
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Subscriptions require a verified organization"
                    },
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Subscriptions are linked to real clients and organizations. Add and verify an organization to create subscriptions. You can view mock subscriptions via GET /api/v1/subscriptions."
                    },
                    "is_sandbox": {
                      "description": "Признак тестового (sandbox) объекта.",
                      "x-description-kk": "Тестілік (sandbox) нысан белгісі.",
                      "x-description-en": "Whether the object is a sandbox (test) object.",
                      "type": "boolean",
                      "example": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Организация не верифицирована",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "Organization not verified"
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Organization not verified"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Ошибка валидации",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "message": "Validation failed",
                    "errors": {
                      "phone_number": [
                        "Номер телефона должен быть в формате 8XXXXXXXXXX (11 цифр)"
                      ]
                    }
                  },
                  "properties": {
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Validation failed"
                    },
                    "errors": {
                      "type": "object",
                      "properties": {
                        "phone_number": {
                          "description": "Номер телефона подписчика.",
                          "x-description-kk": "Жазылушының телефон нөмірі.",
                          "x-description-en": "Subscriber phone number.",
                          "type": "array",
                          "example": [
                            "Номер телефона должен быть в формате 8XXXXXXXXXX (11 цифр)"
                          ],
                          "items": {
                            "description": "Позиции (товары) объекта.",
                            "x-description-kk": "Нысан позициялары (тауарлар).",
                            "x-description-en": "Line items (products) of the object.",
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Подписки"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "phone_number": {
                    "type": "string",
                    "description": "Номер телефона подписчика в формате 8XXXXXXXXXX.",
                    "x-description-kk": "Жазылушының телефон нөмірі 8XXXXXXXXXX форматында.",
                    "x-description-en": "Subscriber phone number in 8XXXXXXXXXX format.",
                    "example": "87001234567"
                  },
                  "billing_period": {
                    "type": "string",
                    "description": "Период биллинга: daily, weekly, biweekly, monthly, quarterly, yearly.",
                    "x-description-kk": "Биллинг кезеңі: daily, weekly, biweekly, monthly, quarterly, yearly.",
                    "x-description-en": "Billing period: daily, weekly, biweekly, monthly, quarterly, yearly.",
                    "example": "monthly"
                  },
                  "billing_day": {
                    "type": "integer",
                    "description": "День биллинга (1-28).",
                    "x-description-kk": "Биллинг күні (1-28).",
                    "x-description-en": "Billing day (1-28).",
                    "example": 15,
                    "nullable": true
                  },
                  "description": {
                    "type": "string",
                    "description": "Описание подписки.",
                    "x-description-kk": "Жазылым сипаттамасы.",
                    "x-description-en": "Subscription description.",
                    "example": "Ежемесячная подписка",
                    "nullable": true
                  },
                  "subscriber_name": {
                    "type": "string",
                    "description": "Имя подписчика.",
                    "x-description-kk": "Жазылушының аты.",
                    "x-description-en": "Subscriber name.",
                    "example": "Иван Петров",
                    "nullable": true
                  },
                  "external_subscriber_id": {
                    "type": "string",
                    "description": "Внешний ID подписчика в вашей системе.",
                    "x-description-kk": "Сіздің жүйеңіздегі жазылушының сыртқы ID-і.",
                    "x-description-en": "External subscriber ID in your system.",
                    "example": "client-42",
                    "nullable": true
                  },
                  "started_at": {
                    "type": "string",
                    "description": "Дата начала (Y-m-d). По умолчанию — сегодня.",
                    "x-description-kk": "Басталу күні (Y-m-d). Әдепкіде — бүгін.",
                    "x-description-en": "Start date (Y-m-d). Defaults to today.",
                    "example": "2026-03-01",
                    "nullable": true
                  },
                  "max_retry_attempts": {
                    "type": "integer",
                    "description": "Макс. кол-во повторных попыток при неудаче (1-10).",
                    "x-description-kk": "Сәтсіздік кезіндегі қайталау әрекеттерінің макс. саны (1-10).",
                    "x-description-en": "Max number of retry attempts on failure (1-10).",
                    "example": 3,
                    "nullable": true
                  },
                  "retry_interval_hours": {
                    "type": "integer",
                    "description": "Интервал между повторами в часах (1-168).",
                    "x-description-kk": "Қайталаулар арасындағы интервал, сағатпен (1-168).",
                    "x-description-en": "Interval between retries in hours (1-168).",
                    "example": 24,
                    "nullable": true
                  },
                  "grace_period_days": {
                    "type": "integer",
                    "description": "Льготный период в днях (1-30).",
                    "x-description-kk": "Жеңілдік кезеңі, күнмен (1-30).",
                    "x-description-en": "Grace period in days (1-30).",
                    "example": 3,
                    "nullable": true
                  },
                  "metadata": {
                    "type": "object",
                    "description": "Произвольные метаданные.",
                    "x-description-kk": "Еркін метадеректер.",
                    "x-description-en": "Arbitrary metadata.",
                    "example": {
                      "source": "website"
                    },
                    "properties": {},
                    "nullable": true
                  },
                  "bill_immediately": {
                    "type": "boolean",
                    "description": "Выставить первый счёт сразу при создании.",
                    "x-description-kk": "Жасау кезінде бірінші шотты бірден шығару.",
                    "x-description-en": "Issue the first invoice immediately on creation.",
                    "example": false,
                    "nullable": true
                  },
                  "amount": {
                    "type": "number",
                    "description": "Сумма списания в тенге (100-1000000). Обязательна для организаций без каталога.",
                    "x-description-kk": "Теңгемен есептен шығару сомасы (100-1000000). Каталогы жоқ ұйымдар үшін міндетті.",
                    "x-description-en": "Charge amount in tenge (100-1000000). Required for organizations without a catalog.",
                    "example": 5000
                  },
                  "cart_items": {
                    "type": "array",
                    "description": "Корзина товаров (только для каталожных организаций).",
                    "x-description-kk": "Тауарлар себеті (тек каталогты ұйымдар үшін).",
                    "x-description-en": "Cart items (only for catalog organizations).",
                    "example": [
                      []
                    ],
                    "items": {
                      "type": "object",
                      "properties": {
                        "catalog_item_id": {
                          "type": "integer",
                          "description": "ID товара из каталога.",
                          "x-description-kk": "Каталогтағы тауардың ID-і.",
                          "x-description-en": "Catalog item ID.",
                          "example": 1
                        },
                        "count": {
                          "type": "integer",
                          "description": "Количество.",
                          "x-description-kk": "Саны.",
                          "x-description-en": "Quantity.",
                          "example": 2
                        },
                        "price": {
                          "type": "number",
                          "nullable": true,
                          "description": "Переопределённая цена за единицу. Если не указана — используется selling_price из каталога.",
                          "x-description-kk": "Бірлік үшін қайта анықталған баға. Көрсетілмесе — каталогтан selling_price қолданылады.",
                          "x-description-en": "Overridden unit price. If omitted, selling_price from the catalog is used.",
                          "example": 4500
                        }
                      },
                      "required": [
                        "catalog_item_id",
                        "count"
                      ]
                    }
                  }
                },
                "required": [
                  "phone_number",
                  "billing_period"
                ]
              }
            }
          }
        }
      }
    },
    "/subscriptions/{id}": {
      "get": {
        "summary": "Просмотр подписки",
        "operationId": "",
        "description": "Возвращает детальную информацию о подписке, включая статистику и последний платёж.",
        "parameters": [
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "subscription": {
                      "id": 1,
                      "subscriber_name": "Иван Петров",
                      "phone_number": "87001234567",
                      "external_subscriber_id": "client-42",
                      "amount": "5000.00",
                      "cart_items": null,
                      "description": "Ежемесячная подписка",
                      "billing_period": "monthly",
                      "billing_period_label": "Ежемесячно",
                      "billing_day": 15,
                      "billing_day_label": "15 числа",
                      "status": "active",
                      "status_label": "Активна",
                      "status_color": "green",
                      "started_at": "2026-01-15T00:00:00+00:00",
                      "next_billing_at": "2026-03-15T00:00:00+00:00",
                      "next_billing_in_days": 17,
                      "next_billing_label": "через 17 дней",
                      "paused_at": null,
                      "cancelled_at": null,
                      "failed_attempts": 0,
                      "max_retry_attempts": 3,
                      "retry_interval_hours": 24,
                      "grace_period_days": 3,
                      "in_grace_period": false,
                      "is_sandbox": false,
                      "metadata": null,
                      "created_at": "2026-01-10T12:00:00+00:00",
                      "updated_at": "2026-02-15T10:30:00+00:00",
                      "last_payment": {
                        "amount": "5000.00",
                        "paid_at": "2026-02-15T10:30:00+00:00",
                        "status": "paid"
                      },
                      "stats": {
                        "total_payments": 3,
                        "successful_payments": 3,
                        "failed_payments": 0,
                        "total_amount": "15000.00"
                      }
                    }
                  },
                  "properties": {
                    "subscription": {
                      "description": "Объект подписки.",
                      "x-description-kk": "Жазылым нысаны.",
                      "x-description-en": "Subscription object.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "description": "ID записи.",
                          "x-description-kk": "Жазбаның ID-і.",
                          "x-description-en": "Record ID.",
                          "type": "integer",
                          "example": 1
                        },
                        "subscriber_name": {
                          "description": "Имя подписчика.",
                          "x-description-kk": "Жазылушының аты.",
                          "x-description-en": "Subscriber name.",
                          "type": "string",
                          "example": "Иван Петров"
                        },
                        "phone_number": {
                          "description": "Номер телефона подписчика.",
                          "x-description-kk": "Жазылушының телефон нөмірі.",
                          "x-description-en": "Subscriber phone number.",
                          "type": "string",
                          "example": "87001234567"
                        },
                        "external_subscriber_id": {
                          "description": "Внешний ID подписчика.",
                          "x-description-kk": "Жазылушының сыртқы ID-і.",
                          "x-description-en": "External subscriber ID.",
                          "type": "string",
                          "example": "client-42"
                        },
                        "amount": {
                          "description": "Сумма в тенге.",
                          "x-description-kk": "Теңгемен сома.",
                          "x-description-en": "Amount in tenge.",
                          "type": "string",
                          "example": "5000.00"
                        },
                        "cart_items": {
                          "description": "Корзина товаров подписки (null без каталога).",
                          "x-description-kk": "Жазылым тауарларының себеті (каталогсыз null).",
                          "x-description-en": "Subscription cart items (null without a catalog).",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "description": {
                          "description": "Описание.",
                          "x-description-kk": "Сипаттама.",
                          "x-description-en": "Description.",
                          "type": "string",
                          "example": "Ежемесячная подписка"
                        },
                        "billing_period": {
                          "description": "Период биллинга: daily, weekly, biweekly, monthly, quarterly, yearly.",
                          "x-description-kk": "Биллинг кезеңі: daily, weekly, biweekly, monthly, quarterly, yearly.",
                          "x-description-en": "Billing period: daily, weekly, biweekly, monthly, quarterly, yearly.",
                          "type": "string",
                          "example": "monthly"
                        },
                        "billing_period_label": {
                          "description": "Локализованное название периода биллинга.",
                          "x-description-kk": "Биллинг кезеңінің локализацияланған атауы.",
                          "x-description-en": "Localized billing period label.",
                          "type": "string",
                          "example": "Ежемесячно"
                        },
                        "billing_day": {
                          "description": "День биллинга (1-28).",
                          "x-description-kk": "Биллинг күні (1-28).",
                          "x-description-en": "Billing day (1-28).",
                          "type": "integer",
                          "example": 15
                        },
                        "billing_day_label": {
                          "description": "Локализованное обозначение дня биллинга.",
                          "x-description-kk": "Биллинг күнінің локализацияланған белгісі.",
                          "x-description-en": "Localized billing day label.",
                          "type": "string",
                          "example": "15 числа"
                        },
                        "status": {
                          "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                          "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                          "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                          "type": "string",
                          "example": "active"
                        },
                        "status_label": {
                          "description": "Локализованное название статуса.",
                          "x-description-kk": "Мәртебенің локализацияланған атауы.",
                          "x-description-en": "Localized status label.",
                          "type": "string",
                          "example": "Активна"
                        },
                        "status_color": {
                          "description": "Цвет статуса для UI.",
                          "x-description-kk": "UI үшін мәртебе түсі.",
                          "x-description-en": "Status color for the UI.",
                          "type": "string",
                          "example": "green"
                        },
                        "started_at": {
                          "description": "Дата начала подписки.",
                          "x-description-kk": "Жазылымның басталу күні.",
                          "x-description-en": "Subscription start date.",
                          "type": "string",
                          "example": "2026-01-15T00:00:00+00:00"
                        },
                        "next_billing_at": {
                          "description": "Дата следующего списания (null если нет).",
                          "x-description-kk": "Келесі есептен шығару күні (болмаса null).",
                          "x-description-en": "Next billing date (null if none).",
                          "type": "string",
                          "example": "2026-03-15T00:00:00+00:00"
                        },
                        "next_billing_in_days": {
                          "description": "Количество дней до следующего списания.",
                          "x-description-kk": "Келесі есептен шығаруға дейінгі күн саны.",
                          "x-description-en": "Number of days until the next billing.",
                          "type": "integer",
                          "example": 17
                        },
                        "next_billing_label": {
                          "description": "Текстовое обозначение следующего списания.",
                          "x-description-kk": "Келесі есептен шығарудың мәтіндік белгісі.",
                          "x-description-en": "Text label for the next billing.",
                          "type": "string",
                          "example": "через 17 дней"
                        },
                        "paused_at": {
                          "description": "Дата приостановки (null если активна).",
                          "x-description-kk": "Тоқтату күні (белсенді болса null).",
                          "x-description-en": "Date the subscription was paused (null if active).",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "cancelled_at": {
                          "description": "Дата отмены (null если не отменена).",
                          "x-description-kk": "Бас тарту күні (тоқтатылмаса null).",
                          "x-description-en": "Date the subscription was cancelled (null if not cancelled).",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "failed_attempts": {
                          "description": "Количество неудачных попыток списания.",
                          "x-description-kk": "Сәтсіз есептен шығару әрекеттерінің саны.",
                          "x-description-en": "Number of failed billing attempts.",
                          "type": "integer",
                          "example": 0
                        },
                        "max_retry_attempts": {
                          "description": "Макс. число повторных попыток.",
                          "x-description-kk": "Қайталау әрекеттерінің макс. саны.",
                          "x-description-en": "Max number of retry attempts.",
                          "type": "integer",
                          "example": 3
                        },
                        "retry_interval_hours": {
                          "description": "Интервал между повторами в часах.",
                          "x-description-kk": "Қайталаулар арасындағы интервал, сағатпен.",
                          "x-description-en": "Interval between retries in hours.",
                          "type": "integer",
                          "example": 24
                        },
                        "grace_period_days": {
                          "description": "Льготный период в днях.",
                          "x-description-kk": "Жеңілдік кезеңі, күнмен.",
                          "x-description-en": "Grace period in days.",
                          "type": "integer",
                          "example": 3
                        },
                        "in_grace_period": {
                          "description": "Признак нахождения в льготном периоде.",
                          "x-description-kk": "Жеңілдік кезеңінде болу белгісі.",
                          "x-description-en": "Whether the subscription is in the grace period.",
                          "type": "boolean",
                          "example": false
                        },
                        "is_sandbox": {
                          "description": "Признак тестового (sandbox) объекта.",
                          "x-description-kk": "Тестілік (sandbox) нысан белгісі.",
                          "x-description-en": "Whether the object is a sandbox (test) object.",
                          "type": "boolean",
                          "example": false
                        },
                        "metadata": {
                          "description": "Произвольные метаданные.",
                          "x-description-kk": "Еркін метадеректер.",
                          "x-description-en": "Arbitrary metadata.",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "created_at": {
                          "description": "Дата и время создания.",
                          "x-description-kk": "Жасалған күні мен уақыты.",
                          "x-description-en": "Date and time of creation.",
                          "type": "string",
                          "example": "2026-01-10T12:00:00+00:00"
                        },
                        "updated_at": {
                          "description": "Дата и время последнего обновления.",
                          "x-description-kk": "Соңғы жаңарту күні мен уақыты.",
                          "x-description-en": "Date and time of the last update.",
                          "type": "string",
                          "example": "2026-02-15T10:30:00+00:00"
                        },
                        "last_payment": {
                          "description": "Данные последнего платежа.",
                          "x-description-kk": "Соңғы төлем деректері.",
                          "x-description-en": "Details of the last payment.",
                          "type": "object",
                          "properties": {
                            "amount": {
                              "description": "Сумма в тенге.",
                              "x-description-kk": "Теңгемен сома.",
                              "x-description-en": "Amount in tenge.",
                              "type": "string",
                              "example": "5000.00"
                            },
                            "paid_at": {
                              "description": "Дата и время оплаты (null если не оплачено).",
                              "x-description-kk": "Төлем күні мен уақыты (төленбесе null).",
                              "x-description-en": "Date and time of payment (null if unpaid).",
                              "type": "string",
                              "example": "2026-02-15T10:30:00+00:00"
                            },
                            "status": {
                              "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                              "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                              "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                              "type": "string",
                              "example": "paid"
                            }
                          }
                        },
                        "stats": {
                          "description": "Статистика по подписке.",
                          "x-description-kk": "Жазылым бойынша статистика.",
                          "x-description-en": "Subscription statistics.",
                          "type": "object",
                          "properties": {
                            "total_payments": {
                              "description": "Всего платежей.",
                              "x-description-kk": "Барлық төлемдер.",
                              "x-description-en": "Total number of payments.",
                              "type": "integer",
                              "example": 3
                            },
                            "successful_payments": {
                              "description": "Успешных платежей.",
                              "x-description-kk": "Сәтті төлемдер.",
                              "x-description-en": "Number of successful payments.",
                              "type": "integer",
                              "example": 3
                            },
                            "failed_payments": {
                              "description": "Неудачных платежей.",
                              "x-description-kk": "Сәтсіз төлемдер.",
                              "x-description-en": "Number of failed payments.",
                              "type": "integer",
                              "example": 0
                            },
                            "total_amount": {
                              "description": "Суммарная сумма платежей.",
                              "x-description-kk": "Төлемдердің жалпы сомасы.",
                              "x-description-en": "Total amount of payments.",
                              "type": "string",
                              "example": "15000.00"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Подписка не найдена",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "Subscription not found"
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Subscription not found"
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Подписки"
        ]
      },
      "put": {
        "summary": "Обновить подписку",
        "operationId": "",
        "description": "Обновляет параметры существующей подписки. Все поля опциональны.",
        "parameters": [
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "message": "Subscription updated",
                    "subscription": {
                      "id": 1,
                      "subscriber_name": "Иван Петров",
                      "phone_number": "87001234567",
                      "external_subscriber_id": "client-42",
                      "amount": "7500.00",
                      "cart_items": null,
                      "description": "Обновлённая подписка",
                      "billing_period": "monthly",
                      "billing_period_label": "Ежемесячно",
                      "billing_day": 20,
                      "billing_day_label": "20 числа",
                      "status": "active",
                      "status_label": "Активна",
                      "status_color": "green",
                      "started_at": "2026-01-15T00:00:00+00:00",
                      "next_billing_at": "2026-03-20T00:00:00+00:00",
                      "next_billing_in_days": 22,
                      "next_billing_label": "через 22 дня",
                      "paused_at": null,
                      "cancelled_at": null,
                      "failed_attempts": 0,
                      "max_retry_attempts": 5,
                      "retry_interval_hours": 48,
                      "grace_period_days": 5,
                      "in_grace_period": false,
                      "is_sandbox": false,
                      "metadata": {
                        "plan": "premium"
                      },
                      "created_at": "2026-01-10T12:00:00+00:00",
                      "updated_at": "2026-02-26T14:00:00+00:00"
                    }
                  },
                  "properties": {
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Subscription updated"
                    },
                    "subscription": {
                      "description": "Объект подписки.",
                      "x-description-kk": "Жазылым нысаны.",
                      "x-description-en": "Subscription object.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "description": "ID записи.",
                          "x-description-kk": "Жазбаның ID-і.",
                          "x-description-en": "Record ID.",
                          "type": "integer",
                          "example": 1
                        },
                        "subscriber_name": {
                          "description": "Имя подписчика.",
                          "x-description-kk": "Жазылушының аты.",
                          "x-description-en": "Subscriber name.",
                          "type": "string",
                          "example": "Иван Петров"
                        },
                        "phone_number": {
                          "description": "Номер телефона подписчика.",
                          "x-description-kk": "Жазылушының телефон нөмірі.",
                          "x-description-en": "Subscriber phone number.",
                          "type": "string",
                          "example": "87001234567"
                        },
                        "external_subscriber_id": {
                          "description": "Внешний ID подписчика.",
                          "x-description-kk": "Жазылушының сыртқы ID-і.",
                          "x-description-en": "External subscriber ID.",
                          "type": "string",
                          "example": "client-42"
                        },
                        "amount": {
                          "description": "Сумма в тенге.",
                          "x-description-kk": "Теңгемен сома.",
                          "x-description-en": "Amount in tenge.",
                          "type": "string",
                          "example": "7500.00"
                        },
                        "cart_items": {
                          "description": "Корзина товаров подписки (null без каталога).",
                          "x-description-kk": "Жазылым тауарларының себеті (каталогсыз null).",
                          "x-description-en": "Subscription cart items (null without a catalog).",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "description": {
                          "description": "Описание.",
                          "x-description-kk": "Сипаттама.",
                          "x-description-en": "Description.",
                          "type": "string",
                          "example": "Обновлённая подписка"
                        },
                        "billing_period": {
                          "description": "Период биллинга: daily, weekly, biweekly, monthly, quarterly, yearly.",
                          "x-description-kk": "Биллинг кезеңі: daily, weekly, biweekly, monthly, quarterly, yearly.",
                          "x-description-en": "Billing period: daily, weekly, biweekly, monthly, quarterly, yearly.",
                          "type": "string",
                          "example": "monthly"
                        },
                        "billing_period_label": {
                          "description": "Локализованное название периода биллинга.",
                          "x-description-kk": "Биллинг кезеңінің локализацияланған атауы.",
                          "x-description-en": "Localized billing period label.",
                          "type": "string",
                          "example": "Ежемесячно"
                        },
                        "billing_day": {
                          "description": "День биллинга (1-28).",
                          "x-description-kk": "Биллинг күні (1-28).",
                          "x-description-en": "Billing day (1-28).",
                          "type": "integer",
                          "example": 20
                        },
                        "billing_day_label": {
                          "description": "Локализованное обозначение дня биллинга.",
                          "x-description-kk": "Биллинг күнінің локализацияланған белгісі.",
                          "x-description-en": "Localized billing day label.",
                          "type": "string",
                          "example": "20 числа"
                        },
                        "status": {
                          "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                          "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                          "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                          "type": "string",
                          "example": "active"
                        },
                        "status_label": {
                          "description": "Локализованное название статуса.",
                          "x-description-kk": "Мәртебенің локализацияланған атауы.",
                          "x-description-en": "Localized status label.",
                          "type": "string",
                          "example": "Активна"
                        },
                        "status_color": {
                          "description": "Цвет статуса для UI.",
                          "x-description-kk": "UI үшін мәртебе түсі.",
                          "x-description-en": "Status color for the UI.",
                          "type": "string",
                          "example": "green"
                        },
                        "started_at": {
                          "description": "Дата начала подписки.",
                          "x-description-kk": "Жазылымның басталу күні.",
                          "x-description-en": "Subscription start date.",
                          "type": "string",
                          "example": "2026-01-15T00:00:00+00:00"
                        },
                        "next_billing_at": {
                          "description": "Дата следующего списания (null если нет).",
                          "x-description-kk": "Келесі есептен шығару күні (болмаса null).",
                          "x-description-en": "Next billing date (null if none).",
                          "type": "string",
                          "example": "2026-03-20T00:00:00+00:00"
                        },
                        "next_billing_in_days": {
                          "description": "Количество дней до следующего списания.",
                          "x-description-kk": "Келесі есептен шығаруға дейінгі күн саны.",
                          "x-description-en": "Number of days until the next billing.",
                          "type": "integer",
                          "example": 22
                        },
                        "next_billing_label": {
                          "description": "Текстовое обозначение следующего списания.",
                          "x-description-kk": "Келесі есептен шығарудың мәтіндік белгісі.",
                          "x-description-en": "Text label for the next billing.",
                          "type": "string",
                          "example": "через 22 дня"
                        },
                        "paused_at": {
                          "description": "Дата приостановки (null если активна).",
                          "x-description-kk": "Тоқтату күні (белсенді болса null).",
                          "x-description-en": "Date the subscription was paused (null if active).",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "cancelled_at": {
                          "description": "Дата отмены (null если не отменена).",
                          "x-description-kk": "Бас тарту күні (тоқтатылмаса null).",
                          "x-description-en": "Date the subscription was cancelled (null if not cancelled).",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "failed_attempts": {
                          "description": "Количество неудачных попыток списания.",
                          "x-description-kk": "Сәтсіз есептен шығару әрекеттерінің саны.",
                          "x-description-en": "Number of failed billing attempts.",
                          "type": "integer",
                          "example": 0
                        },
                        "max_retry_attempts": {
                          "description": "Макс. число повторных попыток.",
                          "x-description-kk": "Қайталау әрекеттерінің макс. саны.",
                          "x-description-en": "Max number of retry attempts.",
                          "type": "integer",
                          "example": 5
                        },
                        "retry_interval_hours": {
                          "description": "Интервал между повторами в часах.",
                          "x-description-kk": "Қайталаулар арасындағы интервал, сағатпен.",
                          "x-description-en": "Interval between retries in hours.",
                          "type": "integer",
                          "example": 48
                        },
                        "grace_period_days": {
                          "description": "Льготный период в днях.",
                          "x-description-kk": "Жеңілдік кезеңі, күнмен.",
                          "x-description-en": "Grace period in days.",
                          "type": "integer",
                          "example": 5
                        },
                        "in_grace_period": {
                          "description": "Признак нахождения в льготном периоде.",
                          "x-description-kk": "Жеңілдік кезеңінде болу белгісі.",
                          "x-description-en": "Whether the subscription is in the grace period.",
                          "type": "boolean",
                          "example": false
                        },
                        "is_sandbox": {
                          "description": "Признак тестового (sandbox) объекта.",
                          "x-description-kk": "Тестілік (sandbox) нысан белгісі.",
                          "x-description-en": "Whether the object is a sandbox (test) object.",
                          "type": "boolean",
                          "example": false
                        },
                        "metadata": {
                          "description": "Произвольные метаданные.",
                          "x-description-kk": "Еркін метадеректер.",
                          "x-description-en": "Arbitrary metadata.",
                          "type": "object",
                          "properties": {
                            "plan": {
                              "description": "Пример ключа метаданных (тариф).",
                              "x-description-kk": "Метадерек кілтінің мысалы (тариф).",
                              "x-description-en": "Example metadata key (plan).",
                              "type": "string",
                              "example": "premium"
                            }
                          }
                        },
                        "created_at": {
                          "description": "Дата и время создания.",
                          "x-description-kk": "Жасалған күні мен уақыты.",
                          "x-description-en": "Date and time of creation.",
                          "type": "string",
                          "example": "2026-01-10T12:00:00+00:00"
                        },
                        "updated_at": {
                          "description": "Дата и время последнего обновления.",
                          "x-description-kk": "Соңғы жаңарту күні мен уақыты.",
                          "x-description-en": "Date and time of the last update.",
                          "type": "string",
                          "example": "2026-02-26T14:00:00+00:00"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Подписка не найдена",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "Subscription not found"
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Subscription not found"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Ошибка валидации",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "message": "Validation failed",
                    "errors": {
                      "amount": [
                        "Минимальная сумма подписки - 100 тенге"
                      ]
                    }
                  },
                  "properties": {
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Validation failed"
                    },
                    "errors": {
                      "type": "object",
                      "properties": {
                        "amount": {
                          "description": "Сумма в тенге.",
                          "x-description-kk": "Теңгемен сома.",
                          "x-description-en": "Amount in tenge.",
                          "type": "array",
                          "example": [
                            "Минимальная сумма подписки - 100 тенге"
                          ],
                          "items": {
                            "description": "Позиции (товары) объекта.",
                            "x-description-kk": "Нысан позициялары (тауарлар).",
                            "x-description-en": "Line items (products) of the object.",
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Подписки"
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "amount": {
                    "type": "number",
                    "description": "Сумма списания в тенге (100-1000000).",
                    "x-description-kk": "Теңгемен есептен шығару сомасы (100-1000000).",
                    "x-description-en": "Charge amount in tenge (100-1000000).",
                    "example": 7500,
                    "nullable": true
                  },
                  "billing_day": {
                    "type": "integer",
                    "description": "День биллинга (1-28).",
                    "x-description-kk": "Биллинг күні (1-28).",
                    "x-description-en": "Billing day (1-28).",
                    "example": 20,
                    "nullable": true
                  },
                  "description": {
                    "type": "string",
                    "description": "Описание подписки.",
                    "x-description-kk": "Жазылым сипаттамасы.",
                    "x-description-en": "Subscription description.",
                    "example": "Обновлённая подписка",
                    "nullable": true
                  },
                  "subscriber_name": {
                    "type": "string",
                    "description": "Имя подписчика.",
                    "x-description-kk": "Жазылушының аты.",
                    "x-description-en": "Subscriber name.",
                    "example": "Иван Петров",
                    "nullable": true
                  },
                  "external_subscriber_id": {
                    "type": "string",
                    "description": "Внешний ID подписчика.",
                    "x-description-kk": "Жазылушының сыртқы ID-і.",
                    "x-description-en": "External subscriber ID.",
                    "example": "client-42",
                    "nullable": true
                  },
                  "max_retry_attempts": {
                    "type": "integer",
                    "description": "Макс. кол-во повторных попыток (1-10).",
                    "x-description-kk": "Қайталау әрекеттерінің макс. саны (1-10).",
                    "x-description-en": "Max number of retry attempts (1-10).",
                    "example": 5,
                    "nullable": true
                  },
                  "retry_interval_hours": {
                    "type": "integer",
                    "description": "Интервал между повторами в часах (1-168).",
                    "x-description-kk": "Қайталаулар арасындағы интервал, сағатпен (1-168).",
                    "x-description-en": "Interval between retries in hours (1-168).",
                    "example": 48,
                    "nullable": true
                  },
                  "grace_period_days": {
                    "type": "integer",
                    "description": "Льготный период в днях (1-30).",
                    "x-description-kk": "Жеңілдік кезеңі, күнмен (1-30).",
                    "x-description-en": "Grace period in days (1-30).",
                    "example": 5,
                    "nullable": true
                  },
                  "metadata": {
                    "type": "object",
                    "description": "Произвольные метаданные.",
                    "x-description-kk": "Еркін метадеректер.",
                    "x-description-en": "Arbitrary metadata.",
                    "example": {
                      "plan": "premium"
                    },
                    "properties": {},
                    "nullable": true
                  },
                  "cart_items": {
                    "type": "array",
                    "description": "Корзина товаров (только для каталожных организаций).",
                    "x-description-kk": "Тауарлар себеті (тек каталогты ұйымдар үшін).",
                    "x-description-en": "Cart items (only for catalog organizations).",
                    "example": [
                      []
                    ],
                    "items": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "catalog_item_id": {
                          "type": "integer",
                          "description": "ID товара из каталога.",
                          "x-description-kk": "Каталогтағы тауардың ID-і.",
                          "x-description-en": "Catalog item ID.",
                          "example": 1
                        },
                        "count": {
                          "type": "integer",
                          "description": "Количество.",
                          "x-description-kk": "Саны.",
                          "x-description-en": "Quantity.",
                          "example": 3
                        },
                        "price": {
                          "type": "number",
                          "nullable": true,
                          "description": "Переопределённая цена за единицу. Если не указана — используется selling_price из каталога.",
                          "x-description-kk": "Бірлік үшін қайта анықталған баға. Көрсетілмесе — каталогтан selling_price қолданылады.",
                          "x-description-en": "Overridden unit price. If omitted, selling_price from the catalog is used.",
                          "example": 4500
                        }
                      },
                      "required": [
                        "catalog_item_id",
                        "count"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      },
      "parameters": [
        {
          "in": "path",
          "name": "id",
          "description": "ID подписки.",
          "example": 1,
          "required": true,
          "schema": {
            "type": "integer"
          }
        }
      ]
    },
    "/subscriptions/{id}/pause": {
      "post": {
        "summary": "Приостановить подписку",
        "operationId": "",
        "description": "Приостанавливает активную подписку. Новые счета не будут выставляться до возобновления.",
        "parameters": [
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "message": "Subscription paused",
                    "subscription": {
                      "id": 1,
                      "subscriber_name": "Иван Петров",
                      "phone_number": "87001234567",
                      "external_subscriber_id": "client-42",
                      "amount": "5000.00",
                      "cart_items": null,
                      "description": "Ежемесячная подписка",
                      "billing_period": "monthly",
                      "billing_period_label": "Ежемесячно",
                      "billing_day": 15,
                      "billing_day_label": "15 числа",
                      "status": "paused",
                      "status_label": "Приостановлена",
                      "status_color": "yellow",
                      "started_at": "2026-01-15T00:00:00+00:00",
                      "next_billing_at": null,
                      "next_billing_in_days": null,
                      "next_billing_label": null,
                      "paused_at": "2026-02-26T14:00:00+00:00",
                      "cancelled_at": null,
                      "failed_attempts": 0,
                      "max_retry_attempts": 3,
                      "retry_interval_hours": 24,
                      "grace_period_days": 3,
                      "in_grace_period": false,
                      "is_sandbox": false,
                      "metadata": null,
                      "created_at": "2026-01-10T12:00:00+00:00",
                      "updated_at": "2026-02-26T14:00:00+00:00"
                    }
                  },
                  "properties": {
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Subscription paused"
                    },
                    "subscription": {
                      "description": "Объект подписки.",
                      "x-description-kk": "Жазылым нысаны.",
                      "x-description-en": "Subscription object.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "description": "ID записи.",
                          "x-description-kk": "Жазбаның ID-і.",
                          "x-description-en": "Record ID.",
                          "type": "integer",
                          "example": 1
                        },
                        "subscriber_name": {
                          "description": "Имя подписчика.",
                          "x-description-kk": "Жазылушының аты.",
                          "x-description-en": "Subscriber name.",
                          "type": "string",
                          "example": "Иван Петров"
                        },
                        "phone_number": {
                          "description": "Номер телефона подписчика.",
                          "x-description-kk": "Жазылушының телефон нөмірі.",
                          "x-description-en": "Subscriber phone number.",
                          "type": "string",
                          "example": "87001234567"
                        },
                        "external_subscriber_id": {
                          "description": "Внешний ID подписчика.",
                          "x-description-kk": "Жазылушының сыртқы ID-і.",
                          "x-description-en": "External subscriber ID.",
                          "type": "string",
                          "example": "client-42"
                        },
                        "amount": {
                          "description": "Сумма в тенге.",
                          "x-description-kk": "Теңгемен сома.",
                          "x-description-en": "Amount in tenge.",
                          "type": "string",
                          "example": "5000.00"
                        },
                        "cart_items": {
                          "description": "Корзина товаров подписки (null без каталога).",
                          "x-description-kk": "Жазылым тауарларының себеті (каталогсыз null).",
                          "x-description-en": "Subscription cart items (null without a catalog).",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "description": {
                          "description": "Описание.",
                          "x-description-kk": "Сипаттама.",
                          "x-description-en": "Description.",
                          "type": "string",
                          "example": "Ежемесячная подписка"
                        },
                        "billing_period": {
                          "description": "Период биллинга: daily, weekly, biweekly, monthly, quarterly, yearly.",
                          "x-description-kk": "Биллинг кезеңі: daily, weekly, biweekly, monthly, quarterly, yearly.",
                          "x-description-en": "Billing period: daily, weekly, biweekly, monthly, quarterly, yearly.",
                          "type": "string",
                          "example": "monthly"
                        },
                        "billing_period_label": {
                          "description": "Локализованное название периода биллинга.",
                          "x-description-kk": "Биллинг кезеңінің локализацияланған атауы.",
                          "x-description-en": "Localized billing period label.",
                          "type": "string",
                          "example": "Ежемесячно"
                        },
                        "billing_day": {
                          "description": "День биллинга (1-28).",
                          "x-description-kk": "Биллинг күні (1-28).",
                          "x-description-en": "Billing day (1-28).",
                          "type": "integer",
                          "example": 15
                        },
                        "billing_day_label": {
                          "description": "Локализованное обозначение дня биллинга.",
                          "x-description-kk": "Биллинг күнінің локализацияланған белгісі.",
                          "x-description-en": "Localized billing day label.",
                          "type": "string",
                          "example": "15 числа"
                        },
                        "status": {
                          "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                          "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                          "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                          "type": "string",
                          "example": "paused"
                        },
                        "status_label": {
                          "description": "Локализованное название статуса.",
                          "x-description-kk": "Мәртебенің локализацияланған атауы.",
                          "x-description-en": "Localized status label.",
                          "type": "string",
                          "example": "Приостановлена"
                        },
                        "status_color": {
                          "description": "Цвет статуса для UI.",
                          "x-description-kk": "UI үшін мәртебе түсі.",
                          "x-description-en": "Status color for the UI.",
                          "type": "string",
                          "example": "yellow"
                        },
                        "started_at": {
                          "description": "Дата начала подписки.",
                          "x-description-kk": "Жазылымның басталу күні.",
                          "x-description-en": "Subscription start date.",
                          "type": "string",
                          "example": "2026-01-15T00:00:00+00:00"
                        },
                        "next_billing_at": {
                          "description": "Дата следующего списания (null если нет).",
                          "x-description-kk": "Келесі есептен шығару күні (болмаса null).",
                          "x-description-en": "Next billing date (null if none).",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "next_billing_in_days": {
                          "description": "Количество дней до следующего списания.",
                          "x-description-kk": "Келесі есептен шығаруға дейінгі күн саны.",
                          "x-description-en": "Number of days until the next billing.",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "next_billing_label": {
                          "description": "Текстовое обозначение следующего списания.",
                          "x-description-kk": "Келесі есептен шығарудың мәтіндік белгісі.",
                          "x-description-en": "Text label for the next billing.",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "paused_at": {
                          "description": "Дата приостановки (null если активна).",
                          "x-description-kk": "Тоқтату күні (белсенді болса null).",
                          "x-description-en": "Date the subscription was paused (null if active).",
                          "type": "string",
                          "example": "2026-02-26T14:00:00+00:00"
                        },
                        "cancelled_at": {
                          "description": "Дата отмены (null если не отменена).",
                          "x-description-kk": "Бас тарту күні (тоқтатылмаса null).",
                          "x-description-en": "Date the subscription was cancelled (null if not cancelled).",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "failed_attempts": {
                          "description": "Количество неудачных попыток списания.",
                          "x-description-kk": "Сәтсіз есептен шығару әрекеттерінің саны.",
                          "x-description-en": "Number of failed billing attempts.",
                          "type": "integer",
                          "example": 0
                        },
                        "max_retry_attempts": {
                          "description": "Макс. число повторных попыток.",
                          "x-description-kk": "Қайталау әрекеттерінің макс. саны.",
                          "x-description-en": "Max number of retry attempts.",
                          "type": "integer",
                          "example": 3
                        },
                        "retry_interval_hours": {
                          "description": "Интервал между повторами в часах.",
                          "x-description-kk": "Қайталаулар арасындағы интервал, сағатпен.",
                          "x-description-en": "Interval between retries in hours.",
                          "type": "integer",
                          "example": 24
                        },
                        "grace_period_days": {
                          "description": "Льготный период в днях.",
                          "x-description-kk": "Жеңілдік кезеңі, күнмен.",
                          "x-description-en": "Grace period in days.",
                          "type": "integer",
                          "example": 3
                        },
                        "in_grace_period": {
                          "description": "Признак нахождения в льготном периоде.",
                          "x-description-kk": "Жеңілдік кезеңінде болу белгісі.",
                          "x-description-en": "Whether the subscription is in the grace period.",
                          "type": "boolean",
                          "example": false
                        },
                        "is_sandbox": {
                          "description": "Признак тестового (sandbox) объекта.",
                          "x-description-kk": "Тестілік (sandbox) нысан белгісі.",
                          "x-description-en": "Whether the object is a sandbox (test) object.",
                          "type": "boolean",
                          "example": false
                        },
                        "metadata": {
                          "description": "Произвольные метаданные.",
                          "x-description-kk": "Еркін метадеректер.",
                          "x-description-en": "Arbitrary metadata.",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "created_at": {
                          "description": "Дата и время создания.",
                          "x-description-kk": "Жасалған күні мен уақыты.",
                          "x-description-en": "Date and time of creation.",
                          "type": "string",
                          "example": "2026-01-10T12:00:00+00:00"
                        },
                        "updated_at": {
                          "description": "Дата и время последнего обновления.",
                          "x-description-kk": "Соңғы жаңарту күні мен уақыты.",
                          "x-description-en": "Date and time of the last update.",
                          "type": "string",
                          "example": "2026-02-26T14:00:00+00:00"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Некорректный статус",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "Only active subscriptions can be paused"
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Only active subscriptions can be paused"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Подписка не найдена",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "Subscription not found"
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Subscription not found"
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Подписки"
        ]
      },
      "parameters": [
        {
          "in": "path",
          "name": "id",
          "description": "ID подписки.",
          "example": 1,
          "required": true,
          "schema": {
            "type": "integer"
          }
        }
      ]
    },
    "/subscriptions/{id}/resume": {
      "post": {
        "summary": "Возобновить подписку",
        "operationId": "",
        "description": "Возобновляет приостановленную подписку. Следующий биллинг будет рассчитан автоматически.",
        "parameters": [
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "message": "Subscription resumed",
                    "subscription": {
                      "id": 1,
                      "subscriber_name": "Иван Петров",
                      "phone_number": "87001234567",
                      "external_subscriber_id": "client-42",
                      "amount": "5000.00",
                      "cart_items": null,
                      "description": "Ежемесячная подписка",
                      "billing_period": "monthly",
                      "billing_period_label": "Ежемесячно",
                      "billing_day": 15,
                      "billing_day_label": "15 числа",
                      "status": "active",
                      "status_label": "Активна",
                      "status_color": "green",
                      "started_at": "2026-01-15T00:00:00+00:00",
                      "next_billing_at": "2026-03-15T00:00:00+00:00",
                      "next_billing_in_days": 17,
                      "next_billing_label": "через 17 дней",
                      "paused_at": null,
                      "cancelled_at": null,
                      "failed_attempts": 0,
                      "max_retry_attempts": 3,
                      "retry_interval_hours": 24,
                      "grace_period_days": 3,
                      "in_grace_period": false,
                      "is_sandbox": false,
                      "metadata": null,
                      "created_at": "2026-01-10T12:00:00+00:00",
                      "updated_at": "2026-02-26T14:00:00+00:00"
                    }
                  },
                  "properties": {
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Subscription resumed"
                    },
                    "subscription": {
                      "description": "Объект подписки.",
                      "x-description-kk": "Жазылым нысаны.",
                      "x-description-en": "Subscription object.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "description": "ID записи.",
                          "x-description-kk": "Жазбаның ID-і.",
                          "x-description-en": "Record ID.",
                          "type": "integer",
                          "example": 1
                        },
                        "subscriber_name": {
                          "description": "Имя подписчика.",
                          "x-description-kk": "Жазылушының аты.",
                          "x-description-en": "Subscriber name.",
                          "type": "string",
                          "example": "Иван Петров"
                        },
                        "phone_number": {
                          "description": "Номер телефона подписчика.",
                          "x-description-kk": "Жазылушының телефон нөмірі.",
                          "x-description-en": "Subscriber phone number.",
                          "type": "string",
                          "example": "87001234567"
                        },
                        "external_subscriber_id": {
                          "description": "Внешний ID подписчика.",
                          "x-description-kk": "Жазылушының сыртқы ID-і.",
                          "x-description-en": "External subscriber ID.",
                          "type": "string",
                          "example": "client-42"
                        },
                        "amount": {
                          "description": "Сумма в тенге.",
                          "x-description-kk": "Теңгемен сома.",
                          "x-description-en": "Amount in tenge.",
                          "type": "string",
                          "example": "5000.00"
                        },
                        "cart_items": {
                          "description": "Корзина товаров подписки (null без каталога).",
                          "x-description-kk": "Жазылым тауарларының себеті (каталогсыз null).",
                          "x-description-en": "Subscription cart items (null without a catalog).",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "description": {
                          "description": "Описание.",
                          "x-description-kk": "Сипаттама.",
                          "x-description-en": "Description.",
                          "type": "string",
                          "example": "Ежемесячная подписка"
                        },
                        "billing_period": {
                          "description": "Период биллинга: daily, weekly, biweekly, monthly, quarterly, yearly.",
                          "x-description-kk": "Биллинг кезеңі: daily, weekly, biweekly, monthly, quarterly, yearly.",
                          "x-description-en": "Billing period: daily, weekly, biweekly, monthly, quarterly, yearly.",
                          "type": "string",
                          "example": "monthly"
                        },
                        "billing_period_label": {
                          "description": "Локализованное название периода биллинга.",
                          "x-description-kk": "Биллинг кезеңінің локализацияланған атауы.",
                          "x-description-en": "Localized billing period label.",
                          "type": "string",
                          "example": "Ежемесячно"
                        },
                        "billing_day": {
                          "description": "День биллинга (1-28).",
                          "x-description-kk": "Биллинг күні (1-28).",
                          "x-description-en": "Billing day (1-28).",
                          "type": "integer",
                          "example": 15
                        },
                        "billing_day_label": {
                          "description": "Локализованное обозначение дня биллинга.",
                          "x-description-kk": "Биллинг күнінің локализацияланған белгісі.",
                          "x-description-en": "Localized billing day label.",
                          "type": "string",
                          "example": "15 числа"
                        },
                        "status": {
                          "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                          "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                          "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                          "type": "string",
                          "example": "active"
                        },
                        "status_label": {
                          "description": "Локализованное название статуса.",
                          "x-description-kk": "Мәртебенің локализацияланған атауы.",
                          "x-description-en": "Localized status label.",
                          "type": "string",
                          "example": "Активна"
                        },
                        "status_color": {
                          "description": "Цвет статуса для UI.",
                          "x-description-kk": "UI үшін мәртебе түсі.",
                          "x-description-en": "Status color for the UI.",
                          "type": "string",
                          "example": "green"
                        },
                        "started_at": {
                          "description": "Дата начала подписки.",
                          "x-description-kk": "Жазылымның басталу күні.",
                          "x-description-en": "Subscription start date.",
                          "type": "string",
                          "example": "2026-01-15T00:00:00+00:00"
                        },
                        "next_billing_at": {
                          "description": "Дата следующего списания (null если нет).",
                          "x-description-kk": "Келесі есептен шығару күні (болмаса null).",
                          "x-description-en": "Next billing date (null if none).",
                          "type": "string",
                          "example": "2026-03-15T00:00:00+00:00"
                        },
                        "next_billing_in_days": {
                          "description": "Количество дней до следующего списания.",
                          "x-description-kk": "Келесі есептен шығаруға дейінгі күн саны.",
                          "x-description-en": "Number of days until the next billing.",
                          "type": "integer",
                          "example": 17
                        },
                        "next_billing_label": {
                          "description": "Текстовое обозначение следующего списания.",
                          "x-description-kk": "Келесі есептен шығарудың мәтіндік белгісі.",
                          "x-description-en": "Text label for the next billing.",
                          "type": "string",
                          "example": "через 17 дней"
                        },
                        "paused_at": {
                          "description": "Дата приостановки (null если активна).",
                          "x-description-kk": "Тоқтату күні (белсенді болса null).",
                          "x-description-en": "Date the subscription was paused (null if active).",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "cancelled_at": {
                          "description": "Дата отмены (null если не отменена).",
                          "x-description-kk": "Бас тарту күні (тоқтатылмаса null).",
                          "x-description-en": "Date the subscription was cancelled (null if not cancelled).",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "failed_attempts": {
                          "description": "Количество неудачных попыток списания.",
                          "x-description-kk": "Сәтсіз есептен шығару әрекеттерінің саны.",
                          "x-description-en": "Number of failed billing attempts.",
                          "type": "integer",
                          "example": 0
                        },
                        "max_retry_attempts": {
                          "description": "Макс. число повторных попыток.",
                          "x-description-kk": "Қайталау әрекеттерінің макс. саны.",
                          "x-description-en": "Max number of retry attempts.",
                          "type": "integer",
                          "example": 3
                        },
                        "retry_interval_hours": {
                          "description": "Интервал между повторами в часах.",
                          "x-description-kk": "Қайталаулар арасындағы интервал, сағатпен.",
                          "x-description-en": "Interval between retries in hours.",
                          "type": "integer",
                          "example": 24
                        },
                        "grace_period_days": {
                          "description": "Льготный период в днях.",
                          "x-description-kk": "Жеңілдік кезеңі, күнмен.",
                          "x-description-en": "Grace period in days.",
                          "type": "integer",
                          "example": 3
                        },
                        "in_grace_period": {
                          "description": "Признак нахождения в льготном периоде.",
                          "x-description-kk": "Жеңілдік кезеңінде болу белгісі.",
                          "x-description-en": "Whether the subscription is in the grace period.",
                          "type": "boolean",
                          "example": false
                        },
                        "is_sandbox": {
                          "description": "Признак тестового (sandbox) объекта.",
                          "x-description-kk": "Тестілік (sandbox) нысан белгісі.",
                          "x-description-en": "Whether the object is a sandbox (test) object.",
                          "type": "boolean",
                          "example": false
                        },
                        "metadata": {
                          "description": "Произвольные метаданные.",
                          "x-description-kk": "Еркін метадеректер.",
                          "x-description-en": "Arbitrary metadata.",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "created_at": {
                          "description": "Дата и время создания.",
                          "x-description-kk": "Жасалған күні мен уақыты.",
                          "x-description-en": "Date and time of creation.",
                          "type": "string",
                          "example": "2026-01-10T12:00:00+00:00"
                        },
                        "updated_at": {
                          "description": "Дата и время последнего обновления.",
                          "x-description-kk": "Соңғы жаңарту күні мен уақыты.",
                          "x-description-en": "Date and time of the last update.",
                          "type": "string",
                          "example": "2026-02-26T14:00:00+00:00"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Некорректный статус",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "Only paused subscriptions can be resumed"
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Only paused subscriptions can be resumed"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Подписка не найдена",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "Subscription not found"
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Subscription not found"
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Подписки"
        ]
      },
      "parameters": [
        {
          "in": "path",
          "name": "id",
          "description": "ID подписки.",
          "example": 1,
          "required": true,
          "schema": {
            "type": "integer"
          }
        }
      ]
    },
    "/subscriptions/{id}/cancel": {
      "post": {
        "summary": "Отменить подписку",
        "operationId": "",
        "description": "Безвозвратно отменяет подписку. Новые счета больше не будут выставляться.",
        "parameters": [
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "message": "Subscription cancelled",
                    "subscription": {
                      "id": 1,
                      "subscriber_name": "Иван Петров",
                      "phone_number": "87001234567",
                      "external_subscriber_id": "client-42",
                      "amount": "5000.00",
                      "cart_items": null,
                      "description": "Ежемесячная подписка",
                      "billing_period": "monthly",
                      "billing_period_label": "Ежемесячно",
                      "billing_day": 15,
                      "billing_day_label": "15 числа",
                      "status": "cancelled",
                      "status_label": "Отменена",
                      "status_color": "red",
                      "started_at": "2026-01-15T00:00:00+00:00",
                      "next_billing_at": null,
                      "next_billing_in_days": null,
                      "next_billing_label": null,
                      "paused_at": null,
                      "cancelled_at": "2026-02-26T14:00:00+00:00",
                      "failed_attempts": 0,
                      "max_retry_attempts": 3,
                      "retry_interval_hours": 24,
                      "grace_period_days": 3,
                      "in_grace_period": false,
                      "is_sandbox": false,
                      "metadata": null,
                      "created_at": "2026-01-10T12:00:00+00:00",
                      "updated_at": "2026-02-26T14:00:00+00:00"
                    }
                  },
                  "properties": {
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Subscription cancelled"
                    },
                    "subscription": {
                      "description": "Объект подписки.",
                      "x-description-kk": "Жазылым нысаны.",
                      "x-description-en": "Subscription object.",
                      "type": "object",
                      "properties": {
                        "id": {
                          "description": "ID записи.",
                          "x-description-kk": "Жазбаның ID-і.",
                          "x-description-en": "Record ID.",
                          "type": "integer",
                          "example": 1
                        },
                        "subscriber_name": {
                          "description": "Имя подписчика.",
                          "x-description-kk": "Жазылушының аты.",
                          "x-description-en": "Subscriber name.",
                          "type": "string",
                          "example": "Иван Петров"
                        },
                        "phone_number": {
                          "description": "Номер телефона подписчика.",
                          "x-description-kk": "Жазылушының телефон нөмірі.",
                          "x-description-en": "Subscriber phone number.",
                          "type": "string",
                          "example": "87001234567"
                        },
                        "external_subscriber_id": {
                          "description": "Внешний ID подписчика.",
                          "x-description-kk": "Жазылушының сыртқы ID-і.",
                          "x-description-en": "External subscriber ID.",
                          "type": "string",
                          "example": "client-42"
                        },
                        "amount": {
                          "description": "Сумма в тенге.",
                          "x-description-kk": "Теңгемен сома.",
                          "x-description-en": "Amount in tenge.",
                          "type": "string",
                          "example": "5000.00"
                        },
                        "cart_items": {
                          "description": "Корзина товаров подписки (null без каталога).",
                          "x-description-kk": "Жазылым тауарларының себеті (каталогсыз null).",
                          "x-description-en": "Subscription cart items (null without a catalog).",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "description": {
                          "description": "Описание.",
                          "x-description-kk": "Сипаттама.",
                          "x-description-en": "Description.",
                          "type": "string",
                          "example": "Ежемесячная подписка"
                        },
                        "billing_period": {
                          "description": "Период биллинга: daily, weekly, biweekly, monthly, quarterly, yearly.",
                          "x-description-kk": "Биллинг кезеңі: daily, weekly, biweekly, monthly, quarterly, yearly.",
                          "x-description-en": "Billing period: daily, weekly, biweekly, monthly, quarterly, yearly.",
                          "type": "string",
                          "example": "monthly"
                        },
                        "billing_period_label": {
                          "description": "Локализованное название периода биллинга.",
                          "x-description-kk": "Биллинг кезеңінің локализацияланған атауы.",
                          "x-description-en": "Localized billing period label.",
                          "type": "string",
                          "example": "Ежемесячно"
                        },
                        "billing_day": {
                          "description": "День биллинга (1-28).",
                          "x-description-kk": "Биллинг күні (1-28).",
                          "x-description-en": "Billing day (1-28).",
                          "type": "integer",
                          "example": 15
                        },
                        "billing_day_label": {
                          "description": "Локализованное обозначение дня биллинга.",
                          "x-description-kk": "Биллинг күнінің локализацияланған белгісі.",
                          "x-description-en": "Localized billing day label.",
                          "type": "string",
                          "example": "15 числа"
                        },
                        "status": {
                          "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                          "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                          "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                          "type": "string",
                          "example": "cancelled"
                        },
                        "status_label": {
                          "description": "Локализованное название статуса.",
                          "x-description-kk": "Мәртебенің локализацияланған атауы.",
                          "x-description-en": "Localized status label.",
                          "type": "string",
                          "example": "Отменена"
                        },
                        "status_color": {
                          "description": "Цвет статуса для UI.",
                          "x-description-kk": "UI үшін мәртебе түсі.",
                          "x-description-en": "Status color for the UI.",
                          "type": "string",
                          "example": "red"
                        },
                        "started_at": {
                          "description": "Дата начала подписки.",
                          "x-description-kk": "Жазылымның басталу күні.",
                          "x-description-en": "Subscription start date.",
                          "type": "string",
                          "example": "2026-01-15T00:00:00+00:00"
                        },
                        "next_billing_at": {
                          "description": "Дата следующего списания (null если нет).",
                          "x-description-kk": "Келесі есептен шығару күні (болмаса null).",
                          "x-description-en": "Next billing date (null if none).",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "next_billing_in_days": {
                          "description": "Количество дней до следующего списания.",
                          "x-description-kk": "Келесі есептен шығаруға дейінгі күн саны.",
                          "x-description-en": "Number of days until the next billing.",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "next_billing_label": {
                          "description": "Текстовое обозначение следующего списания.",
                          "x-description-kk": "Келесі есептен шығарудың мәтіндік белгісі.",
                          "x-description-en": "Text label for the next billing.",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "paused_at": {
                          "description": "Дата приостановки (null если активна).",
                          "x-description-kk": "Тоқтату күні (белсенді болса null).",
                          "x-description-en": "Date the subscription was paused (null if active).",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "cancelled_at": {
                          "description": "Дата отмены (null если не отменена).",
                          "x-description-kk": "Бас тарту күні (тоқтатылмаса null).",
                          "x-description-en": "Date the subscription was cancelled (null if not cancelled).",
                          "type": "string",
                          "example": "2026-02-26T14:00:00+00:00"
                        },
                        "failed_attempts": {
                          "description": "Количество неудачных попыток списания.",
                          "x-description-kk": "Сәтсіз есептен шығару әрекеттерінің саны.",
                          "x-description-en": "Number of failed billing attempts.",
                          "type": "integer",
                          "example": 0
                        },
                        "max_retry_attempts": {
                          "description": "Макс. число повторных попыток.",
                          "x-description-kk": "Қайталау әрекеттерінің макс. саны.",
                          "x-description-en": "Max number of retry attempts.",
                          "type": "integer",
                          "example": 3
                        },
                        "retry_interval_hours": {
                          "description": "Интервал между повторами в часах.",
                          "x-description-kk": "Қайталаулар арасындағы интервал, сағатпен.",
                          "x-description-en": "Interval between retries in hours.",
                          "type": "integer",
                          "example": 24
                        },
                        "grace_period_days": {
                          "description": "Льготный период в днях.",
                          "x-description-kk": "Жеңілдік кезеңі, күнмен.",
                          "x-description-en": "Grace period in days.",
                          "type": "integer",
                          "example": 3
                        },
                        "in_grace_period": {
                          "description": "Признак нахождения в льготном периоде.",
                          "x-description-kk": "Жеңілдік кезеңінде болу белгісі.",
                          "x-description-en": "Whether the subscription is in the grace period.",
                          "type": "boolean",
                          "example": false
                        },
                        "is_sandbox": {
                          "description": "Признак тестового (sandbox) объекта.",
                          "x-description-kk": "Тестілік (sandbox) нысан белгісі.",
                          "x-description-en": "Whether the object is a sandbox (test) object.",
                          "type": "boolean",
                          "example": false
                        },
                        "metadata": {
                          "description": "Произвольные метаданные.",
                          "x-description-kk": "Еркін метадеректер.",
                          "x-description-en": "Arbitrary metadata.",
                          "type": "string",
                          "example": null,
                          "nullable": true
                        },
                        "created_at": {
                          "description": "Дата и время создания.",
                          "x-description-kk": "Жасалған күні мен уақыты.",
                          "x-description-en": "Date and time of creation.",
                          "type": "string",
                          "example": "2026-01-10T12:00:00+00:00"
                        },
                        "updated_at": {
                          "description": "Дата и время последнего обновления.",
                          "x-description-kk": "Соңғы жаңарту күні мен уақыты.",
                          "x-description-en": "Date and time of the last update.",
                          "type": "string",
                          "example": "2026-02-26T14:00:00+00:00"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Некорректный статус",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "Only active or paused subscriptions can be cancelled"
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Only active or paused subscriptions can be cancelled"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Подписка не найдена",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "Subscription not found"
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Subscription not found"
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Подписки"
        ]
      },
      "parameters": [
        {
          "in": "path",
          "name": "id",
          "description": "ID подписки.",
          "example": 1,
          "required": true,
          "schema": {
            "type": "integer"
          }
        }
      ]
    },
    "/subscriptions/{id}/invoices": {
      "get": {
        "summary": "История платежей подписки",
        "operationId": "",
        "description": "Возвращает пагинированный список всех платежей (счетов) по подписке.",
        "parameters": [
          {
            "in": "query",
            "name": "per_page",
            "description": "Кол-во на страницу (по умолчанию 20).",
            "x-description-kk": "Бір беттегі саны (әдепкіде 20).",
            "x-description-en": "Items per page (default 20).",
            "example": 20,
            "required": false,
            "schema": {
              "type": "integer",
              "description": "Кол-во на страницу (по умолчанию 20).",
              "x-description-kk": "Бір беттегі саны (әдепкіде 20).",
              "x-description-en": "Items per page (default 20).",
              "example": 20
            }
          },
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "data": [
                      {
                        "id": 1,
                        "invoice_id": 42,
                        "billing_period_start": "2026-02-01",
                        "billing_period_end": "2026-02-28",
                        "billing_period_label": "01.02.2026 — 28.02.2026",
                        "amount": "5000.00",
                        "attempt_number": 1,
                        "status": "paid",
                        "status_label": "Оплачен",
                        "status_color": "green",
                        "paid_at": "2026-02-01T10:30:00+00:00",
                        "failure_reason": null,
                        "invoice": {
                          "id": 42,
                          "kaspi_invoice_id": "INV-123456",
                          "status": "paid"
                        },
                        "created_at": "2026-02-01T10:00:00+00:00"
                      }
                    ],
                    "meta": {
                      "current_page": 1,
                      "total": 3,
                      "per_page": 20
                    }
                  },
                  "properties": {
                    "data": {
                      "description": "Массив записей результата.",
                      "x-description-kk": "Нәтиже жазбаларының массиві.",
                      "x-description-en": "Array of result records.",
                      "type": "array",
                      "example": [
                        {
                          "id": 1,
                          "invoice_id": 42,
                          "billing_period_start": "2026-02-01",
                          "billing_period_end": "2026-02-28",
                          "billing_period_label": "01.02.2026 — 28.02.2026",
                          "amount": "5000.00",
                          "attempt_number": 1,
                          "status": "paid",
                          "status_label": "Оплачен",
                          "status_color": "green",
                          "paid_at": "2026-02-01T10:30:00+00:00",
                          "failure_reason": null,
                          "invoice": {
                            "id": 42,
                            "kaspi_invoice_id": "INV-123456",
                            "status": "paid"
                          },
                          "created_at": "2026-02-01T10:00:00+00:00"
                        }
                      ],
                      "items": {
                        "description": "Позиции (товары) объекта.",
                        "x-description-kk": "Нысан позициялары (тауарлар).",
                        "x-description-en": "Line items (products) of the object.",
                        "type": "object",
                        "properties": {
                          "id": {
                            "description": "ID записи.",
                            "x-description-kk": "Жазбаның ID-і.",
                            "x-description-en": "Record ID.",
                            "type": "integer",
                            "example": 1
                          },
                          "invoice_id": {
                            "description": "ID связанного счёта.",
                            "x-description-kk": "Байланысты шоттың ID-і.",
                            "x-description-en": "Related invoice ID.",
                            "type": "integer",
                            "example": 42
                          },
                          "billing_period_start": {
                            "description": "Начало расчётного периода.",
                            "x-description-kk": "Есеп айырысу кезеңінің басы.",
                            "x-description-en": "Start of the billing period.",
                            "type": "string",
                            "example": "2026-02-01"
                          },
                          "billing_period_end": {
                            "description": "Конец расчётного периода.",
                            "x-description-kk": "Есеп айырысу кезеңінің соңы.",
                            "x-description-en": "End of the billing period.",
                            "type": "string",
                            "example": "2026-02-28"
                          },
                          "billing_period_label": {
                            "description": "Локализованное название периода биллинга.",
                            "x-description-kk": "Биллинг кезеңінің локализацияланған атауы.",
                            "x-description-en": "Localized billing period label.",
                            "type": "string",
                            "example": "01.02.2026 — 28.02.2026"
                          },
                          "amount": {
                            "description": "Сумма в тенге.",
                            "x-description-kk": "Теңгемен сома.",
                            "x-description-en": "Amount in tenge.",
                            "type": "string",
                            "example": "5000.00"
                          },
                          "attempt_number": {
                            "description": "Номер попытки списания.",
                            "x-description-kk": "Есептен шығару әрекетінің нөмірі.",
                            "x-description-en": "Billing attempt number.",
                            "type": "integer",
                            "example": 1
                          },
                          "status": {
                            "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                            "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                            "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                            "type": "string",
                            "example": "paid"
                          },
                          "status_label": {
                            "description": "Локализованное название статуса.",
                            "x-description-kk": "Мәртебенің локализацияланған атауы.",
                            "x-description-en": "Localized status label.",
                            "type": "string",
                            "example": "Оплачен"
                          },
                          "status_color": {
                            "description": "Цвет статуса для UI.",
                            "x-description-kk": "UI үшін мәртебе түсі.",
                            "x-description-en": "Status color for the UI.",
                            "type": "string",
                            "example": "green"
                          },
                          "paid_at": {
                            "description": "Дата и время оплаты (null если не оплачено).",
                            "x-description-kk": "Төлем күні мен уақыты (төленбесе null).",
                            "x-description-en": "Date and time of payment (null if unpaid).",
                            "type": "string",
                            "example": "2026-02-01T10:30:00+00:00"
                          },
                          "failure_reason": {
                            "description": "Причина неудачи (null при успехе).",
                            "x-description-kk": "Сәтсіздік себебі (сәтті болса null).",
                            "x-description-en": "Failure reason (null on success).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "invoice": {
                            "description": "Связанный счёт.",
                            "x-description-kk": "Байланысты шот.",
                            "x-description-en": "Related invoice.",
                            "type": "object",
                            "properties": {
                              "id": {
                                "description": "ID записи.",
                                "x-description-kk": "Жазбаның ID-і.",
                                "x-description-en": "Record ID.",
                                "type": "integer",
                                "example": 42
                              },
                              "kaspi_invoice_id": {
                                "description": "ID счёта в системе Kaspi.",
                                "x-description-kk": "Kaspi жүйесіндегі шот ID-і.",
                                "x-description-en": "Invoice ID in the Kaspi system.",
                                "type": "string",
                                "example": "INV-123456"
                              },
                              "status": {
                                "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                                "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                                "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                                "type": "string",
                                "example": "paid"
                              }
                            }
                          },
                          "created_at": {
                            "description": "Дата и время создания.",
                            "x-description-kk": "Жасалған күні мен уақыты.",
                            "x-description-en": "Date and time of creation.",
                            "type": "string",
                            "example": "2026-02-01T10:00:00+00:00"
                          }
                        }
                      }
                    },
                    "meta": {
                      "description": "Метаданные пагинации.",
                      "x-description-kk": "Беттеу метадеректері.",
                      "x-description-en": "Pagination metadata.",
                      "type": "object",
                      "properties": {
                        "current_page": {
                          "description": "Номер текущей страницы.",
                          "x-description-kk": "Ағымдағы беттің нөмірі.",
                          "x-description-en": "Current page number.",
                          "type": "integer",
                          "example": 1
                        },
                        "total": {
                          "description": "Общее количество записей.",
                          "x-description-kk": "Жазбалардың жалпы саны.",
                          "x-description-en": "Total number of records.",
                          "type": "integer",
                          "example": 3
                        },
                        "per_page": {
                          "description": "Количество записей на странице.",
                          "x-description-kk": "Бір беттегі жазбалар саны.",
                          "x-description-en": "Number of records per page.",
                          "type": "integer",
                          "example": 20
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Подписка не найдена",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "Subscription not found"
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Subscription not found"
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Подписки"
        ]
      },
      "parameters": [
        {
          "in": "path",
          "name": "id",
          "description": "ID подписки.",
          "example": 1,
          "required": true,
          "schema": {
            "type": "integer"
          }
        }
      ]
    },
    "/refunds": {
      "get": {
        "summary": "Список возвратов",
        "operationId": "",
        "description": "Возвращает список возвратов организации с фильтрацией и пагинацией.",
        "parameters": [
          {
            "in": "query",
            "name": "status[]",
            "description": "Фильтр по статусам. Допустимые значения: `pending`, `processing`, `completed`, `failed`.",
            "x-description-kk": "Мәртебелер бойынша сүзу. Рұқсат етілген мәндер: `pending`, `processing`, `completed`, `failed`.",
            "x-description-en": "Filter by statuses. Allowed values: `pending`, `processing`, `completed`, `failed`.",
            "example": [
              "completed"
            ],
            "required": false,
            "schema": {
              "type": "array",
              "description": "Фильтр по статусам. Допустимые значения: `pending`, `processing`, `completed`, `failed`.",
              "x-description-kk": "Мәртебелер бойынша сүзу. Рұқсат етілген мәндер: `pending`, `processing`, `completed`, `failed`.",
              "x-description-en": "Filter by statuses. Allowed values: `pending`, `processing`, `completed`, `failed`.",
              "example": [
                "completed"
              ],
              "items": {
                "type": "string"
              }
            }
          },
          {
            "in": "query",
            "name": "invoice_id",
            "description": "Фильтр по ID счёта.",
            "x-description-kk": "Шот ID-і бойынша сүзу.",
            "x-description-en": "Filter by invoice ID.",
            "example": 1,
            "required": false,
            "schema": {
              "type": "integer",
              "description": "Фильтр по ID счёта.",
              "x-description-kk": "Шот ID-і бойынша сүзу.",
              "x-description-en": "Filter by invoice ID.",
              "example": 1
            }
          },
          {
            "in": "query",
            "name": "date_from",
            "description": "Начало периода в формате `Y-m-d`.",
            "x-description-kk": "Кезеңнің басы `Y-m-d` форматында.",
            "x-description-en": "Period start in `Y-m-d` format.",
            "example": "2026-01-01",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Начало периода в формате `Y-m-d`.",
              "x-description-kk": "Кезеңнің басы `Y-m-d` форматында.",
              "x-description-en": "Period start in `Y-m-d` format.",
              "example": "2026-01-01"
            }
          },
          {
            "in": "query",
            "name": "date_to",
            "description": "Конец периода в формате `Y-m-d`.",
            "x-description-kk": "Кезеңнің соңы `Y-m-d` форматында.",
            "x-description-en": "Period end in `Y-m-d` format.",
            "example": "2026-01-31",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Конец периода в формате `Y-m-d`.",
              "x-description-kk": "Кезеңнің соңы `Y-m-d` форматында.",
              "x-description-en": "Period end in `Y-m-d` format.",
              "example": "2026-01-31"
            }
          },
          {
            "in": "query",
            "name": "per_page",
            "description": "Количество записей на страницу (1-100).",
            "x-description-kk": "Бір беттегі жазбалар саны (1-100).",
            "x-description-en": "Records per page (1-100).",
            "example": 10,
            "required": false,
            "schema": {
              "type": "integer",
              "description": "Количество записей на страницу (1-100).",
              "x-description-kk": "Бір беттегі жазбалар саны (1-100).",
              "x-description-en": "Records per page (1-100).",
              "example": 10
            }
          },
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ пользователя.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Успешный запрос",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "current_page": 1,
                    "data": [
                      {
                        "id": 1,
                        "invoice_id": 1,
                        "user_id": 1,
                        "api_key_id": 1,
                        "amount": "2500.00",
                        "kaspi_refund_id": null,
                        "kaspi_status": null,
                        "status": "completed",
                        "reason": "Брак",
                        "initiated_by": "api_key",
                        "error_message": null,
                        "created_at": "2026-02-26T11:00:00+06:00",
                        "invoice": {
                          "id": 1,
                          "external_order_id": "ORDER-001",
                          "amount": "5000.00",
                          "status": "paid",
                          "kaspi_invoice_id": "ABC123"
                        },
                        "items": []
                      }
                    ],
                    "total": 1
                  },
                  "properties": {
                    "current_page": {
                      "description": "Номер текущей страницы.",
                      "x-description-kk": "Ағымдағы беттің нөмірі.",
                      "x-description-en": "Current page number.",
                      "type": "integer",
                      "example": 1
                    },
                    "data": {
                      "description": "Массив записей результата.",
                      "x-description-kk": "Нәтиже жазбаларының массиві.",
                      "x-description-en": "Array of result records.",
                      "type": "array",
                      "example": [
                        {
                          "id": 1,
                          "invoice_id": 1,
                          "user_id": 1,
                          "api_key_id": 1,
                          "amount": "2500.00",
                          "kaspi_refund_id": null,
                          "kaspi_status": null,
                          "status": "completed",
                          "reason": "Брак",
                          "initiated_by": "api_key",
                          "error_message": null,
                          "created_at": "2026-02-26T11:00:00+06:00",
                          "invoice": {
                            "id": 1,
                            "external_order_id": "ORDER-001",
                            "amount": "5000.00",
                            "status": "paid",
                            "kaspi_invoice_id": "ABC123"
                          },
                          "items": []
                        }
                      ],
                      "items": {
                        "description": "Позиции (товары) объекта.",
                        "x-description-kk": "Нысан позициялары (тауарлар).",
                        "x-description-en": "Line items (products) of the object.",
                        "type": "object",
                        "properties": {
                          "id": {
                            "description": "ID записи.",
                            "x-description-kk": "Жазбаның ID-і.",
                            "x-description-en": "Record ID.",
                            "type": "integer",
                            "example": 1
                          },
                          "invoice_id": {
                            "description": "ID связанного счёта.",
                            "x-description-kk": "Байланысты шоттың ID-і.",
                            "x-description-en": "Related invoice ID.",
                            "type": "integer",
                            "example": 1
                          },
                          "user_id": {
                            "description": "ID пользователя, инициировавшего операцию.",
                            "x-description-kk": "Операцияны бастаған пайдаланушының ID-і.",
                            "x-description-en": "ID of the user who initiated the operation.",
                            "type": "integer",
                            "example": 1
                          },
                          "api_key_id": {
                            "description": "ID API-ключа.",
                            "x-description-kk": "API-кілттің ID-і.",
                            "x-description-en": "API key ID.",
                            "type": "integer",
                            "example": 1
                          },
                          "amount": {
                            "description": "Сумма в тенге.",
                            "x-description-kk": "Теңгемен сома.",
                            "x-description-en": "Amount in tenge.",
                            "type": "string",
                            "example": "2500.00"
                          },
                          "kaspi_refund_id": {
                            "description": "ID возврата в системе Kaspi (null до обработки).",
                            "x-description-kk": "Kaspi жүйесіндегі қайтару ID-і (өңдеуге дейін null).",
                            "x-description-en": "Refund ID in the Kaspi system (null until processed).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "kaspi_status": {
                            "description": "Статус возврата в системе Kaspi (null до обработки).",
                            "x-description-kk": "Kaspi жүйесіндегі қайтару мәртебесі (өңдеуге дейін null).",
                            "x-description-en": "Refund status in the Kaspi system (null until processed).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "status": {
                            "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                            "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                            "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                            "type": "string",
                            "example": "completed"
                          },
                          "reason": {
                            "description": "Причина возврата.",
                            "x-description-kk": "Қайтару себебі.",
                            "x-description-en": "Refund reason.",
                            "type": "string",
                            "example": "Брак"
                          },
                          "initiated_by": {
                            "description": "Источник инициации: api_key или dashboard.",
                            "x-description-kk": "Бастау көзі: api_key немесе dashboard.",
                            "x-description-en": "Initiation source: api_key or dashboard.",
                            "type": "string",
                            "example": "api_key"
                          },
                          "error_message": {
                            "description": "Текст ошибки (null если ошибок нет).",
                            "x-description-kk": "Қате мәтіні (қате болмаса null).",
                            "x-description-en": "Error text (null if there is no error).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "created_at": {
                            "description": "Дата и время создания.",
                            "x-description-kk": "Жасалған күні мен уақыты.",
                            "x-description-en": "Date and time of creation.",
                            "type": "string",
                            "example": "2026-02-26T11:00:00+06:00"
                          },
                          "invoice": {
                            "description": "Связанный счёт.",
                            "x-description-kk": "Байланысты шот.",
                            "x-description-en": "Related invoice.",
                            "type": "object",
                            "properties": {
                              "id": {
                                "description": "ID записи.",
                                "x-description-kk": "Жазбаның ID-і.",
                                "x-description-en": "Record ID.",
                                "type": "integer",
                                "example": 1
                              },
                              "external_order_id": {
                                "description": "Внешний ID заказа.",
                                "x-description-kk": "Тапсырыстың сыртқы ID-і.",
                                "x-description-en": "External order ID.",
                                "type": "string",
                                "example": "ORDER-001"
                              },
                              "amount": {
                                "description": "Сумма в тенге.",
                                "x-description-kk": "Теңгемен сома.",
                                "x-description-en": "Amount in tenge.",
                                "type": "string",
                                "example": "5000.00"
                              },
                              "status": {
                                "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                                "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                                "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                                "type": "string",
                                "example": "paid"
                              },
                              "kaspi_invoice_id": {
                                "description": "ID счёта в системе Kaspi.",
                                "x-description-kk": "Kaspi жүйесіндегі шот ID-і.",
                                "x-description-en": "Invoice ID in the Kaspi system.",
                                "type": "string",
                                "example": "ABC123"
                              }
                            }
                          },
                          "items": {
                            "description": "Позиции (товары) объекта.",
                            "x-description-kk": "Нысан позициялары (тауарлар).",
                            "x-description-en": "Line items (products) of the object.",
                            "type": "array",
                            "example": []
                          }
                        }
                      }
                    },
                    "total": {
                      "description": "Общее количество записей.",
                      "x-description-kk": "Жазбалардың жалпы саны.",
                      "x-description-en": "Total number of records.",
                      "type": "integer",
                      "example": 1
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Ошибка валидации",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "message": "Validation failed",
                    "errors": {
                      "status.0": [
                        "The selected status.0 is invalid."
                      ]
                    }
                  },
                  "properties": {
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Validation failed"
                    },
                    "errors": {
                      "type": "object",
                      "properties": {
                        "status.0": {
                          "type": "array",
                          "example": [
                            "The selected status.0 is invalid."
                          ],
                          "items": {
                            "description": "Позиции (товары) объекта.",
                            "x-description-kk": "Нысан позициялары (тауарлар).",
                            "x-description-en": "Line items (products) of the object.",
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Возвраты"
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "array",
                    "description": "",
                    "example": null,
                    "items": {
                      "type": "string"
                    }
                  },
                  "invoice_id": {
                    "type": "integer",
                    "description": "The <code>id</code> of an existing record in the invoices table.",
                    "x-description-kk": "invoices кестесіндегі бар жазбаның <code>id</code>-і.",
                    "x-description-en": "The <code>id</code> of an existing record in the invoices table.",
                    "example": 17,
                    "nullable": true
                  },
                  "date_from": {
                    "type": "string",
                    "description": "Must be a valid date. Must be a valid date in the format <code>Y-m-d</code>.",
                    "x-description-kk": "Жарамды күн болуы керек. <code>Y-m-d</code> форматындағы жарамды күн болуы керек.",
                    "x-description-en": "Must be a valid date in the format <code>Y-m-d</code>.",
                    "example": "2026-04-07",
                    "nullable": true
                  },
                  "date_to": {
                    "type": "string",
                    "description": "Must be a valid date. Must be a valid date in the format <code>Y-m-d</code>. Must be a date after or equal to <code>date_from</code>.",
                    "x-description-kk": "Жарамды күн болуы керек. <code>Y-m-d</code> форматында болуы керек. <code>date_from</code>-тан кейінгі немесе оған тең күн болуы керек.",
                    "x-description-en": "Must be a valid date in the format <code>Y-m-d</code>, on or after <code>date_from</code>.",
                    "example": "2107-05-07",
                    "nullable": true
                  },
                  "per_page": {
                    "type": "integer",
                    "description": "Must be at least 1. Must not be greater than 100.",
                    "x-description-kk": "Кемінде 1 болуы керек. 100-ден аспауы керек.",
                    "x-description-en": "Must be at least 1 and at most 100.",
                    "example": 13,
                    "nullable": true
                  }
                }
              }
            }
          }
        }
      }
    },
    "/catalog/units": {
      "get": {
        "summary": "Список единиц измерения",
        "operationId": "",
        "description": "Возвращает список доступных единиц измерения для товаров каталога (шт, кг, л и т.д.).",
        "parameters": [
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "data": [
                      {
                        "id": 1,
                        "name": "шт",
                        "name_kaz": "дана"
                      },
                      {
                        "id": 2,
                        "name": "кг",
                        "name_kaz": "кг"
                      }
                    ]
                  },
                  "properties": {
                    "data": {
                      "description": "Массив записей результата.",
                      "x-description-kk": "Нәтиже жазбаларының массиві.",
                      "x-description-en": "Array of result records.",
                      "type": "array",
                      "example": [
                        {
                          "id": 1,
                          "name": "шт",
                          "name_kaz": "дана"
                        },
                        {
                          "id": 2,
                          "name": "кг",
                          "name_kaz": "кг"
                        }
                      ],
                      "items": {
                        "description": "Позиции (товары) объекта.",
                        "x-description-kk": "Нысан позициялары (тауарлар).",
                        "x-description-en": "Line items (products) of the object.",
                        "type": "object",
                        "properties": {
                          "id": {
                            "description": "ID записи.",
                            "x-description-kk": "Жазбаның ID-і.",
                            "x-description-en": "Record ID.",
                            "type": "integer",
                            "example": 1
                          },
                          "name": {
                            "description": "Название.",
                            "x-description-kk": "Атауы.",
                            "x-description-en": "Name.",
                            "type": "string",
                            "example": "шт"
                          },
                          "name_kaz": {
                            "description": "Название на казахском языке.",
                            "x-description-kk": "Қазақ тіліндегі атауы.",
                            "x-description-en": "Name in Kazakh.",
                            "type": "string",
                            "example": "дана"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Каталог"
        ]
      }
    },
    "/catalog": {
      "get": {
        "summary": "Список товаров каталога",
        "operationId": "",
        "description": "Возвращает пагинированный список товаров каталога организации. Поддерживает поиск и фильтрацию.",
        "parameters": [
          {
            "in": "query",
            "name": "search",
            "description": "Поиск по названию товара.",
            "x-description-kk": "Тауар атауы бойынша іздеу.",
            "x-description-en": "Search by product name.",
            "example": "Кофе",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Поиск по названию товара.",
              "x-description-kk": "Тауар атауы бойынша іздеу.",
              "x-description-en": "Search by product name.",
              "example": "Кофе"
            }
          },
          {
            "in": "query",
            "name": "barcode",
            "description": "Фильтр по штрихкоду.",
            "x-description-kk": "Штрихкод бойынша сүзу.",
            "x-description-en": "Filter by barcode.",
            "example": "4607001234567",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Фильтр по штрихкоду.",
              "x-description-kk": "Штрихкод бойынша сүзу.",
              "x-description-en": "Filter by barcode.",
              "example": "4607001234567"
            }
          },
          {
            "in": "query",
            "name": "first_char",
            "description": "Фильтр по первой букве названия.",
            "x-description-kk": "Атаудың бірінші әрпі бойынша сүзу.",
            "x-description-en": "Filter by the first letter of the name.",
            "example": "К",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Фильтр по первой букве названия.",
              "x-description-kk": "Атаудың бірінші әрпі бойынша сүзу.",
              "x-description-en": "Filter by the first letter of the name.",
              "example": "К"
            }
          },
          {
            "in": "query",
            "name": "statuses[]",
            "description": "Фильтр по статусам товара (можно несколько). Допустимо: active, pending, deleting, failed.",
            "x-description-kk": "Тауар мәртебелері бойынша сүзу (бірнешеуі болуы мүмкін). Рұқсат етілген: active, pending, deleting, failed.",
            "x-description-en": "Filter by product statuses (multiple allowed). Allowed: active, pending, deleting, failed.",
            "example": "active",
            "required": false,
            "schema": {
              "type": "array",
              "description": "Фильтр по статусам товара (можно несколько). Допустимо: active, pending, deleting, failed.",
              "x-description-kk": "Тауар мәртебелері бойынша сүзу (бірнешеуі болуы мүмкін). Рұқсат етілген: active, pending, deleting, failed.",
              "x-description-en": "Filter by product statuses (multiple allowed). Allowed: active, pending, deleting, failed.",
              "items": {
                "type": "string",
                "enum": [
                  "active",
                  "pending",
                  "deleting",
                  "failed"
                ]
              },
              "example": [
                "active"
              ]
            }
          },
          {
            "in": "query",
            "name": "per_page",
            "description": "Кол-во на страницу (1-200, по умолчанию 50).",
            "x-description-kk": "Бір беттегі саны (1-200, әдепкіде 50).",
            "x-description-en": "Items per page (1-200, default 50).",
            "example": 50,
            "required": false,
            "schema": {
              "type": "integer",
              "description": "Кол-во на страницу (1-200, по умолчанию 50).",
              "x-description-kk": "Бір беттегі саны (1-200, әдепкіде 50).",
              "x-description-en": "Items per page (1-200, default 50).",
              "example": 50
            }
          },
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "data": [
                      {
                        "id": 1,
                        "kaspi_item_id": null,
                        "name": "Кофе",
                        "unit_id": 1,
                        "selling_price": "1500.00",
                        "date_added": null,
                        "image_url": null,
                        "first_char": "К",
                        "nds_percentage": null,
                        "barcode": "4607001234567",
                        "ntin": null,
                        "status": "active",
                        "error_message": null,
                        "created_at": "2026-02-26T10:00:00+06:00",
                        "synced_at": "2026-02-26T10:00:00+06:00"
                      }
                    ],
                    "links": {},
                    "meta": {}
                  },
                  "properties": {
                    "data": {
                      "description": "Массив записей результата.",
                      "x-description-kk": "Нәтиже жазбаларының массиві.",
                      "x-description-en": "Array of result records.",
                      "type": "array",
                      "example": [
                        {
                          "id": 1,
                          "kaspi_item_id": null,
                          "name": "Кофе",
                          "unit_id": 1,
                          "selling_price": "1500.00",
                          "date_added": null,
                          "image_url": null,
                          "first_char": "К",
                          "nds_percentage": null,
                          "barcode": "4607001234567",
                          "ntin": null,
                          "status": "active",
                          "error_message": null,
                          "created_at": "2026-02-26T10:00:00+06:00",
                          "synced_at": "2026-02-26T10:00:00+06:00"
                        }
                      ],
                      "items": {
                        "description": "Позиции (товары) объекта.",
                        "x-description-kk": "Нысан позициялары (тауарлар).",
                        "x-description-en": "Line items (products) of the object.",
                        "type": "object",
                        "properties": {
                          "id": {
                            "description": "ID записи.",
                            "x-description-kk": "Жазбаның ID-і.",
                            "x-description-en": "Record ID.",
                            "type": "integer",
                            "example": 1
                          },
                          "kaspi_item_id": {
                            "description": "ID товара в системе Kaspi (null до синхронизации).",
                            "x-description-kk": "Kaspi жүйесіндегі тауар ID-і (синхрондауға дейін null).",
                            "x-description-en": "Item ID in the Kaspi system (null until synced).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "name": {
                            "description": "Название.",
                            "x-description-kk": "Атауы.",
                            "x-description-en": "Name.",
                            "type": "string",
                            "example": "Кофе"
                          },
                          "unit_id": {
                            "description": "ID единицы измерения.",
                            "x-description-kk": "Өлшем бірлігінің ID-і.",
                            "x-description-en": "Unit of measure ID.",
                            "type": "integer",
                            "example": 1
                          },
                          "selling_price": {
                            "description": "Цена продажи.",
                            "x-description-kk": "Сату бағасы.",
                            "x-description-en": "Selling price.",
                            "type": "string",
                            "example": "1500.00"
                          },
                          "date_added": {
                            "description": "Дата добавления (может быть null).",
                            "x-description-kk": "Қосылған күні (null болуы мүмкін).",
                            "x-description-en": "Date added (may be null).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "image_url": {
                            "description": "URL изображения товара (может быть null).",
                            "x-description-kk": "Тауар суретінің URL-і (null болуы мүмкін).",
                            "x-description-en": "Product image URL (may be null).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "first_char": {
                            "description": "Первая буква названия (для группировки).",
                            "x-description-kk": "Атаудың бірінші әрпі (топтау үшін).",
                            "x-description-en": "First letter of the name (for grouping).",
                            "type": "string",
                            "example": "К"
                          },
                          "nds_percentage": {
                            "description": "Процент НДС (может быть null).",
                            "x-description-kk": "ҚҚС пайызы (null болуы мүмкін).",
                            "x-description-en": "VAT percentage (may be null).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "barcode": {
                            "description": "Штрихкод товара.",
                            "x-description-kk": "Тауардың штрихкоды.",
                            "x-description-en": "Product barcode.",
                            "type": "string",
                            "example": "4607001234567"
                          },
                          "ntin": {
                            "description": "Код NTIN/маркировки (может быть null).",
                            "x-description-kk": "NTIN/таңбалау коды (null болуы мүмкін).",
                            "x-description-en": "NTIN/marking code (may be null).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "status": {
                            "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                            "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                            "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                            "type": "string",
                            "example": "active"
                          },
                          "error_message": {
                            "description": "Текст ошибки (null если ошибок нет).",
                            "x-description-kk": "Қате мәтіні (қате болмаса null).",
                            "x-description-en": "Error text (null if there is no error).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "created_at": {
                            "description": "Дата и время создания.",
                            "x-description-kk": "Жасалған күні мен уақыты.",
                            "x-description-en": "Date and time of creation.",
                            "type": "string",
                            "example": "2026-02-26T10:00:00+06:00"
                          },
                          "synced_at": {
                            "description": "Дата последней синхронизации с Kaspi.",
                            "x-description-kk": "Kaspi-мен соңғы синхрондау күні.",
                            "x-description-en": "Date of the last sync with Kaspi.",
                            "type": "string",
                            "example": "2026-02-26T10:00:00+06:00"
                          }
                        }
                      }
                    },
                    "links": {
                      "description": "Ссылки пагинации.",
                      "x-description-kk": "Беттеу сілтемелері.",
                      "x-description-en": "Pagination links.",
                      "type": "object",
                      "properties": {}
                    },
                    "meta": {
                      "description": "Метаданные пагинации.",
                      "x-description-kk": "Беттеу метадеректері.",
                      "x-description-en": "Pagination metadata.",
                      "type": "object",
                      "properties": {}
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Каталог"
        ]
      },
      "post": {
        "summary": "Создать товар каталога",
        "operationId": "",
        "description": "Создаёт один или несколько товаров в каталоге организации. Товары сохраняются локально со статусом pending и отправляются в Kaspi API через очередь.",
        "parameters": [
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "data": [
                      {
                        "id": 1,
                        "kaspi_item_id": null,
                        "name": "Кофе Американо",
                        "unit_id": 1,
                        "selling_price": "1500.00",
                        "date_added": null,
                        "image_url": null,
                        "first_char": "К",
                        "nds_percentage": null,
                        "barcode": "4607001234567",
                        "ntin": null,
                        "status": "pending",
                        "error_message": null,
                        "created_at": "2026-02-26T10:00:00+06:00",
                        "synced_at": "2026-02-26T10:00:00+06:00"
                      }
                    ]
                  },
                  "properties": {
                    "data": {
                      "description": "Массив записей результата.",
                      "x-description-kk": "Нәтиже жазбаларының массиві.",
                      "x-description-en": "Array of result records.",
                      "type": "array",
                      "example": [
                        {
                          "id": 1,
                          "kaspi_item_id": null,
                          "name": "Кофе Американо",
                          "unit_id": 1,
                          "selling_price": "1500.00",
                          "date_added": null,
                          "image_url": null,
                          "first_char": "К",
                          "nds_percentage": null,
                          "barcode": "4607001234567",
                          "ntin": null,
                          "status": "pending",
                          "error_message": null,
                          "created_at": "2026-02-26T10:00:00+06:00",
                          "synced_at": "2026-02-26T10:00:00+06:00"
                        }
                      ],
                      "items": {
                        "description": "Позиции (товары) объекта.",
                        "x-description-kk": "Нысан позициялары (тауарлар).",
                        "x-description-en": "Line items (products) of the object.",
                        "type": "object",
                        "properties": {
                          "id": {
                            "description": "ID записи.",
                            "x-description-kk": "Жазбаның ID-і.",
                            "x-description-en": "Record ID.",
                            "type": "integer",
                            "example": 1
                          },
                          "kaspi_item_id": {
                            "description": "ID товара в системе Kaspi (null до синхронизации).",
                            "x-description-kk": "Kaspi жүйесіндегі тауар ID-і (синхрондауға дейін null).",
                            "x-description-en": "Item ID in the Kaspi system (null until synced).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "name": {
                            "description": "Название.",
                            "x-description-kk": "Атауы.",
                            "x-description-en": "Name.",
                            "type": "string",
                            "example": "Кофе Американо"
                          },
                          "unit_id": {
                            "description": "ID единицы измерения.",
                            "x-description-kk": "Өлшем бірлігінің ID-і.",
                            "x-description-en": "Unit of measure ID.",
                            "type": "integer",
                            "example": 1
                          },
                          "selling_price": {
                            "description": "Цена продажи.",
                            "x-description-kk": "Сату бағасы.",
                            "x-description-en": "Selling price.",
                            "type": "string",
                            "example": "1500.00"
                          },
                          "date_added": {
                            "description": "Дата добавления (может быть null).",
                            "x-description-kk": "Қосылған күні (null болуы мүмкін).",
                            "x-description-en": "Date added (may be null).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "image_url": {
                            "description": "URL изображения товара (может быть null).",
                            "x-description-kk": "Тауар суретінің URL-і (null болуы мүмкін).",
                            "x-description-en": "Product image URL (may be null).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "first_char": {
                            "description": "Первая буква названия (для группировки).",
                            "x-description-kk": "Атаудың бірінші әрпі (топтау үшін).",
                            "x-description-en": "First letter of the name (for grouping).",
                            "type": "string",
                            "example": "К"
                          },
                          "nds_percentage": {
                            "description": "Процент НДС (может быть null).",
                            "x-description-kk": "ҚҚС пайызы (null болуы мүмкін).",
                            "x-description-en": "VAT percentage (may be null).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "barcode": {
                            "description": "Штрихкод товара.",
                            "x-description-kk": "Тауардың штрихкоды.",
                            "x-description-en": "Product barcode.",
                            "type": "string",
                            "example": "4607001234567"
                          },
                          "ntin": {
                            "description": "Код NTIN/маркировки (может быть null).",
                            "x-description-kk": "NTIN/таңбалау коды (null болуы мүмкін).",
                            "x-description-en": "NTIN/marking code (may be null).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "status": {
                            "description": "Статус. Для счёта: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Для возврата: pending, processing, completed, failed. Для подписки: active, paused, cancelled, completed, expired. Для товара каталога: pending, active, error.",
                            "x-description-kk": "Мәртебе. Шот үшін: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. Қайтару үшін: pending, processing, completed, failed. Жазылым үшін: active, paused, cancelled, completed, expired. Каталог тауары үшін: pending, active, error.",
                            "x-description-en": "Status. For an invoice: pending, processing, cancelling, paid, cancelled, expired, error, partially_refunded. For a refund: pending, processing, completed, failed. For a subscription: active, paused, cancelled, completed, expired. For a catalog item: pending, active, error.",
                            "type": "string",
                            "example": "pending"
                          },
                          "error_message": {
                            "description": "Текст ошибки (null если ошибок нет).",
                            "x-description-kk": "Қате мәтіні (қате болмаса null).",
                            "x-description-en": "Error text (null if there is no error).",
                            "type": "string",
                            "example": null,
                            "nullable": true
                          },
                          "created_at": {
                            "description": "Дата и время создания.",
                            "x-description-kk": "Жасалған күні мен уақыты.",
                            "x-description-en": "Date and time of creation.",
                            "type": "string",
                            "example": "2026-02-26T10:00:00+06:00"
                          },
                          "synced_at": {
                            "description": "Дата последней синхронизации с Kaspi.",
                            "x-description-kk": "Kaspi-мен соңғы синхрондау күні.",
                            "x-description-en": "Date of the last sync with Kaspi.",
                            "type": "string",
                            "example": "2026-02-26T10:00:00+06:00"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Ошибка валидации",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "message": "Validation failed",
                    "errors": {
                      "items": [
                        "The items field is required."
                      ]
                    }
                  },
                  "properties": {
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Validation failed"
                    },
                    "errors": {
                      "type": "object",
                      "properties": {
                        "items": {
                          "description": "Позиции (товары) объекта.",
                          "x-description-kk": "Нысан позициялары (тауарлар).",
                          "x-description-en": "Line items (products) of the object.",
                          "type": "array",
                          "example": [
                            "The items field is required."
                          ],
                          "items": {
                            "description": "Позиции (товары) объекта.",
                            "x-description-kk": "Нысан позициялары (тауарлар).",
                            "x-description-en": "Line items (products) of the object.",
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Каталог"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "items": {
                    "type": "array",
                    "description": "Массив товаров (макс. 50).",
                    "x-description-kk": "Тауарлар массиві (макс. 50).",
                    "x-description-en": "Array of products (max 50).",
                    "example": [
                      []
                    ],
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Название товара.",
                          "x-description-kk": "Тауар атауы.",
                          "x-description-en": "Product name.",
                          "example": "Кофе Американо"
                        },
                        "selling_price": {
                          "type": "number",
                          "description": "Цена продажи.",
                          "x-description-kk": "Сату бағасы.",
                          "x-description-en": "Selling price.",
                          "example": 1500
                        },
                        "unit_id": {
                          "type": "integer",
                          "description": "ID единицы измерения.",
                          "x-description-kk": "Өлшем бірлігінің ID-і.",
                          "x-description-en": "Unit of measure ID.",
                          "example": 1
                        },
                        "image_id": {
                          "type": "string",
                          "description": "UUID изображения, полученный из upload-image.",
                          "x-description-kk": "upload-image-ден алынған сурет UUID-і.",
                          "x-description-en": "Image UUID obtained from upload-image.",
                          "example": "abc123",
                          "nullable": true
                        },
                        "barcode": {
                          "type": "string",
                          "description": "Штрихкод товара.",
                          "x-description-kk": "Тауардың штрихкоды.",
                          "x-description-en": "Product barcode.",
                          "example": "4607001234567",
                          "nullable": true
                        }
                      },
                      "required": [
                        "name",
                        "selling_price",
                        "unit_id"
                      ]
                    }
                  }
                },
                "required": [
                  "items"
                ]
              }
            }
          }
        }
      }
    },
    "/catalog/upload-image": {
      "post": {
        "summary": "Загрузить изображение для каталога",
        "operationId": "",
        "description": "Загружает и оптимизирует изображение товара. Использует MD5 дедупликацию — повторная загрузка того же изображения вернёт существующий image_id.",
        "parameters": [
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "image_id": "abc123"
                  },
                  "properties": {
                    "image_id": {
                      "description": "UUID изображения.",
                      "x-description-kk": "Сурет UUID-і.",
                      "x-description-en": "Image UUID.",
                      "type": "string",
                      "example": "abc123"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Ошибка валидации",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "message": "Validation failed",
                    "errors": {
                      "image": [
                        "The image field is required."
                      ]
                    }
                  },
                  "properties": {
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Validation failed"
                    },
                    "errors": {
                      "type": "object",
                      "properties": {
                        "image": {
                          "type": "array",
                          "example": [
                            "The image field is required."
                          ],
                          "items": {
                            "description": "Позиции (товары) объекта.",
                            "x-description-kk": "Нысан позициялары (тауарлар).",
                            "x-description-en": "Line items (products) of the object.",
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Каталог"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "image": {
                    "type": "string",
                    "format": "binary",
                    "description": "Изображение товара (jpeg/png/webp, макс. 2 МБ).",
                    "x-description-kk": "Тауар суреті (jpeg/png/webp, макс. 2 МБ).",
                    "x-description-en": "Product image (jpeg/png/webp, max 2 MB)."
                  }
                },
                "required": [
                  "image"
                ]
              }
            }
          }
        }
      }
    },
    "/catalog/{id}": {
      "patch": {
        "summary": "Обновить товар каталога",
        "operationId": "",
        "description": "Обновляет данные товара каталога. Локальные поля обновляются сразу, изменения в Kaspi API отправляются через очередь.",
        "parameters": [
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "message": "Catalog item update queued",
                    "catalog_item_id": 1
                  },
                  "properties": {
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Catalog item update queued"
                    },
                    "catalog_item_id": {
                      "description": "ID товара каталога.",
                      "x-description-kk": "Каталог тауарының ID-і.",
                      "x-description-en": "Catalog item ID.",
                      "type": "integer",
                      "example": 1
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "Catalog item not found"
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Catalog item not found"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Ошибка валидации",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "message": "Validation failed",
                    "errors": {
                      "selling_price": [
                        "The selling price must be at least 0.01."
                      ]
                    }
                  },
                  "properties": {
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Validation failed"
                    },
                    "errors": {
                      "type": "object",
                      "properties": {
                        "selling_price": {
                          "description": "Цена продажи.",
                          "x-description-kk": "Сату бағасы.",
                          "x-description-en": "Selling price.",
                          "type": "array",
                          "example": [
                            "The selling price must be at least 0.01."
                          ],
                          "items": {
                            "description": "Позиции (товары) объекта.",
                            "x-description-kk": "Нысан позициялары (тауарлар).",
                            "x-description-en": "Line items (products) of the object.",
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Каталог"
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Название товара.",
                    "x-description-kk": "Тауар атауы.",
                    "x-description-en": "Product name.",
                    "example": "Кофе Латте",
                    "nullable": true
                  },
                  "selling_price": {
                    "type": "number",
                    "description": "Цена продажи.",
                    "x-description-kk": "Сату бағасы.",
                    "x-description-en": "Selling price.",
                    "example": 1800,
                    "nullable": true
                  },
                  "unit_id": {
                    "type": "integer",
                    "description": "ID единицы измерения.",
                    "x-description-kk": "Өлшем бірлігінің ID-і.",
                    "x-description-en": "Unit of measure ID.",
                    "example": 1,
                    "nullable": true
                  },
                  "image_id": {
                    "type": "string",
                    "description": "UUID нового изображения.",
                    "x-description-kk": "Жаңа суреттің UUID-і.",
                    "x-description-en": "UUID of the new image.",
                    "example": "abc123",
                    "nullable": true
                  },
                  "is_image_deleted": {
                    "type": "boolean",
                    "description": "Удалить текущее изображение.",
                    "x-description-kk": "Ағымдағы суретті жою.",
                    "x-description-en": "Delete the current image.",
                    "example": false,
                    "nullable": true
                  },
                  "barcode": {
                    "type": "string",
                    "description": "Штрихкод товара.",
                    "x-description-kk": "Тауардың штрихкоды.",
                    "x-description-en": "Product barcode.",
                    "example": "4607001234567",
                    "nullable": true
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Удалить товар каталога",
        "operationId": "",
        "description": "Помечает товар как удаляемый и отправляет запрос на удаление в Kaspi API через очередь.",
        "parameters": [
          {
            "in": "header",
            "name": "X-API-Key",
            "description": "",
            "example": "string required API ключ.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "message": "Catalog item deletion queued",
                    "catalog_item_id": 1
                  },
                  "properties": {
                    "message": {
                      "description": "Текстовое сообщение о результате операции.",
                      "x-description-kk": "Операция нәтижесі туралы мәтіндік хабарлама.",
                      "x-description-en": "Text message describing the operation result.",
                      "type": "string",
                      "example": "Catalog item deletion queued"
                    },
                    "catalog_item_id": {
                      "description": "ID товара каталога.",
                      "x-description-kk": "Каталог тауарының ID-і.",
                      "x-description-en": "Catalog item ID.",
                      "type": "integer",
                      "example": 1
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "example": {
                    "error": "Catalog item not found"
                  },
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "Catalog item not found"
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Public API / Каталог"
        ]
      },
      "parameters": [
        {
          "in": "path",
          "name": "id",
          "description": "ID товара каталога.",
          "example": 1,
          "required": true,
          "schema": {
            "type": "integer"
          }
        }
      ]
    }
  },
  "x-webhooks": {
    "invoice.status_changed": {
      "example": {
        "event": "invoice.status_changed",
        "invoice": {
          "id": 42,
          "external_order_id": "order_123",
          "amount": "15000.00",
          "subtotal": "16500.00",
          "discount_sum": "1500.00",
          "discount_percentage": "10",
          "status": "paid",
          "description": "Оплата заказа",
          "kaspi_invoice_id": "13234689513",
          "client_name": "Иван Иванов",
          "client_phone": "87071234567",
          "is_sandbox": false,
          "kaspi_source_type": "GOLD",
          "kaspi_sale_type": "Remote",
          "paid_at": "2026-02-12T14:35:00+00:00"
        },
        "source": "My API Key",
        "timestamp": "2026-02-12T14:35:01+00:00"
      },
      "description": "Статус счёта изменился (например, счёт оплачен или истёк).",
      "fields": [
        {
          "name": "event",
          "type": "string",
          "nullable": false,
          "description": "Тип события — invoice.status_changed."
        },
        {
          "name": "invoice.id",
          "type": "integer",
          "nullable": false,
          "description": "Внутренний ID счёта в ApiPay."
        },
        {
          "name": "invoice.external_order_id",
          "type": "string",
          "nullable": true,
          "description": "Ваш внешний идентификатор заказа, переданный при создании счёта."
        },
        {
          "name": "invoice.amount",
          "type": "string",
          "nullable": false,
          "description": "Сумма счёта."
        },
        {
          "name": "invoice.subtotal",
          "type": "string",
          "nullable": true,
          "description": "Сумма до применения скидки. Только для счетов с корзиной/скидкой (subtotal и discount_sum приходят вместе)."
        },
        {
          "name": "invoice.discount_sum",
          "type": "string",
          "nullable": true,
          "description": "Сумма скидки. Только для счетов с корзиной/скидкой (subtotal и discount_sum приходят вместе)."
        },
        {
          "name": "invoice.discount_percentage",
          "type": "string",
          "nullable": true,
          "description": "Процент скидки. Только для счетов с корзиной/скидкой."
        },
        {
          "name": "invoice.status",
          "type": "string",
          "nullable": false,
          "description": "Статус счёта: pending / paid / cancelled / expired / error / partially_refunded. Статуса refunded не существует — полный возврат оставляет paid + is_fully_refunded=true."
        },
        {
          "name": "invoice.kaspi_invoice_id",
          "type": "string",
          "nullable": true,
          "description": "ID счёта в Kaspi. Появляется уже при pending (когда счёт создан в Kaspi); null — пока счёт не дошёл до Kaspi."
        },
        {
          "name": "invoice.client_phone",
          "type": "string",
          "nullable": false,
          "description": "Номер телефона клиента."
        },
        {
          "name": "invoice.kaspi_source_type",
          "type": "string",
          "nullable": true,
          "description": "Источник средств клиента: GOLD — дебетовая карта Kaspi, RED — кредитная карта Kaspi, LOAN — рассрочка/кредит, BUSINESSACCOUNT — бизнес-счёт, BANKINTEGRATIONACCOUNT — привязанный внешний банковский счёт. Обычно присутствует при status=paid, но гейтится по наличию значения, а не строго по статусу: поле приходит, когда Kaspi вернул значение (например, счёт, уже получивший его, может пробросить поле и в статусах cancelled/expired), и отсутствует/null иначе. Может отсутствовать для старых счетов; список может расширяться — обрабатывайте неизвестные значения как «прочее»."
        },
        {
          "name": "invoice.kaspi_sale_type",
          "type": "string",
          "nullable": true,
          "description": "Способ приёма счёта: Remote — push на номер, QR — QR-код, Restaurant — ресторанный счёт, Static — статичный QR. Обычно присутствует при status=paid, но гейтится по наличию значения, а не строго по статусу: поле приходит, когда Kaspi вернул значение (например, счёт, уже получивший его, может пробросить поле и в статусах cancelled/expired), и отсутствует/null иначе. Может отсутствовать для старых счетов; список может расширяться — обрабатывайте неизвестные значения как «прочее»."
        },
        {
          "name": "invoice.paid_at",
          "type": "string",
          "nullable": true,
          "description": "Время оплаты счёта (ISO 8601). Поле отсутствует во всех статусах, кроме paid (а не null до оплаты)."
        },
        {
          "name": "invoice.error_message",
          "type": "string",
          "nullable": true,
          "description": "Человекочитаемая причина. При status=error присутствует всегда; при status=cancelled — только если заполнена (обычно отсутствует при отмене клиентом или через API). В статусах paid/pending/expired поле отсутствует."
        },
        {
          "name": "invoice.error_code",
          "type": "string",
          "nullable": true,
          "description": "Стабильный snake_case-код из каталога (раздел \"Коды ошибок\"). Присутствует только если не null и только при status=error/cancelled. Стройте switch-логику по нему, а не по тексту."
        },
        {
          "name": "invoice.cancelled_at",
          "type": "string",
          "nullable": true,
          "description": "Время перехода в cancelled (ISO 8601). Присутствует только при соответствующем статусе."
        },
        {
          "name": "invoice.expired_at",
          "type": "string",
          "nullable": true,
          "description": "Время перехода в expired (ISO 8601). Присутствует только при соответствующем статусе."
        },
        {
          "name": "invoice.errored_at",
          "type": "string",
          "nullable": true,
          "description": "Время перехода в error (ISO 8601). Присутствует только при соответствующем статусе."
        },
        {
          "name": "source",
          "type": "string",
          "nullable": true,
          "description": "Название API-ключа, через который создан счёт."
        },
        {
          "name": "timestamp",
          "type": "string",
          "nullable": false,
          "description": "Время отправки события (ISO 8601)."
        }
      ]
    },
    "invoice.qr_scanned": {
      "example": {
        "event": "invoice.qr_scanned",
        "invoice": {
          "id": 108565,
          "external_order_id": "order-123",
          "amount": "1500.00",
          "status": "pending",
          "qr_substate": "scanned",
          "description": "Оплата заказа",
          "kaspi_invoice_id": "15977100656",
          "client_name": null,
          "client_phone": null,
          "is_sandbox": false
        },
        "source": "My API Key",
        "timestamp": "2026-06-14T14:37:00+00:00"
      },
      "description": "Клиент отсканировал QR-счёт и находится на экране оплаты Kaspi. Это НЕ смена статуса — суб-состояние счёта (status остаётся pending). Событие аддитивное и шлётся ровно один раз на QR-счёт; оно транзиентно — после него штатно приходит paid (клиент оплатил) или cancelled (клиент свернул/закрыл приложение). Отличайте событие по event=invoice.qr_scanned и/или маркеру qr_substate=scanned; не считайте скан гарантией оплаты.",
      "fields": [
        {
          "name": "event",
          "type": "string",
          "nullable": false,
          "description": "Тип события — invoice.qr_scanned."
        },
        {
          "name": "invoice.id",
          "type": "integer",
          "nullable": false,
          "description": "Внутренний ID счёта в ApiPay."
        },
        {
          "name": "invoice.external_order_id",
          "type": "string",
          "nullable": true,
          "description": "Ваш внешний идентификатор заказа, переданный при создании счёта."
        },
        {
          "name": "invoice.amount",
          "type": "string",
          "nullable": false,
          "description": "Сумма счёта в тенге."
        },
        {
          "name": "invoice.status",
          "type": "string",
          "nullable": false,
          "description": "Всегда pending — qr_scanned не меняет статус, а сообщает о суб-состоянии «на экране оплаты»."
        },
        {
          "name": "invoice.qr_substate",
          "type": "string",
          "nullable": false,
          "description": "Маркер суб-состояния QR — scanned (клиент отсканировал QR и на экране оплаты)."
        },
        {
          "name": "invoice.description",
          "type": "string",
          "nullable": true,
          "description": "Описание счёта."
        },
        {
          "name": "invoice.kaspi_invoice_id",
          "type": "string",
          "nullable": true,
          "description": "ID счёта в Kaspi."
        },
        {
          "name": "invoice.client_name",
          "type": "string",
          "nullable": true,
          "description": "Имя клиента (для QR-счёта обычно null)."
        },
        {
          "name": "invoice.client_phone",
          "type": "string",
          "nullable": true,
          "description": "Телефон клиента (для QR-счёта обычно null)."
        },
        {
          "name": "invoice.is_sandbox",
          "type": "boolean",
          "nullable": false,
          "description": "Признак sandbox-счёта."
        },
        {
          "name": "source",
          "type": "string",
          "nullable": true,
          "description": "Название API-ключа, через который создан счёт."
        },
        {
          "name": "timestamp",
          "type": "string",
          "nullable": false,
          "description": "Время отправки события (ISO 8601, UTC)."
        }
      ]
    },
    "invoice.refunded": {
      "example": {
        "event": "invoice.refunded",
        "refund": {
          "id": 5,
          "amount": "2000.00",
          "status": "completed",
          "kaspi_refund_id": "1126827352",
          "reason": "Возврат товара",
          "created_at": "2026-02-12T10:00:00+00:00",
          "items": [
            {
              "catalog_item_id": 12,
              "name": "Кофе",
              "price": "1000.00",
              "count": 2,
              "amount": "2000.00"
            }
          ]
        },
        "invoice": {
          "id": 42,
          "external_order_id": "order_123",
          "amount": "5000.00",
          "subtotal": "5500.00",
          "discount_sum": "500.00",
          "total_refunded": "2000.00",
          "available_for_refund": 3000,
          "is_fully_refunded": false,
          "is_sandbox": false,
          "status": "paid",
          "kaspi_invoice_id": "13234689513"
        },
        "source": "My API Key",
        "timestamp": "2026-02-12T10:00:01+00:00"
      },
      "description": "По счёту выполнен возврат (полный или частичный).",
      "fields": [
        {
          "name": "event",
          "type": "string",
          "nullable": false,
          "description": "Тип события — invoice.refunded."
        },
        {
          "name": "refund.id",
          "type": "integer",
          "nullable": false,
          "description": "ID возврата."
        },
        {
          "name": "refund.amount",
          "type": "string",
          "nullable": false,
          "description": "Сумма возврата."
        },
        {
          "name": "refund.status",
          "type": "string",
          "nullable": false,
          "description": "pending / processing / completed / failed. Вебхук приходит на completed И на failed."
        },
        {
          "name": "refund.kaspi_refund_id",
          "type": "string",
          "nullable": true,
          "description": "ID возврата в Kaspi; null при неудаче."
        },
        {
          "name": "refund.reason",
          "type": "string",
          "nullable": true,
          "description": "Причина возврата."
        },
        {
          "name": "refund.created_at",
          "type": "string",
          "nullable": false,
          "description": "Время создания возврата (ISO 8601)."
        },
        {
          "name": "refund.error_code",
          "type": "string",
          "nullable": true,
          "description": "Только при status=failed. Например refund_window_expired — истёк срок возврата (~14 дней). Поля error_message в вебхуке нет by design — текст смотрите в GET /invoices/{id}/refunds или резолвите код по каталогу."
        },
        {
          "name": "refund.items",
          "type": "array",
          "nullable": true,
          "description": "Позиции возврата (только для позиционных возвратов): catalog_item_id, name, price, count, amount."
        },
        {
          "name": "invoice.id",
          "type": "integer",
          "nullable": false,
          "description": "Внутренний ID счёта в ApiPay."
        },
        {
          "name": "invoice.external_order_id",
          "type": "string",
          "nullable": true,
          "description": "Ваш внешний идентификатор заказа."
        },
        {
          "name": "invoice.amount",
          "type": "string",
          "nullable": false,
          "description": "Сумма счёта."
        },
        {
          "name": "invoice.subtotal",
          "type": "string",
          "nullable": false,
          "description": "Сумма счёта до применения скидки."
        },
        {
          "name": "invoice.discount_sum",
          "type": "string",
          "nullable": false,
          "description": "Сумма скидки по счёту."
        },
        {
          "name": "invoice.total_refunded",
          "type": "string",
          "nullable": false,
          "description": "Суммарно возвращено по счёту на текущий момент."
        },
        {
          "name": "invoice.available_for_refund",
          "type": "number",
          "nullable": false,
          "description": "Сумма, ещё доступная для возврата. Приходит числом (float), в отличие от amount и total_refunded, которые передаются строками."
        },
        {
          "name": "invoice.is_fully_refunded",
          "type": "boolean",
          "nullable": false,
          "description": "true, если счёт возвращён полностью."
        },
        {
          "name": "invoice.is_sandbox",
          "type": "boolean",
          "nullable": false,
          "description": "Счёт создан в sandbox-режиме."
        },
        {
          "name": "invoice.status",
          "type": "string",
          "nullable": false,
          "description": "Статус счёта после возврата. Полный возврат статус НЕ меняет (остаётся paid — или partially_refunded, если ранее был частичный) + is_fully_refunded=true; первый частичный переводит в partially_refunded (и дополнительно приходит invoice.status_changed)."
        },
        {
          "name": "invoice.kaspi_invoice_id",
          "type": "string",
          "nullable": true,
          "description": "ID счёта в Kaspi."
        },
        {
          "name": "source",
          "type": "string",
          "nullable": true,
          "description": "Название API-ключа."
        },
        {
          "name": "timestamp",
          "type": "string",
          "nullable": false,
          "description": "Время отправки события (ISO 8601)."
        }
      ]
    },
    "subscription.payment_succeeded": {
      "example": {
        "event": "subscription.payment_succeeded",
        "subscription": {
          "id": 10,
          "external_subscriber_id": "CLIENT-001",
          "phone_number": "87071234567",
          "subscriber_name": "Иван Иванов",
          "amount": "5000.00",
          "billing_period": "monthly",
          "status": "active",
          "next_billing_at": "2026-03-01T00:00:00+00:00",
          "failed_attempts": 0,
          "in_grace_period": false,
          "is_sandbox": false
        },
        "invoice_id": 200,
        "amount": "5000.00",
        "paid_at": "2026-02-01T12:00:00+00:00",
        "source": "My API Key",
        "timestamp": "2026-02-01T12:00:01+00:00"
      },
      "description": "Очередной платёж по подписке прошёл успешно.",
      "fields": [
        {
          "name": "event",
          "type": "string",
          "nullable": false,
          "description": "Тип события — subscription.payment_succeeded."
        },
        {
          "name": "subscription.id",
          "type": "integer",
          "nullable": false,
          "description": "ID подписки."
        },
        {
          "name": "subscription.external_subscriber_id",
          "type": "string",
          "nullable": true,
          "description": "Ваш внешний идентификатор подписчика."
        },
        {
          "name": "subscription.phone_number",
          "type": "string",
          "nullable": false,
          "description": "Номер телефона подписчика."
        },
        {
          "name": "subscription.subscriber_name",
          "type": "string",
          "nullable": true,
          "description": "Имя подписчика."
        },
        {
          "name": "subscription.amount",
          "type": "string",
          "nullable": false,
          "description": "Сумма платежа по подписке."
        },
        {
          "name": "subscription.billing_period",
          "type": "string",
          "nullable": false,
          "description": "Период списания (например, monthly)."
        },
        {
          "name": "subscription.status",
          "type": "string",
          "nullable": false,
          "description": "Статус подписки (например, active)."
        },
        {
          "name": "subscription.next_billing_at",
          "type": "string",
          "nullable": true,
          "description": "Дата следующего списания (ISO 8601)."
        },
        {
          "name": "subscription.failed_attempts",
          "type": "integer",
          "nullable": false,
          "description": "Количество подряд неуспешных попыток списания."
        },
        {
          "name": "subscription.in_grace_period",
          "type": "boolean",
          "nullable": false,
          "description": "Находится ли подписка в льготном периоде."
        },
        {
          "name": "subscription.is_sandbox",
          "type": "boolean",
          "nullable": false,
          "description": "Подписка создана в sandbox-режиме."
        },
        {
          "name": "invoice_id",
          "type": "integer",
          "nullable": false,
          "description": "ID счёта, по которому прошёл платёж."
        },
        {
          "name": "amount",
          "type": "string",
          "nullable": false,
          "description": "Сумма успешного платежа."
        },
        {
          "name": "paid_at",
          "type": "string",
          "nullable": false,
          "description": "Время оплаты (ISO 8601)."
        },
        {
          "name": "source",
          "type": "string",
          "nullable": true,
          "description": "Название API-ключа."
        },
        {
          "name": "timestamp",
          "type": "string",
          "nullable": false,
          "description": "Время отправки события (ISO 8601)."
        }
      ]
    },
    "subscription.payment_failed": {
      "example": {
        "event": "subscription.payment_failed",
        "subscription": {
          "id": 10,
          "phone_number": "87071234567",
          "amount": "5000.00",
          "billing_period": "monthly",
          "status": "active",
          "failed_attempts": 2,
          "in_grace_period": false,
          "is_sandbox": false
        },
        "invoice_id": 201,
        "amount": "5000.00",
        "reason": "Invoice expired",
        "attempt_number": 2,
        "source": "My API Key",
        "timestamp": "2026-02-02T12:00:01+00:00"
      },
      "description": "Очередной платёж по подписке не прошёл.",
      "fields": [
        {
          "name": "event",
          "type": "string",
          "nullable": false,
          "description": "Тип события — subscription.payment_failed."
        },
        {
          "name": "subscription.id",
          "type": "integer",
          "nullable": false,
          "description": "ID подписки."
        },
        {
          "name": "subscription.phone_number",
          "type": "string",
          "nullable": false,
          "description": "Номер телефона подписчика."
        },
        {
          "name": "subscription.amount",
          "type": "string",
          "nullable": false,
          "description": "Сумма платежа по подписке."
        },
        {
          "name": "subscription.billing_period",
          "type": "string",
          "nullable": false,
          "description": "Период списания (например, monthly)."
        },
        {
          "name": "subscription.status",
          "type": "string",
          "nullable": false,
          "description": "Статус подписки (например, active)."
        },
        {
          "name": "subscription.failed_attempts",
          "type": "integer",
          "nullable": false,
          "description": "Количество подряд неуспешных попыток списания."
        },
        {
          "name": "subscription.in_grace_period",
          "type": "boolean",
          "nullable": false,
          "description": "Находится ли подписка в льготном периоде."
        },
        {
          "name": "subscription.is_sandbox",
          "type": "boolean",
          "nullable": false,
          "description": "Подписка создана в sandbox-режиме."
        },
        {
          "name": "invoice_id",
          "type": "integer",
          "nullable": false,
          "description": "ID счёта, по которому не прошёл платёж."
        },
        {
          "name": "amount",
          "type": "string",
          "nullable": false,
          "description": "Сумма неуспешного платежа."
        },
        {
          "name": "reason",
          "type": "string",
          "nullable": true,
          "description": "Причина неуспеха: принимает \"Invoice expired\" или \"Invoice cancelled\"."
        },
        {
          "name": "attempt_number",
          "type": "integer",
          "nullable": false,
          "description": "Номер текущей попытки списания."
        },
        {
          "name": "source",
          "type": "string",
          "nullable": true,
          "description": "Название API-ключа."
        },
        {
          "name": "timestamp",
          "type": "string",
          "nullable": false,
          "description": "Время отправки события (ISO 8601)."
        }
      ]
    },
    "subscription.grace_period_started": {
      "example": {
        "event": "subscription.grace_period_started",
        "subscription": {
          "id": 10,
          "phone_number": "87071234567",
          "amount": "5000.00",
          "status": "active",
          "failed_attempts": 3,
          "in_grace_period": true,
          "is_sandbox": false
        },
        "grace_period_days": 3,
        "expires_at": "2026-02-05T12:00:00+00:00",
        "source": "My API Key",
        "timestamp": "2026-02-02T12:00:01+00:00"
      },
      "description": "Подписка вошла в льготный период после нескольких неуспешных списаний.",
      "fields": [
        {
          "name": "event",
          "type": "string",
          "nullable": false,
          "description": "Тип события — subscription.grace_period_started."
        },
        {
          "name": "subscription.id",
          "type": "integer",
          "nullable": false,
          "description": "ID подписки."
        },
        {
          "name": "subscription.phone_number",
          "type": "string",
          "nullable": false,
          "description": "Номер телефона подписчика."
        },
        {
          "name": "subscription.amount",
          "type": "string",
          "nullable": false,
          "description": "Сумма платежа по подписке."
        },
        {
          "name": "subscription.status",
          "type": "string",
          "nullable": false,
          "description": "Статус подписки (например, active)."
        },
        {
          "name": "subscription.failed_attempts",
          "type": "integer",
          "nullable": false,
          "description": "Количество подряд неуспешных попыток списания."
        },
        {
          "name": "subscription.in_grace_period",
          "type": "boolean",
          "nullable": false,
          "description": "Находится ли подписка в льготном периоде (здесь true)."
        },
        {
          "name": "subscription.is_sandbox",
          "type": "boolean",
          "nullable": false,
          "description": "Подписка создана в sandbox-режиме."
        },
        {
          "name": "grace_period_days",
          "type": "integer",
          "nullable": false,
          "description": "Длительность льготного периода в днях."
        },
        {
          "name": "expires_at",
          "type": "string",
          "nullable": false,
          "description": "Когда истекает льготный период (ISO 8601)."
        },
        {
          "name": "source",
          "type": "string",
          "nullable": true,
          "description": "Название API-ключа."
        },
        {
          "name": "timestamp",
          "type": "string",
          "nullable": false,
          "description": "Время отправки события (ISO 8601)."
        }
      ]
    },
    "subscription.expired": {
      "example": {
        "event": "subscription.expired",
        "subscription": {
          "id": 10,
          "phone_number": "87071234567",
          "amount": "5000.00",
          "status": "expired",
          "next_billing_at": null,
          "failed_attempts": 3,
          "in_grace_period": false,
          "is_sandbox": false
        },
        "source": "My API Key",
        "timestamp": "2026-02-05T12:00:01+00:00"
      },
      "description": "Подписка истекла после исчерпания попыток списания и льготного периода.",
      "fields": [
        {
          "name": "event",
          "type": "string",
          "nullable": false,
          "description": "Тип события — subscription.expired."
        },
        {
          "name": "subscription.id",
          "type": "integer",
          "nullable": false,
          "description": "ID подписки."
        },
        {
          "name": "subscription.phone_number",
          "type": "string",
          "nullable": false,
          "description": "Номер телефона подписчика."
        },
        {
          "name": "subscription.amount",
          "type": "string",
          "nullable": false,
          "description": "Сумма платежа по подписке."
        },
        {
          "name": "subscription.status",
          "type": "string",
          "nullable": false,
          "description": "Статус подписки (здесь expired)."
        },
        {
          "name": "subscription.next_billing_at",
          "type": "string",
          "nullable": true,
          "description": "Дата следующего списания (null для истёкшей подписки)."
        },
        {
          "name": "subscription.failed_attempts",
          "type": "integer",
          "nullable": false,
          "description": "Количество подряд неуспешных попыток списания."
        },
        {
          "name": "subscription.in_grace_period",
          "type": "boolean",
          "nullable": false,
          "description": "Находится ли подписка в льготном периоде."
        },
        {
          "name": "subscription.is_sandbox",
          "type": "boolean",
          "nullable": false,
          "description": "Подписка создана в sandbox-режиме."
        },
        {
          "name": "source",
          "type": "string",
          "nullable": true,
          "description": "Название API-ключа."
        },
        {
          "name": "timestamp",
          "type": "string",
          "nullable": false,
          "description": "Время отправки события (ISO 8601)."
        }
      ]
    },
    "subscription.created": {
      "example": {
        "event": "subscription.created",
        "subscription": {
          "id": 10,
          "external_subscriber_id": "CLIENT-001",
          "phone_number": "87071234567",
          "subscriber_name": "Иван Иванов",
          "amount": "5000.00",
          "billing_period": "monthly",
          "status": "active",
          "next_billing_at": "2026-03-01T00:00:00+00:00",
          "failed_attempts": 0,
          "in_grace_period": false,
          "is_sandbox": false
        },
        "source": "My API Key",
        "timestamp": "2026-02-01T12:00:01+00:00"
      },
      "description": "Подписка создана. Первый счёт будет выставлен в next_billing_at (или сразу, если при создании передан bill_immediately).",
      "fields": [
        {
          "name": "event",
          "type": "string",
          "nullable": false,
          "description": "Тип события — subscription.created."
        },
        {
          "name": "subscription.id",
          "type": "integer",
          "nullable": false,
          "description": "ID подписки."
        },
        {
          "name": "subscription.external_subscriber_id",
          "type": "string",
          "nullable": true,
          "description": "Ваш внешний идентификатор подписчика."
        },
        {
          "name": "subscription.phone_number",
          "type": "string",
          "nullable": false,
          "description": "Номер телефона подписчика."
        },
        {
          "name": "subscription.subscriber_name",
          "type": "string",
          "nullable": true,
          "description": "Имя подписчика."
        },
        {
          "name": "subscription.amount",
          "type": "string",
          "nullable": false,
          "description": "Сумма платежа по подписке."
        },
        {
          "name": "subscription.billing_period",
          "type": "string",
          "nullable": false,
          "description": "Период списания (например, monthly)."
        },
        {
          "name": "subscription.status",
          "type": "string",
          "nullable": false,
          "description": "Статус подписки (здесь active)."
        },
        {
          "name": "subscription.next_billing_at",
          "type": "string",
          "nullable": true,
          "description": "Дата следующего списания (ISO 8601)."
        },
        {
          "name": "subscription.failed_attempts",
          "type": "integer",
          "nullable": false,
          "description": "Количество подряд неуспешных попыток списания."
        },
        {
          "name": "subscription.in_grace_period",
          "type": "boolean",
          "nullable": false,
          "description": "Находится ли подписка в льготном периоде."
        },
        {
          "name": "subscription.is_sandbox",
          "type": "boolean",
          "nullable": false,
          "description": "Подписка создана в sandbox-режиме."
        },
        {
          "name": "source",
          "type": "string",
          "nullable": true,
          "description": "Название API-ключа."
        },
        {
          "name": "timestamp",
          "type": "string",
          "nullable": false,
          "description": "Время отправки события (ISO 8601)."
        }
      ]
    },
    "subscription.paused": {
      "example": {
        "event": "subscription.paused",
        "subscription": {
          "id": 10,
          "external_subscriber_id": "CLIENT-001",
          "phone_number": "87071234567",
          "subscriber_name": "Иван Иванов",
          "amount": "5000.00",
          "billing_period": "monthly",
          "status": "paused",
          "next_billing_at": "2026-03-01T00:00:00+00:00",
          "failed_attempts": 0,
          "in_grace_period": false,
          "is_sandbox": false
        },
        "source": "My API Key",
        "timestamp": "2026-02-10T09:00:00+00:00"
      },
      "description": "Подписка приостановлена. Счета не выставляются до resume.",
      "fields": [
        {
          "name": "event",
          "type": "string",
          "nullable": false,
          "description": "Тип события — subscription.paused."
        },
        {
          "name": "subscription.id",
          "type": "integer",
          "nullable": false,
          "description": "ID подписки."
        },
        {
          "name": "subscription.external_subscriber_id",
          "type": "string",
          "nullable": true,
          "description": "Ваш внешний идентификатор подписчика."
        },
        {
          "name": "subscription.phone_number",
          "type": "string",
          "nullable": false,
          "description": "Номер телефона подписчика."
        },
        {
          "name": "subscription.subscriber_name",
          "type": "string",
          "nullable": true,
          "description": "Имя подписчика."
        },
        {
          "name": "subscription.amount",
          "type": "string",
          "nullable": false,
          "description": "Сумма платежа по подписке."
        },
        {
          "name": "subscription.billing_period",
          "type": "string",
          "nullable": false,
          "description": "Период списания (например, monthly)."
        },
        {
          "name": "subscription.status",
          "type": "string",
          "nullable": false,
          "description": "Статус подписки (здесь paused)."
        },
        {
          "name": "subscription.next_billing_at",
          "type": "string",
          "nullable": true,
          "description": "Дата следующего списания (ISO 8601)."
        },
        {
          "name": "subscription.failed_attempts",
          "type": "integer",
          "nullable": false,
          "description": "Количество подряд неуспешных попыток списания."
        },
        {
          "name": "subscription.in_grace_period",
          "type": "boolean",
          "nullable": false,
          "description": "Находится ли подписка в льготном периоде."
        },
        {
          "name": "subscription.is_sandbox",
          "type": "boolean",
          "nullable": false,
          "description": "Подписка создана в sandbox-режиме."
        },
        {
          "name": "source",
          "type": "string",
          "nullable": true,
          "description": "Название API-ключа."
        },
        {
          "name": "timestamp",
          "type": "string",
          "nullable": false,
          "description": "Время отправки события (ISO 8601)."
        }
      ]
    },
    "subscription.resumed": {
      "example": {
        "event": "subscription.resumed",
        "subscription": {
          "id": 10,
          "external_subscriber_id": "CLIENT-001",
          "phone_number": "87071234567",
          "subscriber_name": "Иван Иванов",
          "amount": "5000.00",
          "billing_period": "monthly",
          "status": "active",
          "next_billing_at": "2026-03-15T09:30:00+00:00",
          "failed_attempts": 0,
          "in_grace_period": false,
          "is_sandbox": false
        },
        "source": "My API Key",
        "timestamp": "2026-02-15T09:30:00+00:00"
      },
      "description": "Подписка возобновлена. next_billing_at пересчитан от момента возобновления — пропущенные периоды не доначисляются.",
      "fields": [
        {
          "name": "event",
          "type": "string",
          "nullable": false,
          "description": "Тип события — subscription.resumed."
        },
        {
          "name": "subscription.id",
          "type": "integer",
          "nullable": false,
          "description": "ID подписки."
        },
        {
          "name": "subscription.external_subscriber_id",
          "type": "string",
          "nullable": true,
          "description": "Ваш внешний идентификатор подписчика."
        },
        {
          "name": "subscription.phone_number",
          "type": "string",
          "nullable": false,
          "description": "Номер телефона подписчика."
        },
        {
          "name": "subscription.subscriber_name",
          "type": "string",
          "nullable": true,
          "description": "Имя подписчика."
        },
        {
          "name": "subscription.amount",
          "type": "string",
          "nullable": false,
          "description": "Сумма платежа по подписке."
        },
        {
          "name": "subscription.billing_period",
          "type": "string",
          "nullable": false,
          "description": "Период списания (например, monthly)."
        },
        {
          "name": "subscription.status",
          "type": "string",
          "nullable": false,
          "description": "Статус подписки (здесь active)."
        },
        {
          "name": "subscription.next_billing_at",
          "type": "string",
          "nullable": true,
          "description": "Дата следующего списания (ISO 8601), пересчитанная от момента возобновления."
        },
        {
          "name": "subscription.failed_attempts",
          "type": "integer",
          "nullable": false,
          "description": "Количество подряд неуспешных попыток списания."
        },
        {
          "name": "subscription.in_grace_period",
          "type": "boolean",
          "nullable": false,
          "description": "Находится ли подписка в льготном периоде."
        },
        {
          "name": "subscription.is_sandbox",
          "type": "boolean",
          "nullable": false,
          "description": "Подписка создана в sandbox-режиме."
        },
        {
          "name": "source",
          "type": "string",
          "nullable": true,
          "description": "Название API-ключа."
        },
        {
          "name": "timestamp",
          "type": "string",
          "nullable": false,
          "description": "Время отправки события (ISO 8601)."
        }
      ]
    },
    "subscription.cancelled": {
      "example": {
        "event": "subscription.cancelled",
        "subscription": {
          "id": 10,
          "external_subscriber_id": "CLIENT-001",
          "phone_number": "87071234567",
          "subscriber_name": "Иван Иванов",
          "amount": "5000.00",
          "billing_period": "monthly",
          "status": "cancelled",
          "next_billing_at": "2026-03-01T00:00:00+00:00",
          "failed_attempts": 0,
          "in_grace_period": false,
          "is_sandbox": false
        },
        "source": "My API Key",
        "timestamp": "2026-02-20T18:00:00+00:00"
      },
      "description": "Подписка отменена безвозвратно. next_billing_at НЕ обнуляется (сохраняет последнее значение; счета больше не выставляются). Для возобновления создайте новую подписку.",
      "fields": [
        {
          "name": "event",
          "type": "string",
          "nullable": false,
          "description": "Тип события — subscription.cancelled."
        },
        {
          "name": "subscription.id",
          "type": "integer",
          "nullable": false,
          "description": "ID подписки."
        },
        {
          "name": "subscription.external_subscriber_id",
          "type": "string",
          "nullable": true,
          "description": "Ваш внешний идентификатор подписчика."
        },
        {
          "name": "subscription.phone_number",
          "type": "string",
          "nullable": false,
          "description": "Номер телефона подписчика."
        },
        {
          "name": "subscription.subscriber_name",
          "type": "string",
          "nullable": true,
          "description": "Имя подписчика."
        },
        {
          "name": "subscription.amount",
          "type": "string",
          "nullable": false,
          "description": "Сумма платежа по подписке."
        },
        {
          "name": "subscription.billing_period",
          "type": "string",
          "nullable": false,
          "description": "Период списания (например, monthly)."
        },
        {
          "name": "subscription.status",
          "type": "string",
          "nullable": false,
          "description": "Статус подписки (здесь cancelled)."
        },
        {
          "name": "subscription.next_billing_at",
          "type": "string",
          "nullable": true,
          "description": "Дата следующего списания (ISO 8601). НЕ обнуляется при отмене — сохраняет последнее значение; счета больше не выставляются."
        },
        {
          "name": "subscription.failed_attempts",
          "type": "integer",
          "nullable": false,
          "description": "Количество подряд неуспешных попыток списания."
        },
        {
          "name": "subscription.in_grace_period",
          "type": "boolean",
          "nullable": false,
          "description": "Находится ли подписка в льготном периоде."
        },
        {
          "name": "subscription.is_sandbox",
          "type": "boolean",
          "nullable": false,
          "description": "Подписка создана в sandbox-режиме."
        },
        {
          "name": "source",
          "type": "string",
          "nullable": true,
          "description": "Название API-ключа."
        },
        {
          "name": "timestamp",
          "type": "string",
          "nullable": false,
          "description": "Время отправки события (ISO 8601)."
        }
      ]
    }
  }
}
