{
    "openapi": "3.1.0",
    "info": {
        "title": "Ski Manager API",
        "version": "1.0.0",
        "description": "Read-only game data used by the Ski Manager mobile apps, plus a health check. Endpoints return the signed-in player's data when called with a ski-manager.net session cookie, and public or demo data otherwise.",
        "contact": {
            "name": "Ski Manager",
            "url": "https://ski-manager.net/contact"
        }
    },
    "servers": [
        {
            "url": "https://ski-manager.net"
        }
    ],
    "paths": {
        "/api/resort-data": {
            "get": {
                "operationId": "getResortData",
                "summary": "Trail map, season, weather and (when signed in) your resort",
                "description": "Returns the active map segments and sectors, the current season and weather. With a session cookie it also includes your finances, lifts, slopes and buildings; without one, finances are a demo baseline and the player arrays are empty.",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "success"
                                        },
                                        "server_time": {
                                            "type": "integer",
                                            "description": "Unix timestamp"
                                        },
                                        "resort_map": {
                                            "type": "string",
                                            "example": "ParkCity"
                                        },
                                        "map_image_url": {
                                            "type": "string",
                                            "format": "uri"
                                        },
                                        "season": {
                                            "type": "object"
                                        },
                                        "game_day": {
                                            "type": "integer"
                                        },
                                        "finances": {
                                            "type": "object"
                                        },
                                        "segments": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer"
                                                    },
                                                    "type": {
                                                        "type": "string",
                                                        "description": "lift, downhill, snowpark, ..."
                                                    },
                                                    "difficulty": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "enum": [
                                                            "green",
                                                            "blue",
                                                            "black",
                                                            "double_black",
                                                            null
                                                        ]
                                                    },
                                                    "name": {
                                                        "type": "string"
                                                    },
                                                    "points": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "number"
                                                            }
                                                        }
                                                    },
                                                    "length_meters": {
                                                        "type": "integer"
                                                    },
                                                    "sector": {
                                                        "type": "integer"
                                                    }
                                                }
                                            }
                                        },
                                        "sectors": {
                                            "type": "array",
                                            "items": {
                                                "type": "object"
                                            }
                                        },
                                        "player_lifts": {
                                            "type": "array",
                                            "items": {
                                                "type": "object"
                                            }
                                        },
                                        "player_slopes": {
                                            "type": "array",
                                            "items": {
                                                "type": "object"
                                            }
                                        },
                                        "buildings": {
                                            "type": "array",
                                            "items": {
                                                "type": "object"
                                            }
                                        },
                                        "weather": {
                                            "type": "object"
                                        }
                                    },
                                    "required": [
                                        "status",
                                        "segments",
                                        "sectors"
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/leaderboard": {
            "get": {
                "operationId": "getLeaderboard",
                "summary": "Top 50 resorts",
                "description": "Ranked by cash plus lifetime income.",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "type": "object",
                                        "properties": {
                                            "id": {
                                                "type": "integer"
                                            },
                                            "username": {
                                                "type": "string"
                                            },
                                            "resortName": {
                                                "type": "string"
                                            },
                                            "cash": {
                                                "type": "integer"
                                            },
                                            "reputation": {
                                                "type": "integer"
                                            },
                                            "rankPosition": {
                                                "type": "integer"
                                            }
                                        },
                                        "required": [
                                            "id",
                                            "username",
                                            "cash",
                                            "rankPosition"
                                        ]
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/auth": {
            "post": {
                "operationId": "mobileDemoAuth",
                "summary": "Demo sign-in for the mobile apps",
                "description": "Returns a random token for the mobile demo. It does not check credentials, and no other endpoint requires the token.",
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "username": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "authenticated"
                                        },
                                        "token": {
                                            "type": "string"
                                        },
                                        "username": {
                                            "type": "string"
                                        },
                                        "server": {
                                            "type": "string",
                                            "format": "uri"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/sync": {
            "post": {
                "operationId": "mobileSync",
                "summary": "Mobile sync acknowledgement",
                "description": "Acknowledges a sync from the mobile apps and echoes back the cash value sent. Nothing is saved.",
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "cash": {
                                        "type": "integer"
                                    },
                                    "game_day": {
                                        "type": "integer"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "example": "success"
                                        },
                                        "synced_at": {
                                            "type": "string"
                                        },
                                        "server_time": {
                                            "type": "integer"
                                        },
                                        "server_game_day": {
                                            "type": "integer"
                                        },
                                        "confirmed_cash": {
                                            "type": "integer"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/health": {
            "get": {
                "operationId": "getHealth",
                "summary": "Service health",
                "description": "Database and storage checks. 200 when healthy, 503 when degraded.",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "ok",
                                                "degraded"
                                            ]
                                        },
                                        "app": {
                                            "type": "string"
                                        },
                                        "timestamp": {
                                            "type": "string",
                                            "format": "date-time"
                                        },
                                        "checks": {
                                            "type": "object"
                                        }
                                    },
                                    "required": [
                                        "status"
                                    ]
                                }
                            }
                        }
                    },
                    "503": {
                        "description": "Degraded: a check failed"
                    }
                }
            }
        }
    }
}