{
  "swagger": "2.0",
  "info": {
    "contact": {},
    "title": "xPayment Developer API",
    "description": "Filtered OpenAPI specification for the public device-level integration surface."
  },
  "paths": {
    "/payments": {
      "get": {
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "description": "Returns a paginated list of payments for the authenticated device API key owner.",
        "produces": [
          "application/json"
        ],
        "tags": [
          "payments"
        ],
        "summary": "List payments",
        "parameters": [
          {
            "type": "string",
            "description": "Filter by status (pending, completed, cancelled, failed)",
            "name": "status",
            "in": "query"
          },
          {
            "type": "string",
            "description": "Filter by payer phone",
            "name": "payer_phone",
            "in": "query"
          },
          {
            "type": "string",
            "description": "Filter by merchant order ID",
            "name": "merchant_order_id",
            "in": "query"
          },
          {
            "type": "string",
            "description": "Pagination cursor from previous response",
            "name": "cursor",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/definitions/handler.paymentListResponse"
            }
          },
          "401": {
            "description": "Unauthorized",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "500": {
            "description": "Internal Server Error",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          }
        }
      },
      "post": {
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "description": "Initiates a new Kaspi QR payment for the authenticated device API key.",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "tags": [
          "payments"
        ],
        "summary": "Create a payment",
        "parameters": [
          {
            "type": "string",
            "description": "Idempotency key",
            "name": "X-Idempotency-Key",
            "in": "header"
          },
          {
            "description": "Payment request",
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/handler.createPaymentRequest"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created",
            "schema": {
              "$ref": "#/definitions/handler.paymentObject"
            }
          },
          "400": {
            "description": "Bad Request",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "401": {
            "description": "Unauthorized",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "500": {
            "description": "Internal Server Error",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          }
        }
      }
    },
    "/payments/{paymentID}": {
      "get": {
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "description": "Returns payment details by ID.",
        "produces": [
          "application/json"
        ],
        "tags": [
          "payments"
        ],
        "summary": "Get a payment",
        "parameters": [
          {
            "type": "string",
            "description": "Payment ID",
            "name": "paymentID",
            "in": "path",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/definitions/handler.paymentObject"
            }
          },
          "401": {
            "description": "Unauthorized",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "404": {
            "description": "Not Found",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "500": {
            "description": "Internal Server Error",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          }
        }
      }
    },
    "/payments/{paymentID}/cancel": {
      "post": {
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "description": "Cancels a pending payment.",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "tags": [
          "payments"
        ],
        "summary": "Cancel a payment",
        "parameters": [
          {
            "type": "string",
            "description": "Payment ID",
            "name": "paymentID",
            "in": "path",
            "required": true
          },
          {
            "description": "Cancel reason",
            "name": "body",
            "in": "body",
            "schema": {
              "$ref": "#/definitions/handler.cancelPaymentRequest"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/definitions/handler.paymentObject"
            }
          },
          "401": {
            "description": "Unauthorized",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "404": {
            "description": "Not Found",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "409": {
            "description": "Conflict",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "500": {
            "description": "Internal Server Error",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          }
        }
      }
    },
    "/payments/{paymentID}/refund": {
      "post": {
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "description": "Initiates a refund for a completed payment.",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "tags": [
          "refunds"
        ],
        "summary": "Create a refund",
        "parameters": [
          {
            "type": "string",
            "description": "Payment ID",
            "name": "paymentID",
            "in": "path",
            "required": true
          },
          {
            "description": "Refund request",
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/handler.createRefundRequest"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted",
            "schema": {
              "$ref": "#/definitions/handler.refundObject"
            }
          },
          "400": {
            "description": "Bad Request",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "401": {
            "description": "Unauthorized",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "404": {
            "description": "Not Found",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "409": {
            "description": "Conflict",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "500": {
            "description": "Internal Server Error",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          }
        }
      }
    },
    "/payments/{paymentID}/refunds": {
      "get": {
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "description": "Returns all refunds for a given payment.",
        "produces": [
          "application/json"
        ],
        "tags": [
          "refunds"
        ],
        "summary": "List refunds for a payment",
        "parameters": [
          {
            "type": "string",
            "description": "Payment ID",
            "name": "paymentID",
            "in": "path",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/definitions/handler.refundListResponse"
            }
          },
          "401": {
            "description": "Unauthorized",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "500": {
            "description": "Internal Server Error",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          }
        }
      }
    },
    "/payments/link": {
      "post": {
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "description": "Generates a Kaspi QR payment link for the given amount. The returned qr_token URL can be displayed as a QR code or opened directly by the payer.",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "tags": [
          "payments"
        ],
        "summary": "Create a payment link",
        "parameters": [
          {
            "description": "Payment link request",
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/handler.createPaymentLinkRequest"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/definitions/handler.paymentLinkResponse"
            }
          },
          "400": {
            "description": "Bad Request",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "401": {
            "description": "Unauthorized",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "500": {
            "description": "Internal Server Error",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          }
        }
      }
    },
    "/refunds": {
      "get": {
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "description": "Returns a paginated list of all refunds for the authenticated merchant.",
        "produces": [
          "application/json"
        ],
        "tags": [
          "refunds"
        ],
        "summary": "List refunds",
        "parameters": [
          {
            "type": "string",
            "description": "Filter by payment ID",
            "name": "payment_id",
            "in": "query"
          },
          {
            "type": "string",
            "description": "Filter by status (pending, completed, failed)",
            "name": "status",
            "in": "query"
          },
          {
            "type": "string",
            "description": "Pagination cursor",
            "name": "cursor",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/definitions/handler.refundListResponse"
            }
          },
          "401": {
            "description": "Unauthorized",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "500": {
            "description": "Internal Server Error",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          }
        }
      }
    },
    "/refunds/{refundID}": {
      "get": {
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "description": "Returns refund details by ID.",
        "produces": [
          "application/json"
        ],
        "tags": [
          "refunds"
        ],
        "summary": "Get a refund",
        "parameters": [
          {
            "type": "string",
            "description": "Refund ID",
            "name": "refundID",
            "in": "path",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/definitions/handler.refundObject"
            }
          },
          "401": {
            "description": "Unauthorized",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "404": {
            "description": "Not Found",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "500": {
            "description": "Internal Server Error",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          }
        }
      }
    },
    "/static-qr-payments/{orderNumber}": {
      "get": {
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "description": "Returns a static QR (Link) payment record fetched from Kaspi history.",
        "produces": [
          "application/json"
        ],
        "tags": [
          "static-qr"
        ],
        "summary": "Get static QR payment by order number",
        "parameters": [
          {
            "type": "string",
            "description": "Kaspi order number (e.g. QR15029656207)",
            "name": "orderNumber",
            "in": "path",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/definitions/handler.staticQrPaymentObject"
            }
          },
          "404": {
            "description": "Not Found",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "500": {
            "description": "Internal Server Error",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          }
        }
      }
    },
    "/webhook-simulate": {
      "post": {
        "security": [
          {
            "DeviceAuth": []
          }
        ],
        "description": "Fires a test webhook delivery for the given event type without creating a real payment.\nIf subscription_id is omitted, all active subscriptions are tested.",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "tags": [
          "webhook-simulate"
        ],
        "summary": "Simulate a webhook event (device key)",
        "parameters": [
          {
            "description": "Simulation parameters",
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/handler.simulateEventRequest"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/definitions/handler.simulateEventResponse"
            }
          },
          "400": {
            "description": "Bad Request",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "401": {
            "description": "Unauthorized",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "404": {
            "description": "Not Found",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "500": {
            "description": "Internal Server Error",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          }
        }
      }
    },
    "/webhook-simulate/subscriptions": {
      "get": {
        "security": [
          {
            "DeviceAuth": []
          }
        ],
        "description": "Returns all webhook subscriptions for the merchant owning the device API key.",
        "produces": [
          "application/json"
        ],
        "tags": [
          "webhook-simulate"
        ],
        "summary": "List webhook subscriptions (device key)",
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/definitions/handler.subscriptionListResponse"
            }
          },
          "401": {
            "description": "Unauthorized",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          },
          "500": {
            "description": "Internal Server Error",
            "schema": {
              "$ref": "#/definitions/handler.errorResponse"
            }
          }
        }
      }
    }
  },
  "definitions": {
    "domain.WebhookEventType": {
      "type": "string",
      "enum": [
        "payment.completed",
        "payment.expired",
        "payment.cancelled",
        "payment.failed",
        "payment.refunded",
        "payment.refund_failed",
        "*"
      ],
      "x-enum-varnames": [
        "EventPaymentCompleted",
        "EventPaymentExpired",
        "EventPaymentCancelled",
        "EventPaymentFailed",
        "EventPaymentRefunded",
        "EventPaymentRefundFailed",
        "EventAll"
      ]
    },
    "handler.cancelPaymentRequest": {
      "type": "object",
      "properties": {
        "reason": {
          "type": "string",
          "example": "Customer requested cancellation"
        }
      }
    },
    "handler.createPaymentLinkRequest": {
      "type": "object",
      "properties": {
        "amount": {
          "type": "number",
          "example": 1500
        },
        "merchant_order_id": {
          "type": "string",
          "example": "order-uuid"
        }
      }
    },
    "handler.createPaymentRequest": {
      "type": "object",
      "properties": {
        "amount": {
          "type": "number",
          "example": 1500
        },
        "comment": {
          "type": "string",
          "example": "Order #42"
        },
        "merchant_order_id": {
          "type": "string",
          "example": "order-uuid"
        },
        "metadata": {
          "type": "object",
          "additionalProperties": {}
        },
        "payer_phone": {
          "type": "string",
          "example": "+77001234567"
        }
      }
    },
    "handler.createRefundRequest": {
      "type": "object",
      "properties": {
        "amount": {
          "type": "number",
          "example": 500
        },
        "reason": {
          "type": "string",
          "example": "Product returned"
        }
      }
    },
    "handler.errorResponse": {
      "type": "object",
      "properties": {
        "error": {
          "type": "string",
          "example": "VALIDATION_ERROR"
        },
        "message": {
          "type": "string",
          "example": "payer_phone and amount are required"
        }
      }
    },
    "handler.paymentLinkResponse": {
      "type": "object",
      "properties": {
        "expire_date": {
          "type": "string",
          "example": "2026-04-06T11:39:53.000+05:00"
        },
        "ext_tran_id": {
          "type": "string",
          "example": "QR14893934009"
        },
        "payment_id": {
          "type": "string",
          "example": "uuid"
        },
        "qr_operation_id": {
          "type": "integer",
          "example": 14893934009
        },
        "qr_token": {
          "type": "string",
          "example": "https://qr.kaspi.kz/55308082630746899169618031642188672381021"
        },
        "status": {
          "type": "string",
          "example": "QrTokenCreated"
        }
      }
    },
    "handler.paymentListResponse": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/handler.paymentObject"
          }
        },
        "has_more": {
          "type": "boolean",
          "example": false
        },
        "next_cursor": {
          "type": "string",
          "example": ""
        }
      }
    },
    "handler.paymentObject": {
      "type": "object",
      "properties": {
        "amount": {
          "type": "number",
          "example": 1500
        },
        "cancel_reason": {
          "type": "string"
        },
        "cancelled_at": {
          "type": "string"
        },
        "comment": {
          "type": "string",
          "example": "Order #42"
        },
        "completed_at": {
          "type": "string"
        },
        "created_at": {
          "type": "string"
        },
        "currency": {
          "type": "string",
          "example": "KZT"
        },
        "merchant_order_id": {
          "type": "string",
          "example": "order-uuid"
        },
        "metadata": {
          "type": "object",
          "additionalProperties": {}
        },
        "payer_phone": {
          "type": "string",
          "example": "+77001234567"
        },
        "payment_id": {
          "type": "string",
          "example": "uuid"
        },
        "status": {
          "type": "string",
          "example": "pending"
        },
        "updated_at": {
          "type": "string"
        },
        "user_id": {
          "type": "string",
          "example": "uuid"
        }
      }
    },
    "handler.refundListResponse": {
      "type": "object",
      "properties": {
        "data": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/handler.refundObject"
          }
        },
        "has_more": {
          "type": "boolean",
          "example": false
        },
        "next_cursor": {
          "type": "string",
          "example": ""
        }
      }
    },
    "handler.refundObject": {
      "type": "object",
      "properties": {
        "amount": {
          "type": "number",
          "example": 500
        },
        "completed_at": {
          "type": "string"
        },
        "created_at": {
          "type": "string"
        },
        "fail_reason": {
          "type": "string"
        },
        "payment_id": {
          "type": "string",
          "example": "uuid"
        },
        "reason": {
          "type": "string",
          "example": "Product returned"
        },
        "refund_id": {
          "type": "string",
          "example": "uuid"
        },
        "status": {
          "type": "string",
          "example": "pending"
        },
        "updated_at": {
          "type": "string"
        },
        "user_id": {
          "type": "string",
          "example": "uuid"
        }
      }
    },
    "handler.simulateEventRequest": {
      "type": "object",
      "properties": {
        "event": {
          "allOf": [
            {
              "$ref": "#/definitions/domain.WebhookEventType"
            }
          ],
          "example": "payment.completed"
        },
        "merchant_order_id": {
          "type": "string",
          "example": "order-123"
        },
        "subscription_id": {
          "type": "string",
          "example": "uuid"
        }
      }
    },
    "handler.simulateEventResponse": {
      "type": "object",
      "properties": {
        "results": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/handler.simulateResult"
          }
        }
      }
    },
    "handler.simulateResult": {
      "type": "object",
      "properties": {
        "error": {
          "type": "string",
          "example": "connection refused"
        },
        "event": {
          "type": "string",
          "example": "payment.completed"
        },
        "subscription_id": {
          "type": "string",
          "example": "uuid"
        },
        "success": {
          "type": "boolean",
          "example": true
        },
        "url": {
          "type": "string",
          "example": "https://example.com/webhook"
        }
      }
    },
    "handler.staticQrPaymentObject": {
      "type": "object",
      "properties": {
        "amount": {
          "type": "number",
          "example": 12
        },
        "client_short_name": {
          "type": "string",
          "example": "Рустем Е."
        },
        "comment": {
          "type": "string",
          "example": "Order #45"
        },
        "features": {
          "type": "integer",
          "example": 0
        },
        "id": {
          "type": "integer",
          "example": 1
        },
        "kaspi_operation_id": {
          "type": "integer",
          "example": 15029656207
        },
        "operation_method": {
          "type": "integer",
          "example": 0
        },
        "operation_type": {
          "type": "integer",
          "example": 0
        },
        "order_number": {
          "type": "string",
          "example": "QR15029656207"
        },
        "order_reg_date": {
          "type": "string",
          "example": "2026-04-15T13:57:25+05:00"
        },
        "sale_id": {
          "type": "integer",
          "example": 14930989637
        },
        "sale_type": {
          "type": "string",
          "example": "Link"
        },
        "source_type": {
          "type": "string",
          "example": "GOLD"
        },
        "synced_at": {
          "type": "string",
          "example": "2026-04-15T14:00:00+05:00"
        }
      }
    },
    "handler.subscriptionListResponse": {
      "type": "object",
      "properties": {
        "subscriptions": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/handler.subscriptionObject"
          }
        }
      }
    },
    "handler.subscriptionObject": {
      "type": "object",
      "properties": {
        "created_at": {
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "events": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "id": {
          "type": "string",
          "example": "uuid"
        },
        "is_active": {
          "type": "boolean",
          "example": true
        },
        "organization_id": {
          "type": "string",
          "example": "uuid"
        },
        "secret": {
          "type": "string"
        },
        "updated_at": {
          "type": "string"
        },
        "url": {
          "type": "string",
          "example": "https://example.com/webhook"
        }
      }
    }
  }
}
