{"openapi":"3.0.0","info":{"title":"SolarSight API","version":"1.0.0","description":"API documentation for SolarSight application by Phoenix Solar Group","contact":{"name":"Phoenix Solar Group"}},"servers":[{"url":"https://app.solarsight.io","description":"Application server"}],"components":{"securitySchemes":{"sessionCookie":{"type":"apiKey","in":"cookie","name":"session","description":"Session-based authentication via HTTP-only cookies"}},"parameters":{"page":{"in":"query","name":"page","schema":{"type":"integer","minimum":1,"default":1},"description":"Page number (1-based)"},"pageSize":{"in":"query","name":"pageSize","schema":{"type":"integer","minimum":1,"default":100},"description":"Items per page (default: 100)"}},"schemas":{"Error":{"type":"object","description":"Standard error envelope produced by `errorResponse()`. All routes throw named error classes (ValidationError, UnauthorisedError, ForbiddenError, NotFoundError, TimeoutError, ConflictError, NotAvailableError, ServerError) which the wrap-route handler maps to this shape.","properties":{"message":{"type":"string","description":"Human-readable error message","example":"address is required and must be a string"},"timestamp":{"type":"string","format":"date-time","description":"When the error occurred (server time)","example":"2026-04-08T04:55:30.000Z"},"details":{"type":"string","description":"Additional detail about the error — for ValidationError this is the cause message; for other errors this is typically the same as `message`"}},"required":["message","timestamp","details"]},"HealthStatus":{"type":"object","properties":{"service":{"type":"string","example":"solarsight-application"},"status":{"type":"string","enum":["healthy","unhealthy"],"example":"healthy"},"timestamp":{"type":"string","format":"date-time","example":"2024-01-01T12:00:00.000Z"},"checks":{"type":"object","properties":{"environment":{"$ref":"#/components/schemas/HealthCheck"},"database":{"$ref":"#/components/schemas/HealthCheck"}}}},"required":["service","status","timestamp","checks"]},"HealthCheck":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","unhealthy"]},"details":{"oneOf":[{"type":"string","description":"Error details for single failures"},{"type":"array","items":{"type":"string"},"description":"List of issues for multiple failures"}]}},"required":["status"]},"ChuckJoke":{"type":"object","properties":{"id":{"type":"string","example":"abc123"},"joke":{"type":"string","example":"Chuck Norris can divide by zero."},"categories":{"type":"array","items":{"type":"string"},"example":["dev"]},"url":{"type":"string","format":"uri","example":"https://api.chucknorris.io/jokes/abc123"}},"required":["id","joke","categories","url"]},"ChuckResponse":{"type":"object","properties":{"message":{"type":"string","example":"3 Chuck Norris jokes fetched successfully"},"timestamp":{"type":"string","format":"date-time","example":"2024-01-01T12:00:00.000Z"},"source":{"type":"string","format":"uri","example":"https://api.chucknorris.io"},"count":{"type":"integer","minimum":1,"maximum":10,"example":3},"jokes":{"type":"array","items":{"$ref":"#/components/schemas/ChuckJoke"}}},"required":["message","timestamp","source","count","jokes"]},"User":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000"},"self":{"type":"string","format":"uri","example":"/api/users/123e4567-e89b-12d3-a456-426614174000"},"firstName":{"type":"string","nullable":true,"example":"John"},"lastName":{"type":"string","nullable":true,"example":"Doe"},"email":{"type":"string","format":"email","example":"john.doe@example.com"},"phoneNumber":{"type":"string","nullable":true,"example":"+12025551234"},"phoneNumberVerified":{"type":"boolean","description":"Whether the phone number has been verified via OTP","example":false},"createdAt":{"type":"string","format":"date-time","description":"UTC timestamp when the user was created","example":"2024-01-15T10:30:00.000Z"},"updatedAt":{"type":"string","format":"date-time","description":"UTC timestamp when the user was last updated","example":"2024-01-15T10:30:00.000Z"}},"required":["id","self","email","createdAt","updatedAt"]},"UsersList":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/User"}},"links":{"type":"object","properties":{"self":{"type":"string","format":"uri","example":"/api/users?page=1&pageSize=20"},"next":{"type":"string","format":"uri","example":"/api/users?page=2&pageSize=20"},"prev":{"type":"string","format":"uri","example":"/api/users?page=1&pageSize=20"}},"required":["self"]}},"required":["items","links"]}}},"paths":{},"tags":[]}