{"id":35856949,"url":"https://github.com/ruaan-deysel/unraid-api","last_synced_at":"2026-04-15T01:01:46.119Z","repository":{"id":280718948,"uuid":"942326653","full_name":"ruaan-deysel/unraid-api","owner":"ruaan-deysel","description":"An async Python client library for the Unraid GraphQL API","archived":false,"fork":false,"pushed_at":"2026-03-30T22:56:51.000Z","size":387,"stargazers_count":5,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-31T00:33:23.147Z","etag":null,"topics":["pypi","unraid","unraid-api"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ruaan-deysel.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"ruaan-deysel"}},"created_at":"2025-03-03T23:52:21.000Z","updated_at":"2026-03-30T22:56:54.000Z","dependencies_parsed_at":null,"dependency_job_id":"e3393f3d-02db-4229-a08e-6b45b4ebfdf4","html_url":"https://github.com/ruaan-deysel/unraid-api","commit_stats":null,"previous_names":["domalab/unraid-api-client","ruaan-deysel/unraid-api-client","ruaan-deysel/unraid-api"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/ruaan-deysel/unraid-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruaan-deysel%2Funraid-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruaan-deysel%2Funraid-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruaan-deysel%2Funraid-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruaan-deysel%2Funraid-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ruaan-deysel","download_url":"https://codeload.github.com/ruaan-deysel/unraid-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruaan-deysel%2Funraid-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31290858,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["pypi","unraid","unraid-api"],"created_at":"2026-01-08T09:15:57.718Z","updated_at":"2026-04-15T01:01:46.056Z","avatar_url":"https://github.com/ruaan-deysel.png","language":"Python","funding_links":["https://github.com/sponsors/ruaan-deysel"],"categories":[],"sub_categories":[],"readme":"# unraid-api\n\n[![PyPI version](https://badge.fury.io/py/unraid-api.svg)](https://badge.fury.io/py/unraid-api)\n[![Python versions](https://img.shields.io/pypi/pyversions/unraid-api.svg)](https://pypi.org/project/unraid-api/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nAn async Python client library for the Unraid GraphQL API.\n\n## Features\n\n- 🔄 **Async/await** - Built with `aiohttp` for non-blocking operations\n- 🏠 **Home Assistant ready** - Accepts external `aiohttp.ClientSession` for integration\n- 🔒 **Secure by design** - GraphQL variables, no string interpolation\n- 📦 **Typed** - Full type hints with `py.typed` marker (PEP 561)\n- 🧩 **Pydantic models** - Structured response parsing\n- 🔌 **SSL auto-discovery** - Handles Unraid's \"No\", \"Yes\", and \"Strict\" SSL modes\n- ⚡ **Redirect handling** - Supports myunraid.net remote access\n\n## Installation\n\n```bash\npip install unraid-api\n```\n\n## Quick Start\n\n```python\nimport asyncio\nfrom unraid_api import UnraidClient\n\nasync def main():\n    async with UnraidClient(\"192.168.1.100\", \"your-api-key\") as client:\n        # Test connection\n        if await client.test_connection():\n            print(\"Connected!\")\n\n            # Get version info\n            version = await client.get_version()\n            print(f\"Unraid {version['unraid']}, API {version['api']}\")\n\nasyncio.run(main())\n```\n\n## Usage Examples\n\n### Basic Queries\n\n```python\nasync with UnraidClient(host, api_key) as client:\n    # Custom GraphQL query\n    result = await client.query(\"\"\"\n        query {\n            info {\n                os { hostname uptime }\n                cpu { name cores threads }\n                memory { total used }\n            }\n        }\n    \"\"\")\n    print(result[\"info\"][\"os\"][\"hostname\"])\n```\n\n### Docker Container Control\n\n```python\nasync with UnraidClient(host, api_key) as client:\n    # Start a container\n    await client.start_container(\"container:plex\")\n\n    # Stop a container\n    await client.stop_container(\"container:plex\")\n```\n\n### VM Management\n\n```python\nasync with UnraidClient(host, api_key) as client:\n    # Start a VM\n    await client.start_vm(\"vm:windows-11\")\n\n    # Stop a VM\n    await client.stop_vm(\"vm:windows-11\")\n```\n\n### Array Operations\n\n```python\nasync with UnraidClient(host, api_key) as client:\n    # Start/stop array\n    await client.start_array()\n    await client.stop_array()\n\n    # Parity check\n    await client.start_parity_check(correct=True)\n    await client.pause_parity_check()\n    await client.resume_parity_check()\n    await client.cancel_parity_check()\n\n    # Disk spin control\n    await client.spin_up_disk(\"disk:1\")\n    await client.spin_down_disk(\"disk:1\")\n```\n\n### Session Injection (Home Assistant)\n\n```python\nimport aiohttp\nfrom unraid_api import UnraidClient\n\nasync def setup_client(session: aiohttp.ClientSession):\n    \"\"\"Use shared session from Home Assistant.\"\"\"\n    client = UnraidClient(\n        host=\"192.168.1.100\",\n        api_key=\"your-api-key\",\n        session=session,  # Injected session won't be closed by client\n        verify_ssl=False,\n    )\n    return client\n```\n\n### Real-Time Subscriptions (WebSocket)\n\n```python\nasync with UnraidClient(host, api_key) as client:\n    # Stream CPU metrics\n    async for cpu in client.subscribe_cpu_metrics():\n        print(f\"CPU: {cpu.percentTotal}%\")\n\n    # Stream Docker container stats\n    async for stats in client.subscribe_container_stats(\"container:plex\"):\n        print(f\"CPU: {stats.cpuPercent}%, Mem: {stats.memUsage}\")\n\n    # Generic subscription with custom query\n    async for data in client.subscribe(\"subscription { arraySubscription { state } }\"):\n        print(f\"Array state: {data['state']}\")\n```\n\n## Pydantic Models\n\nResponse data can be parsed into typed models:\n\n```python\nfrom unraid_api.models import DockerContainer, VmDomain, UnraidArray\n\n# Parse container data\ncontainer = DockerContainer(**container_data)\nprint(f\"{container.name}: {container.state}\")\n\n# Parse array data\narray = UnraidArray(**array_data)\nprint(f\"Array: {array.state}, Capacity: {array.capacity.usage_percent}%\")\n```\n\n## Exception Handling\n\n```python\nfrom unraid_api import UnraidClient\nfrom unraid_api.exceptions import (\n    UnraidAPIError,\n    UnraidAuthenticationError,\n    UnraidConnectionError,\n    UnraidSSLError,\n    UnraidTimeoutError,\n)\n\nasync with UnraidClient(host, api_key) as client:\n    try:\n        await client.query(\"query { online }\")\n    except UnraidAuthenticationError:\n        print(\"Invalid API key\")\n    except UnraidSSLError:\n        print(\"SSL certificate verification failed\")\n    except UnraidConnectionError:\n        print(\"Cannot reach server\")\n    except UnraidTimeoutError:\n        print(\"Request timed out\")\n    except UnraidAPIError as e:\n        print(f\"API error: {e}\")\n```\n\n## API Reference\n\n### UnraidClient\n\n#### Core Methods\n\n| Method | Description |\n|--------|-------------|\n| `test_connection()` | Test if server is reachable |\n| `get_version()` | Get Unraid and API version |\n| `get_server_info()` | Get server info for device registration |\n| `query(query, variables)` | Execute GraphQL query |\n| `mutate(mutation, variables)` | Execute GraphQL mutation |\n\n#### High-Level Typed Methods (Pydantic Models)\n\n| Method | Returns | Description |\n|--------|---------|-------------|\n| `get_system_metrics()` | `SystemMetrics` | CPU, memory, temperature, power, uptime |\n| `get_system_metrics_safe()` | `SystemMetrics` | Same as above but omits temperature sensors to avoid waking sleeping disks |\n| `typed_get_array()` | `UnraidArray` | Array state, capacity, disks |\n| `typed_get_containers()` | `list[DockerContainer]` | All Docker containers |\n| `typed_get_vms()` | `list[VmDomain]` | All virtual machines |\n| `typed_get_ups_devices()` | `list[UPSDevice]` | UPS devices with battery info |\n| `typed_get_shares()` | `list[Share]` | User shares with usage |\n| `get_notification_overview()` | `NotificationOverview` | Notification counts |\n| `typed_get_vars()` | `Vars` | System configuration variables |\n| `typed_get_registration()` | `Registration` | License information |\n| `typed_get_services()` | `list[Service]` | System services status |\n| `typed_get_flash()` | `Flash` | Flash drive info |\n| `typed_get_owner()` | `Owner` | Owner information |\n| `typed_get_plugins()` | `list[Plugin]` | Installed API plugins |\n| `typed_get_docker_networks()` | `list[DockerNetwork]` | Docker networks |\n| `typed_get_log_files()` | `list[LogFile]` | Available log files |\n| `typed_get_cloud()` | `Cloud` | ⚠️ **Deprecated** — Cloud status |\n| `typed_get_connect()` | `Connect` | ⚠️ **Deprecated** — Connect configuration |\n| `typed_get_remote_access()` | `RemoteAccess` | ⚠️ **Deprecated** — Remote access settings |\n| `get_container_update_statuses()` | `list[ContainerUpdateStatus]` | Docker container update availability |\n| `get_ups_configuration()` | `UPSConfiguration` | UPS hardware/software configuration |\n| `get_display_settings()` | `DisplaySettings` | Display and temperature settings |\n| `get_docker_port_conflicts()` | `DockerPortConflicts` | Docker LAN port conflicts |\n| `get_temperature_metrics()` | `TemperatureMetrics` | Temperature sensors, thresholds, summary |\n\n#### Raw Data Methods\n\n| Method | Returns | Description |\n|--------|---------|-------------|\n| `get_array_status()` | `dict` | Array state and capacity |\n| `get_disks()` | `list[dict]` | Physical disks |\n| `get_shares()` | `list[dict]` | User shares |\n| `get_containers()` | `list[dict]` | Docker containers |\n| `get_vms()` | `list[dict]` | Virtual machines |\n| `get_ups_status()` | `list[dict]` | UPS devices |\n| `get_notifications()` | `list[dict]` | Notifications |\n| `get_parity_history()` | `list[dict]` | Parity check history |\n| `get_services()` | `list[dict]` | System services |\n| `get_plugins()` | `list[dict]` | Installed plugins |\n| `get_docker_networks()` | `list[dict]` | Docker networks |\n| `get_log_files()` | `list[dict]` | Log files |\n| `get_log_file(path)` | `dict` | Log file contents |\n\n#### Control Methods\n\n| Method | Description |\n|--------|-------------|\n| `start_container(id)` | Start Docker container |\n| `stop_container(id)` | Stop Docker container |\n| `restart_container(id)` | Restart Docker container |\n| `start_vm(id)` | Start VM |\n| `stop_vm(id)` | Stop VM (graceful) |\n| `force_stop_vm(id)` | Force stop VM |\n| `pause_vm(id)` | Pause VM |\n| `resume_vm(id)` | Resume paused VM |\n| `start_array()` | Start disk array |\n| `stop_array()` | Stop disk array |\n| `start_parity_check(correct)` | Start parity check |\n| `pause_parity_check()` | Pause parity check |\n| `resume_parity_check()` | Resume parity check |\n| `cancel_parity_check()` | Cancel parity check |\n| `spin_up_disk(id)` | Spin up disk |\n| `spin_down_disk(id)` | Spin down disk |\n\n#### Subscription Methods (WebSocket)\n\n| Method | Yields | Description |\n|--------|--------|-------------|\n| `subscribe(subscription, variables)` | `dict` | Generic GraphQL subscription (async generator) |\n| `subscribe_container_stats(container_id)` | `DockerContainerStats` | Real-time Docker container resource metrics |\n| `subscribe_cpu_metrics()` | `CpuMetrics` | CPU usage per-core and total |\n| `subscribe_cpu_telemetry()` | `CpuTelemetryMetrics` | CPU power and temperature |\n| `subscribe_memory_metrics()` | `MemoryMetrics` | System memory usage |\n| `subscribe_ups_updates()` | `dict` | UPS state changes (raw) |\n| `subscribe_array_updates()` | `ArraySubscriptionUpdate` | Array state and capacity changes |\n| `subscribe_temperature_metrics()` | `TemperatureMetrics` | Temperature sensor updates |\n\n### Models\n\n#### System Models\n- `ServerInfo` - Server info for HA device registration\n- `SystemInfo` - System information\n- `SystemMetrics` - CPU, memory, temperature, power, uptime metrics (includes `TemperatureMetrics`)\n- `Vars` - System configuration variables\n- `Registration` - License/registration info\n- `Flash` - Flash drive information\n- `Owner` - Server owner info\n\n#### Storage Models\n- `UnraidArray` - Array state and disks\n- `ArrayDisk` - Individual array disk\n- `ArrayCapacity` - Capacity calculations\n- `PhysicalDisk` - Physical disk details (serialNum, firmwareRevision, partitions)\n- `DiskPartition` - Disk partition info (name, fsType, size)\n- `Share` - User share with usage and comment\n\n#### Docker/VM Models\n- `DockerContainer` - Container with ports, state, mounts, Tailscale, template ports\n- `DockerNetwork` - Docker network configuration\n- `VmDomain` - Virtual machine (id, name, state)\n- `TailscaleStatus` - Tailscale hostname, DNS name, and online status\n- `ContainerTemplatePort` - Template port configuration\n- `ContainerUpdateStatus` - Container update availability\n- `DockerPortConflicts` - Port conflict detection\n\n#### Service Models\n- `Service` - System service status\n- `UPSDevice` - UPS with battery/power info\n- `UPSConfiguration` - UPS hardware/software configuration\n- `Plugin` - Installed plugin info\n- `LogFile` - Log file metadata\n- `LogFileContent` - Log file contents\n- `DisplaySettings` - Display and temperature threshold settings\n- `KeyFile` - Registration key file location and contents\n\n#### Network Models (Deprecated)\n\n- `Cloud` - Unraid Connect cloud status *(deprecated — removed from live API)*\n- `Connect` - Connect configuration *(deprecated — removed from live API)*\n- `RemoteAccess` - Remote access settings *(deprecated — removed from live API)*\n\n#### Notification Models\n- `Notification` - System notification (with link, type, formattedTimestamp)\n- `NotificationOverview` - Notification counts\n- `NotificationOverviewCounts` - Per-importance notification counts\n\n#### Subscription Models\n- `CpuCore` - Per-core CPU usage (percentTotal, percentUser, percentSystem, percentIdle, percentNice, percentIrq, percentGuest, percentSteal)\n- `CpuMetrics` - CPU usage with per-core breakdown\n- `CpuTelemetryMetrics` - CPU power and temperature\n- `MemoryUtilization` - Full memory data (total, used, free, available, active, buffcache, swap)\n- `MemoryMetrics` - System memory total/used/free\n- `ArraySubscriptionUpdate` - Array state and capacity updates\n- `DockerContainerStats` - Real-time container resource metrics\n- `TemperatureMetrics` - Temperature sensors with summary and per-sensor data\n- `TemperatureSensor` - Individual sensor with reading, thresholds, and status helpers\n- `TemperatureReading` - Temperature value, unit, and status\n- `TemperatureSummary` - Average, hottest, coolest, warning/critical counts\n- `SensorType` - Enum: CPU_PACKAGE, CPU_CORE, DISK, NVME, CUSTOM\n- `TemperatureUnit` - Enum: CELSIUS, FAHRENHEIT\n- `TemperatureStatus` - Enum: NORMAL, WARNING, CRITICAL, UNKNOWN\n\n### Exceptions\n\n| Exception | Parent | Description |\n|-----------|--------|-------------|\n| `UnraidAPIError` | `Exception` | Base exception for all API errors |\n| `UnraidConnectionError` | `UnraidAPIError` | Connection failures |\n| `UnraidSSLError` | `UnraidConnectionError` | SSL certificate verification failures |\n| `UnraidAuthenticationError` | `UnraidAPIError` | Authentication failures (invalid API key) |\n| `UnraidTimeoutError` | `UnraidAPIError` | Request timeout |\n\n**Note:** `UnraidSSLError` inherits from `UnraidConnectionError`, so it can be caught with either exception type for backwards compatibility.\n\n## Requirements\n\n- Python 3.14+\n- Unraid 7.2.4+ with latest Unraid API\n- API key with appropriate permissions\n\n## Development\n\n```bash\n# Clone repository\ngit clone https://github.com/ruaan-deysel/unraid-api.git\ncd unraid-api\n\n# Install dependencies with uv\nuv sync --all-extras\n\n# Run tests\nuv run pytest tests/ -v --cov=src/unraid_api\n\n# Lint and type check\nuv run ruff check .\nuv run ruff format .\nuv run mypy src/\n```\n\n## License\n\nMIT License - see [LICENSE](LICENSE) for details.\n\n## Contributing\n\nContributions welcome! Please ensure:\n1. Tests are written first (TDD)\n2. No linting errors (`ruff check . \u0026\u0026 mypy src/`)\n3. GraphQL variables used (no string interpolation)\n\n## Links\n\n- [Official Unraid API Repository](https://github.com/unraid/api)\n- [GraphQL API Reference](UNRAIDAPI.md)\n- [PyPI Package](https://pypi.org/project/unraid-api/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruaan-deysel%2Funraid-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fruaan-deysel%2Funraid-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruaan-deysel%2Funraid-api/lists"}