Anker Solix API Exploration

April 4, 2026 · View on GitHub

⚠️ IMPORTANT DISCLAIMER

This reference was created through reverse engineering of the Anker App v3.18.0 APK using Blutter (Dart AOT decompiler). The analysis was heavily AI-assisted. This means the content may be:

  • Inaccurate — field names extracted from compiled binary code may be misattributed to the wrong endpoint or context
  • Incomplete — many values, types and constraints are compiled into native ARM64 machine code and could not be recovered
  • Fundamentally wrong in parts — AI interpretation of decompiled assembly can produce plausible-looking but incorrect conclusions

Do not rely on this as authoritative documentation. Every claim should be verified against the live API or the mqtt_monitor tool before use in production code. Anker can change any endpoint, field name or behavior between app versions without notice.

No server-side impact analysis has been performed. This exploration documents what the app sends, not what the server expects or tolerates. Sending malformed, unexpected, or excessive requests to Anker's API or MQTT infrastructure could have unintended consequences including but not limited to account restrictions, device malfunction, or infrastructure impact. Anyone using this data does so entirely at their own risk and responsibility. The authors accept no liability for any consequences arising from the use of this information.


How this was built

SourceMethodWhat it providesConfidence
libapp.so (58MB ARM64 ELF)Blutter AOT decompilation against Dart SDK 3.4.4Endpoint paths, function names, request params, response model fields, required/optional classificationMedium — string constants are reliable, param-to-endpoint attribution may have errors
libapp.so stringsstrings extraction + pattern matchingMQTT field names, model toString() patterns, debug log messagesHigh for field names, low for interpretation
mqtt_monitor sessionsLive MQTT traffic capture on real devices (A17C1, A17X8)Verified MQTT command fields, state change trackingHigh — byte-for-byte verified
APK manifest + resourcesStandard APK analysisDevice model codes, BLE UUIDs, app versionHigh
Model toJson() methods460 class scan across asm/charging/model/Exact request body nesting, field names per modelHigh — compiler-generated serialization
Device-specific logicui/page/device/*/ + helper classes scan95 additional endpoints not in central repositoryMedium — device-specific, may not be available to all accounts
Upstream cross-referencethomluther/anker-solix-api code comparisonNesting verification, missing fields, confirmed constantsHigh — upstream code is community-tested on real devices

Dart SDK: 3.4.4 (stable), snapshot hash d20a1be77c3d3c41b2a5accaee1ce549

APK: Anker App v3.18.0 (build 160), package com.anker.charging, from APKPure


How to use this reference

For API endpoint development

  1. Find the endpoint in endpoints/ by service prefix
  2. Check the function name — it tells you the purpose (e.g., getSafetySocParams = get safety SOC parameters)
  3. Check REQUIRED_FIELDS.md for which params are required vs optional
  4. Check the response model in models/ for expected response fields

For adding new device controls

  1. Check VALIDATION_MODEL.md for the GET→SET flow
  2. The app always queries limits/options first (GET), then sets values (SET)
  3. Validation ranges come from the server, not from the app — you must query them too

For mqtt_monitor decoding sessions

  1. Use the MQTT field name references to identify unknown hex fields
  2. The Blutter-extracted field names tell you what to expect, but hex-to-field assignment requires live verification per Discussion #222

Statistics

  • ~243 unique API endpoints across 12 service prefixes
    • 148 from http_request_repository_impl.dart (initial extraction)
    • +95 from device-specific logic files (breadth scan)
  • 460 toJson() class implementations scanned (depth analysis)
  • 94 response models with field names
  • 180 endpoints with required/optional field classification
  • 33 device setting categories with complete GET→SET flows
  • 82 BLE/IoT SDK action names (65 actions + 14 prop + 3 query)
  • 234+ cross-referenced field types with examples
  • 60 unique product codes (44 IoT + 16 from message models)
  • 30+ enum types with exact API integer values
  • 71 real API response examples from thomluther's code
  • 13 supported countries for dynamic pricing

API Service Prefixes

PrefixEndpointsPrimary Device
/power_service/v1/~130All devices (core API)
/power_service/v2/5AX170, A17EX (newer)
/charging_hes_svc/~55A5101 HES/X1
/charging_energy_service/~12A17B1 System
/charging_hes_dynamic_price_svc/6Dynamic pricing
/charging_disaster_prepared/5A17B1/A5101 Backup & Storm Guard
/charging_pv_svc/5A5140 Solar
/charging_common_svc/3Location
/smart_service/v1/3Anka AI Agent
/charging_imsg_svc/2EV Charger faults
/mini_power/v1/27A2345/A2687 Charger
/app/~10Auth, News, AIOT

param_type Values

For get_site_device_param / set_site_device_param:

The type numbers are already listed in apitypes.py of thomluther/anker-solix-api. What Blutter adds is the function name → purpose mapping.

typeFunction (from Blutter)PurposeStatus
1getSiteGreenModeDeviceParamGreen mode settingsNumber known, purpose new
2getSitePeakTimeDeviceParamPeak/valley time paramsNumber known, purpose new
3getSiteEnablePeakDeviceParamPeak shaving enableNumber known, purpose new
4(native layer)SB1 scheduleKnown (schedule.py has example data)
5getSiteLowerLimitDeviceParamLower limit / min powerNumber known, purpose new
6(native layer)SB2/SB3 scheduleKnown (schedule.py has example data)
7(not in APK v3.18.0)UnknownNumber known, purpose unknown
9(native layer)SB1 in SB2 system scheduleKnown (schedule.py)
12(native layer)SB3 TOU/dynamic price planKnown (schedule.py)
13(native layer)SB3 system configKnown (schedule.py)
16getCombineBoxListDataCombiner box / power dockKnown response, function name from Blutter
18getSafetySocParamsSafety SOC parametersKnown response, function name from Blutter
19setSiteDevicePowerLimitPower limit (SET only)Number not in apitypes.py list, purpose new
20get/setStationCountryCodeStation country codeNumber known, purpose new
23(not in APK v3.18.0)Switch configKnown (schedule.py, minimal)
26getThreePvParam3rd-party PV paramsKnown response, function name from Blutter

Command Flows (new — step-by-step traces)

  • FLOWS.md — Complete traces from UI button to wire bytes for 5 key operations

Covers: Solarbank schedule (dual API+BLE, CRC32, 14 slots), EV Charger start (encoding_type 2 is below Flutter layer!), Smart Plug timer (states 0/4/6), Smart Plug schedule (isEffective INVERTED), Solarbank power limit (4 code paths).


Business Rules (new — not available from mqtt_monitor)

  • BUSINESS_RULES.md — When SET commands are allowed, what values are valid, what guards exist

Extracted from APK controller assembly. These are the conditions the Anker app checks before sending a command — device connectivity, charge priority blocking schedules, value-unchanged skip, SOC defaults, max 7 schedule slots, 4 different power limit paths. This information is not obtainable from mqtt_monitor or API responses.


Device Pages

Start here if you own a specific device:

DevicePageUpstream IssueStatus
Solarbank 2/3 (A17C1/C5)devices/solarbank.md70+ issuesCore supported
Smart Plug (A17X8)devices/smart_plug.md#150Switch in v3.5.0, timer open
EV Charger V1 (A5191)devices/ev_charger.md#322Not yet supported
X1 HES / E10 (A5101)devices/x1_hes_e10.md#274Basic monitoring

Endpoints

ServiceFileEndpointsDescription
power_service/v1/site/power_service_site.md31Core site/station management
charging_hes_svc/charging_hes_svc.md28Home Energy System (X1, A5101)
mini_power/v1/mini_power.md27Prime Charger (A2345, A2687)
passport/passport.md24Authentication, account management
app/app.md18Device management, help, OTA
power_service/v1/app/power_service_app.md17Upgrade, sharing, device config
charging_energy_service/charging_energy_service.md10Power Panel (A17B1)
power_service/v1/app/compatible/power_service_compatible.md12OTA, solar compatibility
power_service/v1/ (other)power_service_other.md12Messages, currency, products
power_service/v1/app/device/power_service_device.md8Device attributes, home load (21 functions, heavily overloaded)
power_service/v1/app/share_site/power_service_share.md5Site member management
power_service/v1/dynamic_price/power_service_dynamic_price.md3Dynamic pricing (Nordpool, Tibber, Octopus)
charging_pv_svc/charging_pv_svc.md4Standalone inverters
power_service/v1/ai_ems/power_service_ai_ems.md2AI Energy Management
charging_common_svc/charging_common_svc.md1Location services
(device-specific)device_specific.md95EV Charger, Generator, HES, Storm Guard, AI, etc.

BLE/MQTT Command Map (new)

  • BLE_COMMAND_MAP.md — Cross-reference of APK command builders with upstream TLV tag assignments

New methodology: By tracing the decompiled command builder functions (field order + Dart Smi constants) and cross-referencing with thomluther's device-tested mqttcmdmap.py, we can infer which APK field name maps to which TLV hex tag — without needing a physical device.

Validated on 5 confirmed commands (A17X8 + A17C1) with 100% match rate. This does NOT replace device testing — it generates hypotheses that device owners can verify in one mqtt_monitor session.

Covers: A17C1/C5 (Solarbank), A17X8 (Smart Plug), A17C0 (SB Gen1), PPS family, A1790 (F3800), A5190 (EV Charger), A5101 (X1 HES), EverFrost, Prime Charger. Includes 20+ NEW commands not in upstream.


Validation Model

Covers: Power limits, home load, SOC reserve, usage modes, grid export, LED, temperature, cutoff, smart plug schedule/timer, EV charger, generator, heat pump, disaster preparedness, and more.

Key finding: the app does not hardcode validation ranges. It queries the server for device-specific min/max/step values and builds the UI dynamically. Developers must follow the same pattern.

Field Types and Examples

  • FIELD_TYPES.md — 234 fields with data types and example values, cross-referenced across Blutter (B), thomluther's API examples (U), and MQTT mappings (M)
  • DART_PYTHON_MAPPING.md — 35 confirmed Dart camelCase → JSON snake_case field name pairs

Endpoint → Fields Direct Mapping

  • PARAM_DATA_STRUCTURES.md — Nested JSON structures for param_data per param_type (cross-referenced with thomluther's Issue #423 device findings)
  • ENDPOINT_FIELDS.md — ~150 endpoints with request parameters and response model mapping (91 with identified response models), plus nesting corrections from 460 toJson() class analysis

JSON Payloads and Examples

  • JSON_EXAMPLES.md — 33 upstream-sourced request payloads + 60 inferred + new parameter discoveries + enum constants + device-specific payload templates (EV charger, generator, SceneInfo feature flags)
  • RESPONSE_EXAMPLES.md — 71 real API response examples from 48 endpoints (extracted from thomluther's documented code)

Enums, Constants, and Product Codes

  • ENUMS.md — 30+ enum types with exact API integer values: EmsModeType (6 modes with API codes 1/4/5/8/9/10), 16-bit EnergyFlowType bitmask, AI mode codes, BLE status codes, MQTT command types, generator modes, PPS work status, price types, 60 product codes, 13 supported countries, TOU schedule templates

Required vs Optional Fields

Derived from conditional branching patterns in decompiled Dart code: fields without a preceding branch instruction are always included in the request body (required), fields with a branch are conditionally added (optional/context-dependent).

97 endpoints have explicit required fields. 63 pass parameters via object construction not visible as string constants.


Response Models

These are Dart class names from the decompiled APK, not Python classes from thomluther's API library. The field names come from fromJson / toJson methods and represent the JSON keys in API responses.

CategoryFileModelsDescription
Othermodels/other.md28Banner, FAQ, messages, ranking, misc
Home Energy Systemmodels/hes.md14A5101/X1 disaster prep, commands, grid config
Account / Sharingmodels/account.md10User, login, site members, validation
Firmware / OTAmodels/firmware.md9Update status, batch device, upgrade records
Pricing / TOUmodels/pricing.md7Dynamic price, TOU, currency
Solarbankmodels/solarbank.md5Home load, site consumption strategy, schedules
WiFi / Installationmodels/connectivity.md4WiFi info, installation inspection
Chargermodels/charger.md4A2345/A2687 charge modes, protocols
Device Managementmodels/device.md3Device list, auto-upgrade
Green Energymodels/energy.md3Scene info, green PPS site detail
Products / Brandsmodels/products.md3Product categories, brands, Shelly platforms
Power Limitsmodels/power.md2Station power limit, device power limit
PPSmodels/pps.md2A5140 status, A1340 charging device

Cross-Reference: Response Model → Endpoint → Setting

Key models that carry validation information:

Response ModelEndpoint GroupProvides
StationPowerLimitModelpower_service_sitemin, max, step, legal_limit, power_limit_option
DevicePowerLimitpower_service_sitemin, max, step, legal_power_limit, region_power_limit
SiteConsumptionStrategyModelpower_service_sitemode_type, min_load, max_load, step, reserved_soc
A17C1DeviceHomeLoadDatapower_service_devicemin_load, max_load, step, ranges, schedule_mode
SiteHomeLoadModelpower_service_sitemin_load, max_load, step, parallel_home_load
AiModeStatusModelpower_service_ai_emsstatus, result, left_time
CheckFunctionModelcharging_hes_svcauto_disaster, peak_shaving, support flags
AutoDisasterPrepareStatusModelcharging_hes_svccode, disasterPrepareStatus, events
DynamicPriceDetailModelpower_service_dynamic_pricetime, price, currency, avgPrice, trend
TouDeviceAttrsModelpower_service_deviceattributes, prices, ranges, reserve_power
GetSiteDeviceParamResponsepower_service_siteparam_data (JSON per param_type)

What this exploration IS and IS NOT

This is useful as:

  • A vocabulary / cheat sheet for mqtt_monitor decoding sessions — knowing the field names that exist in the app helps identify unknown hex fields faster
  • A param_type purpose mapping — types 1, 2, 3, 5, 19, 20 were previously undocumented
  • A validation flow guide — understanding that the app always queries limits before setting values
  • A BLE action inventory — 82 action/prop/query names tell you what controls exist, even if the payload format is unknown
  • An enum reference — EMS modes, energy flow bitmasks, price types, device types, BLE status codes with their exact API integer values
  • A product code registry — 60 known device model codes
  • A starting point for device owners who want to contribute verified mappings

This is NOT:

  • A replacement for thomluther/anker-solix-api — that library has real, tested, working code
  • A source of verified hex-to-field mappings — those require mqtt_monitor sessions per Discussion #222
  • Implementation-ready data — the field names are Dart class names (camelCase), not the snake_case JSON keys used in API responses. See DART_PYTHON_MAPPING.md for 35 confirmed pairs, but coverage is incomplete.
  • A complete API specification — most of the 205 endpoints listed here are already documented in apitypes.py. The incremental value is in the param_type mappings, response model fields, and required/optional classification.
  • Reliable for required/optional — the branch-based detection has known false positives (see REQUIRED_FIELDS.md header)

Known Limitations

  • Dart names ≠ JSON keys — the response model fields are Dart property names (camelCase). The actual API JSON uses snake_case in most cases, but the mapping is not 1:1 — see DART_PYTHON_MAPPING.md for 35 confirmed pairs
  • Partial nesting information — key SET functions now have upstream-confirmed nesting (set_device_attrs, param_data) and structurally inferred nesting from toJson() analysis (disturb_scenes, home_load_data), but many GET response structures still lack full nesting detail
  • Example responses are from thomluther's codeRESPONSE_EXAMPLES.md has 71 examples, but these are copies from thomluther's docstrings, not independently captured
  • Field types (int/string/bool/list) are not extractable — the TLV protocol carries type information in the data packets themselves, and the server responses use standard JSON typing
  • Validation ranges are dynamic (from server), not hardcoded in the app — each device/region may have different min/max/step values
  • Error codes are scattered throughout the code with no central registry found
  • Cooler devices (A17A3-A5 EverFrost) have minimal logic in the Dart layer — most control appears to be BLE-only with limited decompilable structure
  • BLE action names without payload formats — knowing action_set_backup_strategy exists does not help without the binary payload structure, which requires hardware testing
  • 12 response models yielded no field names due to generic deserialization patterns
  • 25 of 205 endpoints are not covered in REQUIRED_FIELDS.md (passport auth + misc)
  • param_type 7 is listed in apitypes.py but not found in APK v3.18.0

Contributing

To improve this reference:

  1. Run mqtt_monitor sessions on your device and compare unknown fields against the model field names listed here
  2. Test API endpoints with the anker-solix-api library and report actual response structures
  3. Report errors — if you find a field attribution that is wrong, please flag it so it can be corrected
  4. Follow the methodology described in Discussion #222

Trademarks

Anker, Solix, Solarbank, EverFrost, and related product names are trademarks of Anker Innovations Limited. Shelly is a trademark of Allterco Robotics. Nordpool, Tibber, Octopus Energy, Amazon, Alexa, and Google are trademarks of their respective owners. OCPP is a standard by the Open Charge Alliance.

This project is not affiliated with, endorsed by, or connected to any of these companies. All trademarks are used here solely for identification and interoperability documentation purposes under fair use.