{
  "openapi": "3.0.0",
  "info": {
    "title": "Mock Bank API - Positive",
    "version": "1.0.0",
    "description": "Tier 1 (Perfect Data Alignment)"
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error_code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  },
  "paths": {
    "/api/v1/accounts": {
      "get": {
        "summary": "Get all accounts for current user",
        "tags": [
          "Accounts"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "List of accounts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "accounts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "account_id": {
                            "type": "string",
                            "example": "GB29MOCK12345678901234"
                          },
                          "currency": {
                            "type": "string",
                            "example": "GBP"
                          },
                          "type": {
                            "type": "string",
                            "example": "CHECKING"
                          },
                          "status": {
                            "type": "string",
                            "example": "ACTIVE"
                          }
                        }
                      }
                    },
                    "total_count": {
                      "type": "integer",
                      "example": 2
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/accounts/{account_id}/balance": {
      "get": {
        "summary": "Get account balance",
        "tags": [
          "Accounts"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "GB29MOCK12345678901234"
          }
        ],
        "responses": {
          "200": {
            "description": "Account balance details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "account_id": {
                      "type": "string",
                      "example": "GB29MOCK12345678901234"
                    },
                    "balance": {
                      "type": "number",
                      "example": 15500.5
                    },
                    "currency": {
                      "type": "string",
                      "example": "GBP"
                    },
                    "last_updated": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2026-04-17T17:27:00Z"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Account does not belong to the current user",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Account not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/accounts/{account_id}/cards": {
      "get": {
        "summary": "Get cards for account",
        "tags": [
          "Accounts"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "GB29MOCK12345678901234"
          }
        ],
        "responses": {
          "200": {
            "description": "List of cards attached to the account",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "account_id": {
                      "type": "string",
                      "example": "GB29MOCK12345678901234"
                    },
                    "cards": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "card_token": {
                            "type": "string",
                            "example": "ct_8899"
                          },
                          "masked_pan": {
                            "type": "string",
                            "example": "**** **** **** 1234"
                          },
                          "type": {
                            "type": "string",
                            "example": "VISA_GOLD"
                          },
                          "status": {
                            "type": "string",
                            "example": "ACTIVE"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Account does not belong to the current user"
          },
          "404": {
            "description": "Account not found"
          }
        }
      }
    },
    "/api/v1/accounts/{account_id}/settings": {
      "patch": {
        "summary": "Update account settings",
        "tags": [
          "Accounts"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "GB29MOCK12345678901234"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "nickname": {
                    "type": "string",
                    "example": "Salary Account"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Settings updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "account_id": {
                      "type": "string",
                      "example": "GB29MOCK12345678901234"
                    },
                    "nickname": {
                      "type": "string",
                      "example": "Salary Account"
                    },
                    "updated_fields": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "example": [
                        "nickname"
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request missing fields"
          },
          "403": {
            "description": "Account does not belong to the current user"
          },
          "404": {
            "description": "Account not found"
          }
        }
      }
    },
    "/api/v1/accounts/{account_id}/statement": {
      "get": {
        "summary": "Get account statement",
        "tags": [
          "Accounts"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "GB29MOCK12345678901234"
          },
          {
            "in": "query",
            "name": "format",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "pdf",
                "csv"
              ]
            },
            "example": "pdf"
          },
          {
            "in": "query",
            "name": "from",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-01-01"
          },
          {
            "in": "query",
            "name": "to",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-04-17"
          }
        ],
        "responses": {
          "200": {
            "description": "Account statement file (PDF)",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Account not found"
          }
        }
      }
    },
    "/api/v1/auth/login": {
      "post": {
        "summary": "User login",
        "description": "Authenticate with username/password, receive JWT access token and refresh token.",
        "tags": [
          "Authentication"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "username",
                  "password"
                ],
                "properties": {
                  "username": {
                    "type": "string",
                    "example": "testuser_1"
                  },
                  "password": {
                    "type": "string",
                    "example": "password123"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful login",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string",
                      "description": "JWT access token",
                      "example": "eyJhbGciOiJIUzI1NiIs..."
                    },
                    "refresh_token": {
                      "type": "string",
                      "description": "Refresh token",
                      "example": "rt_abc123def456..."
                    },
                    "user_id": {
                      "type": "string",
                      "example": "usr_98765"
                    },
                    "expires_in": {
                      "type": "integer",
                      "example": 3600
                    },
                    "token_type": {
                      "type": "string",
                      "example": "Bearer"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request missing required fields",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/refresh": {
      "post": {
        "summary": "Refresh access token",
        "description": "Exchange a valid refresh token for a new access token. The old refresh token is invalidated (rotation).",
        "tags": [
          "Authentication"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "refresh_token"
                ],
                "properties": {
                  "refresh_token": {
                    "type": "string",
                    "description": "Refresh token from login or previous refresh",
                    "example": "rt_abc123def456..."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successfully refreshed token",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string",
                      "example": "eyJhbGciOiJIUzI1NiIs_NEW..."
                    },
                    "refresh_token": {
                      "type": "string",
                      "example": "rt_new_789xyz..."
                    },
                    "expires_in": {
                      "type": "integer",
                      "example": 3600
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or expired refresh token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/internal/auth/verify": {
      "post": {
        "summary": "Verify JWT token (internal)",
        "description": "Internal service-to-service endpoint for verifying JWT tokens. Not rate-limited.",
        "tags": [
          "Internal"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "token"
                ],
                "properties": {
                  "token": {
                    "type": "string",
                    "description": "JWT token to verify"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Token is valid",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "user_id": {
                      "type": "string"
                    },
                    "valid": {
                      "type": "boolean"
                    },
                    "roles": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Token expired or invalid"
          }
        }
      }
    },
    "/api/v1/cards/{card_token}/limits": {
      "post": {
        "summary": "Set card limits",
        "tags": [
          "Cards"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "card_token",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "ct_8899"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "limit_type": {
                    "type": "string",
                    "example": "ONLINE_SHOPPING"
                  },
                  "new_value": {
                    "type": "number",
                    "example": 5000
                  },
                  "currency": {
                    "type": "string",
                    "example": "GBP"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Card limits updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "card_token": {
                      "type": "string",
                      "example": "ct_8899"
                    },
                    "limit_type": {
                      "type": "string",
                      "example": "ONLINE_SHOPPING"
                    },
                    "previous_value": {
                      "type": "number",
                      "example": 10000
                    },
                    "new_value": {
                      "type": "number",
                      "example": 5000
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request missing fields"
          },
          "403": {
            "description": "Card does not belong to the current user"
          },
          "404": {
            "description": "Card not found"
          }
        }
      }
    },
    "/api/v1/cards/{card_token}/block": {
      "post": {
        "summary": "Block a card",
        "tags": [
          "Cards"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "card_token",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "ct_8899"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "example": "LOST"
                  },
                  "notify_sms": {
                    "type": "boolean",
                    "example": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Card blocked successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "card_token": {
                      "type": "string",
                      "example": "ct_8899"
                    },
                    "previous_status": {
                      "type": "string",
                      "example": "ACTIVE"
                    },
                    "new_status": {
                      "type": "string",
                      "example": "BLOCKED"
                    },
                    "blocked_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2026-04-17T20:05:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Card is already blocked"
          },
          "403": {
            "description": "Card does not belong to the current user"
          },
          "404": {
            "description": "Card not found"
          }
        }
      }
    },
    "/api/v1/exchange/quote": {
      "get": {
        "summary": "Get currency exchange quote",
        "tags": [
          "Exchange"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "from",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Source currency (sell)",
            "example": "USD"
          },
          {
            "in": "query",
            "name": "to",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Target currency (buy)",
            "example": "GBP"
          },
          {
            "in": "query",
            "name": "amount",
            "required": true,
            "schema": {
              "type": "number"
            },
            "description": "Amount to sell",
            "example": 100
          }
        ],
        "responses": {
          "200": {
            "description": "Quote received",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "quote_id": {
                      "type": "string",
                      "example": "q_772211"
                    },
                    "from_currency": {
                      "type": "string",
                      "example": "USD"
                    },
                    "to_currency": {
                      "type": "string",
                      "example": "GBP"
                    },
                    "rate": {
                      "type": "number",
                      "example": 41.25
                    },
                    "result_amount": {
                      "type": "number",
                      "example": 4125
                    },
                    "expiry_ms": {
                      "type": "integer",
                      "example": 30000
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request missing parameters"
          }
        }
      }
    },
    "/api/v1/exchange/confirm": {
      "post": {
        "summary": "Confirm currency exchange",
        "tags": [
          "Exchange"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "quote_id": {
                    "type": "string",
                    "example": "q_772211"
                  },
                  "debit_account": {
                    "type": "string",
                    "example": "acc_usd_001"
                  },
                  "credit_account": {
                    "type": "string",
                    "example": "GB29MOCK12345678901234"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Exchange completed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "exchange_ref": {
                      "type": "string",
                      "example": "exch_001122"
                    },
                    "status": {
                      "type": "string",
                      "example": "COMPLETED"
                    },
                    "debited": {
                      "type": "object",
                      "properties": {
                        "amount": {
                          "type": "number",
                          "example": 100
                        },
                        "currency": {
                          "type": "string",
                          "example": "USD"
                        }
                      }
                    },
                    "credited": {
                      "type": "object",
                      "properties": {
                        "amount": {
                          "type": "number",
                          "example": 4125
                        },
                        "currency": {
                          "type": "string",
                          "example": "GBP"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request missing parameters"
          },
          "404": {
            "description": "Quote not found, debit account not found, or credit account not found"
          },
          "422": {
            "description": "Quote expired, insufficient funds, or currency mismatch"
          }
        }
      }
    },
    "/internal/audit/logs": {
      "get": {
        "summary": "Get audit logs (internal)",
        "tags": [
          "Internal"
        ],
        "parameters": [
          {
            "in": "query",
            "name": "service",
            "schema": {
              "type": "string"
            },
            "description": "Filter by trace_id"
          },
          {
            "in": "query",
            "name": "action",
            "schema": {
              "type": "string",
              "default": 1
            }
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "type": "integer",
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of audit logs"
          }
        }
      }
    },
    "/api/v1/events/publish": {
      "post": {
        "summary": "Publish an event to Kafka (Mock)",
        "tags": [
          "Events"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "topic": {
                    "type": "string",
                    "example": "market.quotes"
                  },
                  "event": {
                    "type": "string",
                    "example": "market.update"
                  },
                  "payload": {
                    "type": "object",
                    "example": {
                      "symbol": "MOCKBNK",
                      "price": 250
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Event accepted for processing"
          }
        }
      }
    },
    "/internal/fraud/score": {
      "post": {
        "summary": "Get fraud risk score (internal)",
        "tags": [
          "Internal"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "transaction_id": {
                    "type": "string"
                  },
                  "amount": {
                    "type": "number"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Risk score"
          }
        }
      }
    },
    "/internal/vendor/credit-score": {
      "get": {
        "summary": "Get vendor credit score (internal)",
        "tags": [
          "Internal"
        ],
        "parameters": [
          {
            "in": "query",
            "name": "vendor_id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Credit score"
          }
        }
      }
    },
    "/api/v1/loans/apply": {
      "post": {
        "summary": "Submit loan application",
        "tags": [
          "Loans"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "account_id",
                  "loan_type",
                  "requested_amount",
                  "term_months",
                  "monthly_income"
                ],
                "properties": {
                  "account_id": {
                    "type": "string",
                    "example": "GB29MOCK12345678901234"
                  },
                  "loan_type": {
                    "type": "string",
                    "enum": [
                      "PERSONAL",
                      "MORTGAGE",
                      "BUSINESS"
                    ],
                    "example": "PERSONAL"
                  },
                  "requested_amount": {
                    "type": "number",
                    "example": 50000
                  },
                  "term_months": {
                    "type": "integer",
                    "example": 24
                  },
                  "monthly_income": {
                    "type": "number",
                    "example": 15000
                  },
                  "callback_url": {
                    "type": "string",
                    "example": "https://webhook.site/mock"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Loan application submitted and in progress",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "application_id": {
                      "type": "string",
                      "example": "loan_app_98765432"
                    },
                    "status": {
                      "type": "string",
                      "example": "IN_PROGRESS"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing required parameters"
          },
          "403": {
            "description": "Account does not belong to current user"
          },
          "404": {
            "description": "Account not found"
          },
          "422": {
            "description": "DTI exceeded or invalid mortgage term"
          }
        }
      }
    },
    "/api/v1/loans/status": {
      "get": {
        "summary": "Check loan application status",
        "tags": [
          "Loans"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "app_id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "loan_app_98765432"
          },
          {
            "in": "query",
            "name": "details",
            "required": false,
            "schema": {
              "type": "boolean"
            },
            "example": true
          }
        ],
        "responses": {
          "200": {
            "description": "Loan application details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "app_id": {
                      "type": "string",
                      "example": "loan_app_98765432"
                    },
                    "current_stage": {
                      "type": "string",
                      "enum": [
                        "IN_PROGRESS",
                        "APPROVED",
                        "REJECTED"
                      ],
                      "example": "APPROVED"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "approved_amount": {
                      "type": "number",
                      "example": 50000
                    },
                    "interest_rate": {
                      "type": "number",
                      "example": 12.5
                    },
                    "monthly_payment": {
                      "type": "number",
                      "example": 2604.17
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing app_id query parameter"
          },
          "404": {
            "description": "Loan application not found"
          }
        }
      }
    },
    "/api/v1/loans/{id}/documents": {
      "post": {
        "summary": "Upload document for loan application",
        "tags": [
          "Loans"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  },
                  "doc_type": {
                    "type": "string",
                    "enum": [
                      "PASSPORT",
                      "INCOME_STATEMENT",
                      "TAX_RETURN"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "File uploaded successfully"
          }
        }
      }
    },
    "/api/v1/market/stocks/stream": {
      "get": {
        "summary": "Stream stock quotes via SSE",
        "tags": [
          "Market"
        ],
        "description": "Establishes a Server-Sent Events connection and sends stock quotes in JSON format every second.",
        "responses": {
          "200": {
            "description": "Event Stream",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "example": "data: {\"symbol\": \"MOCKBNK\", \"price\": 245.12, \"change_percent\": 0.02, \"volume\": 15340, \"timestamp\": \"2026-04-17T18:55:01Z\"}\n"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/payments/init": {
      "post": {
        "summary": "Initiate a payment",
        "tags": [
          "Payments"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "from_account",
                  "payee_iban",
                  "amount",
                  "purpose"
                ],
                "properties": {
                  "from_account": {
                    "type": "string",
                    "example": "GB29MOCK12345678901234"
                  },
                  "payee_iban": {
                    "type": "string",
                    "example": "GB29MIDL40051512345678"
                  },
                  "amount": {
                    "type": "number",
                    "example": 1500
                  },
                  "purpose": {
                    "type": "string",
                    "example": "Utility Bill"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Payment initiated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payment_id": {
                      "type": "string",
                      "example": "pay_555"
                    },
                    "status": {
                      "type": "string",
                      "example": "AWAITING_OTP"
                    },
                    "otp_method": {
                      "type": "string",
                      "example": "SMS"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing required parameters or invalid amount"
          },
          "404": {
            "description": "Source account not found"
          },
          "422": {
            "description": "Cannot initiate payment from a closed account"
          }
        }
      }
    },
    "/api/v1/payments/{payment_id}/status": {
      "get": {
        "summary": "Get payment status",
        "tags": [
          "Payments"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "payment_id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "pay_555"
          }
        ],
        "responses": {
          "200": {
            "description": "Payment status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payment_id": {
                      "type": "string",
                      "example": "pay_555"
                    },
                    "status": {
                      "type": "string",
                      "example": "AWAITING_OTP"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2026-04-17T19:00:00Z"
                    },
                    "completed_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Payment not found"
          }
        }
      }
    },
    "/api/v1/payments/{payment_id}/verify": {
      "post": {
        "summary": "Verify payment with OTP",
        "tags": [
          "Payments"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "payment_id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "pay_555"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "otp_code"
                ],
                "properties": {
                  "otp_code": {
                    "type": "string",
                    "example": "1234"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Payment accepted for asynchronous processing",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payment_id": {
                      "type": "string",
                      "example": "pay_555"
                    },
                    "status": {
                      "type": "string",
                      "example": "PENDING_PROCESSING"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing otp_code, invalid OTP, or payment not awaiting OTP"
          },
          "404": {
            "description": "Payment not found or Account not found"
          },
          "422": {
            "description": "Account closed or Insufficient funds"
          },
          "429": {
            "description": "3+ invalid OTP attempts exceeded"
          }
        }
      }
    },
    "/api/v1/payments/batch": {
      "post": {
        "summary": "Process batch payments",
        "tags": [
          "Payments"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "from_account",
                  "payments"
                ],
                "properties": {
                  "from_account": {
                    "type": "string",
                    "example": "GB29MOCK12345678901234"
                  },
                  "payments": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "payee_iban": {
                          "type": "string",
                          "example": "GB29MIDL40051512345678"
                        },
                        "amount": {
                          "type": "number",
                          "example": 1500
                        },
                        "purpose": {
                          "type": "string",
                          "example": "Rent"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "207": {
            "description": "Multi-status batch processing result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "total": {
                      "type": "integer",
                      "example": 3
                    },
                    "succeeded": {
                      "type": "integer",
                      "example": 2
                    },
                    "failed": {
                      "type": "integer",
                      "example": 1
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "index": {
                            "type": "integer",
                            "example": 0
                          },
                          "status": {
                            "type": "string",
                            "example": "ACCEPTED"
                          },
                          "payment_id": {
                            "type": "string",
                            "example": "pay_601"
                          },
                          "error_code": {
                            "type": "string",
                            "example": "INVALID_IBAN"
                          },
                          "message": {
                            "type": "string",
                            "example": "Invalid IBAN format"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing required fields"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Account not found"
          },
          "422": {
            "description": "Account closed"
          }
        }
      }
    },
    "/api/v1/support/chat/init": {
      "post": {
        "summary": "Initialise WebSocket chat",
        "tags": [
          "Support"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "reason"
                ],
                "properties": {
                  "reason": {
                    "type": "string",
                    "example": "credit_limit"
                  },
                  "priority": {
                    "type": "string",
                    "example": "high"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successfully initialised",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "chat_token": {
                      "type": "string"
                    },
                    "agent_id": {
                      "type": "string"
                    },
                    "welcome_message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/transactions": {
      "get": {
        "summary": "Get list of transactions",
        "tags": [
          "Transactions"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "account_id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "GB29MOCK12345678901234"
          },
          {
            "in": "query",
            "name": "days",
            "schema": {
              "type": "integer",
              "default": 30
            }
          },
          {
            "in": "query",
            "name": "status",
            "schema": {
              "type": "string",
              "enum": [
                "COMPLETED",
                "PENDING",
                "FAILED"
              ]
            }
          },
          {
            "in": "query",
            "name": "page",
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "type": "integer",
              "default": 20
            }
          },
          {
            "in": "query",
            "name": "sort",
            "schema": {
              "type": "string"
            },
            "example": "created_at:desc"
          },
          {
            "in": "query",
            "name": "date_from",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "in": "query",
            "name": "date_to",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "in": "query",
            "name": "min_amount",
            "schema": {
              "type": "number"
            }
          },
          {
            "in": "query",
            "name": "max_amount",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of transactions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "txn_id": {
                            "type": "string",
                            "example": "txn_554433"
                          },
                          "type": {
                            "type": "string",
                            "example": "TRANSFER_OUT"
                          },
                          "amount": {
                            "type": "number",
                            "example": -500
                          },
                          "currency": {
                            "type": "string",
                            "example": "GBP"
                          },
                          "counterparty": {
                            "type": "string",
                            "example": "acc_998877"
                          },
                          "status": {
                            "type": "string",
                            "example": "COMPLETED"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time",
                            "example": "2026-04-17T17:30:00Z"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer",
                          "example": 2
                        },
                        "limit": {
                          "type": "integer",
                          "example": 10
                        },
                        "total_items": {
                          "type": "integer",
                          "example": 47
                        },
                        "total_pages": {
                          "type": "integer",
                          "example": 5
                        },
                        "has_next": {
                          "type": "boolean",
                          "example": true
                        },
                        "has_prev": {
                          "type": "boolean",
                          "example": true
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request missing fields"
          },
          "403": {
            "description": "Account does not belong to the current user"
          },
          "404": {
            "description": "Account not found"
          }
        }
      }
    },
    "/api/v1/transactions/transfer": {
      "post": {
        "summary": "Initiate a funds transfer",
        "description": "Initiate a funds transfer. Processed asynchronously.",
        "tags": [
          "Transactions"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "example": "req_55667788"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "from_account": {
                    "type": "string",
                    "example": "GB29MOCK12345678901234"
                  },
                  "to_account": {
                    "type": "string",
                    "example": "acc_998877"
                  },
                  "amount": {
                    "type": "number",
                    "example": 500
                  },
                  "currency": {
                    "type": "string",
                    "example": "GBP"
                  },
                  "purpose": {
                    "type": "string",
                    "example": "Loan Repayment"
                  },
                  "callback_url": {
                    "type": "string",
                    "example": "http://client-server.local:9090/webhook"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Idempotent hit (already processed)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "transaction_ref": {
                      "type": "string",
                      "example": "txn_554433"
                    },
                    "status": {
                      "type": "string",
                      "example": "PENDING_PROCESSING"
                    },
                    "fraud_risk_score": {
                      "type": "number",
                      "example": 0.05
                    },
                    "idempotent_hit": {
                      "type": "boolean",
                      "example": true
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "Transfer accepted for processing",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "transaction_ref": {
                      "type": "string",
                      "example": "txn_554433"
                    },
                    "status": {
                      "type": "string",
                      "example": "PENDING_PROCESSING"
                    },
                    "fraud_risk_score": {
                      "type": "number",
                      "example": 0.05
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request missing fields"
          },
          "403": {
            "description": "Source account does not belong to the current user"
          },
          "404": {
            "description": "Source account not found"
          },
          "409": {
            "description": "Idempotency-Key has already been used for a different request"
          },
          "422": {
            "description": "Insufficient funds"
          }
        }
      }
    },
    "/api/v1/user/profile": {
      "put": {
        "summary": "Update user profile",
        "tags": [
          "Users"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "display_name": {
                    "type": "string",
                    "example": "John Doe"
                  },
                  "email": {
                    "type": "string",
                    "example": "ivan.p@example.com"
                  },
                  "phone": {
                    "type": "string",
                    "example": "+380501234567"
                  },
                  "language": {
                    "type": "string",
                    "example": "en-GB"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Profile updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "user_id": {
                      "type": "string",
                      "example": "usr_98765"
                    },
                    "display_name": {
                      "type": "string",
                      "example": "John Doe"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2026-04-17T20:30:00Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "No fields provided for update"
          },
          "404": {
            "description": "User not found"
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Accounts",
      "description": "Bank accounts, balances, cards, and settings"
    },
    {
      "name": "Authentication",
      "description": "User authentication and token management"
    },
    {
      "name": "Cards",
      "description": "Card management and settings"
    },
    {
      "name": "Exchange",
      "description": "Currency exchange quotes and confirmations"
    },
    {
      "name": "Audit",
      "description": "Audit and logging"
    },
    {
      "name": "Market",
      "description": "Market data and quotes (SSE)"
    },
    {
      "name": "Payments",
      "description": "OTP-verified payments and batch processing"
    },
    {
      "name": "Support",
      "description": "Support chat and WebSockets"
    },
    {
      "name": "Transactions",
      "description": "Funds transfers and transaction history"
    },
    {
      "name": "Users",
      "description": "User profile and settings"
    }
  ],
  "servers": [
    {
      "url": "https://bank.testbuster.ai",
      "description": "Current Sandbox Environment"
    },
    {
      "url": "https://bank.testbuster.ai",
      "description": "Production Demo Stand"
    },
    {
      "url": "http://localhost:7050",
      "description": "Local Development Server"
    }
  ]
}