{
  "openapi": "3.0.3",
  "info": {
    "title": "Aurix API",
    "description": "Multi-tenant fintech backend for digital gold trading",
    "version": "0.1.0"
  },
  "servers": [
    {
      "url": "http://localhost:8080"
    }
  ],
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "JWT access token. Admin endpoints require role: \"admin\" in JWT claims."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error": {
            "type": "object",
            "required": ["code", "message"],
            "properties": {
              "code": {
                "type": "string",
                "example": "error_code_snake_case"
              },
              "message": {
                "type": "string",
                "example": "Human-readable description"
              },
              "details": {
                "type": "object"
              }
            }
          }
        }
      },
      "RateLimitError": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error": {
            "type": "object",
            "required": ["code", "message"],
            "properties": {
              "code": {
                "type": "string",
                "example": "rate_limited"
              },
              "message": {
                "type": "string",
                "example": "Too many requests. Please try again later."
              },
              "details": {
                "type": "object",
                "properties": {
                  "retry_after_seconds": {
                    "type": "integer",
                    "example": 45
                  }
                }
              }
            }
          }
        }
      },
      "HealthResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": ["healthy", "degraded"]
          },
          "components": {
            "type": "object",
            "properties": {
              "api": {
                "type": "string",
                "example": "up"
              },
              "database": {
                "type": "string",
                "example": "up"
              },
              "redis": {
                "type": "string",
                "example": "up"
              }
            }
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "RegisterRequest": {
        "type": "object",
        "required": ["tenant_code", "email", "password"],
        "properties": {
          "tenant_code": {
            "type": "string",
            "example": "acme"
          },
          "email": {
            "type": "string",
            "format": "email",
            "example": "alice@example.com"
          },
          "password": {
            "type": "string",
            "format": "password",
            "minLength": 10,
            "example": "Str0ng!Pass#2026"
          }
        }
      },
      "RegisterResponse": {
        "type": "object",
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "tenant_id": {
            "type": "string",
            "format": "uuid"
          },
          "wallet_id": {
            "type": "string",
            "format": "uuid"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "LoginRequest": {
        "type": "object",
        "required": ["tenant_code", "email", "password"],
        "properties": {
          "tenant_code": {
            "type": "string",
            "example": "acme"
          },
          "email": {
            "type": "string",
            "format": "email",
            "example": "alice@example.com"
          },
          "password": {
            "type": "string",
            "format": "password",
            "example": "Str0ng!Pass#2026"
          }
        }
      },
      "TokenResponse": {
        "type": "object",
        "properties": {
          "access_token": {
            "type": "string"
          },
          "refresh_token": {
            "type": "string"
          },
          "token_type": {
            "type": "string",
            "example": "Bearer"
          },
          "expires_in": {
            "type": "integer",
            "example": 900
          }
        }
      },
      "RefreshRequest": {
        "type": "object",
        "required": ["refresh_token"],
        "properties": {
          "refresh_token": {
            "type": "string"
          }
        }
      },
      "LogoutRequest": {
        "type": "object",
        "required": ["refresh_token"],
        "properties": {
          "refresh_token": {
            "type": "string"
          }
        }
      },
      "ChangePasswordRequest": {
        "type": "object",
        "required": ["current_password", "new_password"],
        "properties": {
          "current_password": {
            "type": "string",
            "format": "password"
          },
          "new_password": {
            "type": "string",
            "format": "password",
            "minLength": 10
          }
        }
      },
      "WalletResponse": {
        "type": "object",
        "properties": {
          "wallet_id": {
            "type": "string",
            "format": "uuid"
          },
          "tenant_id": {
            "type": "string",
            "format": "uuid"
          },
          "user_id": {
            "type": "string",
            "format": "uuid"
          },
          "gold_balance_grams": {
            "type": "string",
            "example": "12.50000000"
          },
          "fiat_balance_eur": {
            "type": "string",
            "example": "8421.35"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "BuySellRequest": {
        "type": "object",
        "required": ["grams"],
        "properties": {
          "grams": {
            "type": "string",
            "example": "1.25000000"
          }
        }
      },
      "BuyResponse": {
        "type": "object",
        "properties": {
          "transaction": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "type": {
                "type": "string",
                "example": "buy"
              },
              "gold_grams": {
                "type": "string"
              },
              "price_eur_per_gram": {
                "type": "string"
              },
              "gross_eur": {
                "type": "string"
              },
              "fee_eur": {
                "type": "string"
              },
              "total_eur": {
                "type": "string"
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "wallet": {
            "type": "object",
            "properties": {
              "gold_balance_grams": {
                "type": "string"
              },
              "fiat_balance_eur": {
                "type": "string"
              }
            }
          }
        }
      },
      "SellResponse": {
        "type": "object",
        "properties": {
          "transaction": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "type": {
                "type": "string",
                "example": "sell"
              },
              "gold_grams": {
                "type": "string"
              },
              "price_eur_per_gram": {
                "type": "string"
              },
              "gross_eur": {
                "type": "string"
              },
              "fee_eur": {
                "type": "string"
              },
              "net_eur": {
                "type": "string"
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "wallet": {
            "type": "object",
            "properties": {
              "gold_balance_grams": {
                "type": "string"
              },
              "fiat_balance_eur": {
                "type": "string"
              }
            }
          }
        }
      },
      "TransactionItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "type": {
            "type": "string",
            "enum": ["buy", "sell"]
          },
          "gold_grams": {
            "type": "string"
          },
          "price_eur_per_gram": {
            "type": "string"
          },
          "gross_eur": {
            "type": "string"
          },
          "fee_eur": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "example": "posted"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TransactionListResponse": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TransactionItem"
            }
          },
          "next_cursor": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "InsightItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "frequency": {
            "type": "string",
            "enum": ["daily", "weekly"]
          },
          "period_start": {
            "type": "string",
            "format": "date"
          },
          "period_end": {
            "type": "string",
            "format": "date"
          },
          "generated_at": {
            "type": "string",
            "format": "date-time"
          },
          "signals": {
            "type": "object"
          },
          "insights": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "InsightListResponse": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InsightItem"
            }
          },
          "next_cursor": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "PrivacyExportResponse": {
        "type": "object",
        "properties": {
          "user": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "email": {
                "type": "string",
                "format": "email"
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "wallet": {
            "type": "object"
          },
          "transactions": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "insights": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "exported_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ErasureResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "example": "accepted"
          },
          "message": {
            "type": "string"
          },
          "request_id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "ForbiddenError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "example": "forbidden"
              },
              "message": {
                "type": "string",
                "example": "Admin access required"
              },
              "details": {
                "type": "object"
              }
            }
          }
        }
      }
    },
    "headers": {
      "X-Request-Id": {
        "description": "Request correlation ID",
        "schema": {
          "type": "string"
        }
      },
      "X-RateLimit-Limit": {
        "description": "Maximum requests allowed in the window",
        "schema": {
          "type": "integer"
        }
      },
      "X-RateLimit-Remaining": {
        "description": "Remaining requests in the current window",
        "schema": {
          "type": "integer"
        }
      },
      "X-RateLimit-Reset": {
        "description": "Unix timestamp when the rate limit resets",
        "schema": {
          "type": "integer"
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing or invalid JWT",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/X-Request-Id"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "unauthorized",
                "message": "Missing or invalid authentication token",
                "details": {}
              }
            }
          }
        }
      },
      "RateLimited": {
        "description": "Too many requests",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/X-Request-Id"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/RateLimitError"
            },
            "example": {
              "error": {
                "code": "rate_limited",
                "message": "Too many requests. Please try again later.",
                "details": {
                  "retry_after_seconds": 45
                }
              }
            }
          }
        }
      }
    }
  },
  "paths": {
    "/health": {
      "get": {
        "tags": ["Health"],
        "summary": "Health check",
        "operationId": "healthCheck",
        "responses": {
          "200": {
            "description": "All components healthy",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                },
                "example": {
                  "status": "healthy",
                  "components": {
                    "api": "up",
                    "database": "up",
                    "redis": "up"
                  },
                  "timestamp": "2026-04-02T10:00:00Z"
                }
              }
            }
          },
          "503": {
            "description": "One or more components degraded",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                },
                "example": {
                  "status": "degraded",
                  "components": {
                    "api": "up",
                    "database": "down",
                    "redis": "up"
                  },
                  "timestamp": "2026-04-02T10:00:00Z"
                }
              }
            }
          }
        }
      }
    },
    "/auth/register": {
      "post": {
        "tags": ["Auth"],
        "summary": "Create account",
        "operationId": "register",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Account created",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegisterResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error (invalid_tenant, invalid_email, invalid_password)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Tenant inactive",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Email already taken",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/login": {
      "post": {
        "tags": ["Auth"],
        "summary": "Authenticate",
        "operationId": "login",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoginRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Authentication successful",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error (invalid_tenant)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Account disabled or tenant inactive",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/refresh": {
      "post": {
        "tags": ["Auth"],
        "summary": "Refresh tokens",
        "operationId": "refreshTokens",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RefreshRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tokens refreshed",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            }
          },
          "401": {
            "description": "Token expired or revoked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Account disabled",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/logout": {
      "post": {
        "tags": ["Auth"],
        "summary": "Revoke refresh token",
        "operationId": "logout",
        "security": [{"BearerAuth": []}],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LogoutRequest"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Logged out successfully",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/auth/change-password": {
      "post": {
        "tags": ["Auth"],
        "summary": "Change password",
        "operationId": "changePassword",
        "security": [{"BearerAuth": []}],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChangePasswordRequest"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Password changed successfully",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            }
          },
          "400": {
            "description": "Validation error (invalid_password, password_unchanged)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/wallet": {
      "get": {
        "tags": ["Wallet"],
        "summary": "Get wallet",
        "operationId": "getWallet",
        "security": [{"BearerAuth": []}],
        "responses": {
          "200": {
            "description": "Wallet details",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WalletResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Wallet not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/wallet/buy": {
      "post": {
        "tags": ["Wallet"],
        "summary": "Buy gold",
        "operationId": "buyGold",
        "security": [{"BearerAuth": []}],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Unique key to prevent duplicate processing",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BuySellRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Gold purchased",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuyResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid amount",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "description": "Duplicate idempotency key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Insufficient EUR balance",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/wallet/sell": {
      "post": {
        "tags": ["Wallet"],
        "summary": "Sell gold",
        "operationId": "sellGold",
        "security": [{"BearerAuth": []}],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Unique key to prevent duplicate processing",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BuySellRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Gold sold",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SellResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid amount",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "description": "Duplicate idempotency key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Insufficient gold balance",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/transactions": {
      "get": {
        "tags": ["Transactions"],
        "summary": "List transactions",
        "operationId": "listTransactions",
        "security": [{"BearerAuth": []}],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "description": "Opaque cursor for pagination",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Items per page",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "type",
            "in": "query",
            "description": "Filter by transaction type",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["buy", "sell"]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Transaction list",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/insights": {
      "get": {
        "tags": ["Insights"],
        "summary": "Get AI insights",
        "operationId": "listInsights",
        "security": [{"BearerAuth": []}],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "description": "Opaque cursor for pagination",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Items per page",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 10,
              "minimum": 1,
              "maximum": 50
            }
          },
          {
            "name": "frequency",
            "in": "query",
            "description": "Filter by insight frequency",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["daily", "weekly"]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Insight list",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InsightListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/privacy/export": {
      "get": {
        "tags": ["Privacy"],
        "summary": "Export personal data",
        "operationId": "exportData",
        "security": [{"BearerAuth": []}],
        "responses": {
          "200": {
            "description": "Personal data export",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PrivacyExportResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/privacy/erasure-request": {
      "post": {
        "tags": ["Privacy"],
        "summary": "Request erasure",
        "operationId": "requestErasure",
        "security": [{"BearerAuth": []}],
        "responses": {
          "202": {
            "description": "Erasure request accepted",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErasureResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/admin/tenants": {
      "get": {
        "tags": ["Admin"],
        "summary": "List all tenants",
        "description": "Returns all tenants. Requires admin role.",
        "operationId": "listTenants",
        "security": [{"BearerAuth": []}],
        "responses": {
          "200": {
            "description": "Tenant list",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "code": {
                            "type": "string",
                            "example": "aurix-demo"
                          },
                          "name": {
                            "type": "string",
                            "example": "Aurix Demo Tenant"
                          },
                          "status": {
                            "type": "string",
                            "example": "active"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "items": [
                    {
                      "id": "a0000000-0000-0000-0000-000000000001",
                      "code": "aurix-demo",
                      "name": "Aurix Demo Tenant",
                      "status": "active",
                      "created_at": "2026-04-02T10:00:00Z"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Forbidden — non-admin user",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ForbiddenError"
                },
                "example": {
                  "error": {
                    "code": "forbidden",
                    "message": "Admin access required",
                    "details": {}
                  }
                }
              }
            }
          }
        }
      }
    },
    "/admin/tenants/{tenant_id}/deactivate": {
      "post": {
        "tags": ["Admin"],
        "summary": "Deactivate a tenant",
        "description": "Sets tenant status to inactive. All login attempts for that tenant will return 403.",
        "operationId": "deactivateTenant",
        "security": [{"BearerAuth": []}],
        "parameters": [
          {
            "name": "tenant_id",
            "in": "path",
            "description": "Tenant UUID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tenant deactivated",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "example": "deactivated"
                    },
                    "tenant_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                },
                "example": {
                  "status": "deactivated",
                  "tenant_id": "a0000000-0000-0000-0000-000000000001"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Forbidden — non-admin user",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ForbiddenError"
                }
              }
            }
          },
          "404": {
            "description": "Tenant not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/admin/gold-price": {
      "post": {
        "tags": ["Admin"],
        "summary": "Update gold price",
        "description": "Updates the gold price per gram in EUR. Takes effect immediately for new transactions.",
        "operationId": "updateGoldPrice",
        "security": [{"BearerAuth": []}],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["price_eur"],
                "properties": {
                  "price_eur": {
                    "type": "string",
                    "example": "72.50"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Gold price updated",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "example": "updated"
                    },
                    "price_eur": {
                      "type": "string",
                      "example": "72.50"
                    }
                  }
                },
                "example": {
                  "status": "updated",
                  "price_eur": "72.50"
                }
              }
            }
          },
          "400": {
            "description": "Bad request — price must be a positive decimal",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_price",
                    "message": "Price must be a positive decimal",
                    "details": {}
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Forbidden — non-admin user",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ForbiddenError"
                }
              }
            }
          }
        }
      }
    },
    "/admin/tenants/{tenant_id}/fees": {
      "put": {
        "tags": ["Admin"],
        "summary": "Update tenant fee configuration",
        "description": "Sets buy/sell fee rates and minimum fee for a specific tenant. Changes take effect on the next transaction.",
        "operationId": "updateTenantFees",
        "security": [{"BearerAuth": []}],
        "parameters": [
          {
            "name": "tenant_id",
            "in": "path",
            "description": "Tenant UUID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["buy_fee_rate", "sell_fee_rate", "min_fee_eur_cents"],
                "properties": {
                  "buy_fee_rate": {
                    "type": "string",
                    "description": "Buy fee rate as decimal string (e.g. 0.005 = 0.5%)",
                    "example": "0.005000"
                  },
                  "sell_fee_rate": {
                    "type": "string",
                    "description": "Sell fee rate as decimal string",
                    "example": "0.005000"
                  },
                  "min_fee_eur_cents": {
                    "type": "integer",
                    "description": "Minimum fee in EUR cents",
                    "example": 50
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Fee configuration updated",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "example": "updated"
                    },
                    "tenant_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                },
                "example": {
                  "status": "updated",
                  "tenant_id": "a0000000-0000-0000-0000-000000000001"
                }
              }
            }
          },
          "400": {
            "description": "Bad request (invalid_params or bad_request)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Forbidden — non-admin user",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ForbiddenError"
                }
              }
            }
          }
        }
      }
    },
    "/admin/etl/trigger": {
      "post": {
        "tags": ["Admin"],
        "summary": "Trigger ETL aggregation job",
        "description": "Manually triggers the ETL aggregation job. The job is idempotent and safe to re-run.",
        "operationId": "triggerEtl",
        "security": [{"BearerAuth": []}],
        "responses": {
          "200": {
            "description": "ETL job triggered",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "example": "triggered"
                    }
                  }
                },
                "example": {
                  "status": "triggered"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Forbidden — non-admin user",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ForbiddenError"
                }
              }
            }
          }
        }
      }
    }
  },
  "tags": [
    {"name": "Health", "description": "System health checks"},
    {"name": "Auth", "description": "Authentication and account management"},
    {"name": "Wallet", "description": "Wallet operations and gold trading"},
    {"name": "Transactions", "description": "Transaction history"},
    {"name": "Insights", "description": "AI-generated trading insights"},
    {"name": "Privacy", "description": "GDPR data export and erasure"},
    {"name": "Admin", "description": "Admin-only operations (requires role=admin in JWT)"}
  ]
}
