API Reference
Client
Client for the Pinergy smart-meter API.
Authentication is performed lazily — the first call to any API method that
requires a token will trigger :meth:login automatically if no token has
been set yet. Lazy login is thread-safe: concurrent first calls perform a
single login. If the server rejects a token (HTTP 401), the stale token is
dropped so the next call re-authenticates transparently.
The client owns a pooled :class:requests.Session (keep-alive connection
reuse). Use it as a context manager, or call :meth:close when done, to
release the pool deterministically::
with PinergyClient("user@example.com", "my-password") as client:
balance = client.get_balance()
print(f"Balance: €{balance.credit_balance:.2f}")
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
email
|
str
|
Registered Pinergy account email address. |
required |
password
|
str
|
Plaintext account password (hashed internally before sending). |
required |
base_url
|
str
|
Override the API base URL (useful for testing). |
_BASE_URL
|
timeout
|
float
|
Default request timeout in seconds, applied to every network call. Accepts a float for sub-second precision. |
30.0
|
Source code in src/pypinergy/client.py
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 | |
is_authenticated
property
True if an auth token is currently held.
check_email(email)
Check whether an email address has a registered Pinergy account.
This endpoint does not require authentication.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
email
|
str
|
Email address to check. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if the address is registered. |
Source code in src/pypinergy/client.py
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 | |
close()
Release the underlying HTTP connection pool.
Idempotent — safe to call more than once. The client must not be used for further API calls after closing.
Source code in src/pypinergy/client.py
101 102 103 104 105 106 107 | |
compare_usage()
Compare this home's usage with similar homes.
Returns:
| Type | Description |
|---|---|
CompareResponse
|
class: |
CompareResponse
|
and |
Example::
cmp = client.compare_usage()
d = cmp.day
print(f"Today: {d.kwh.users_home:.1f} kWh vs avg {d.kwh.average_home:.1f} kWh")
Source code in src/pypinergy/client.py
360 361 362 363 364 365 366 367 368 369 370 371 372 373 | |
get_active_topups()
Return scheduled and automatic top-up configurations.
Returns:
| Type | Description |
|---|---|
ActiveTopUpsResponse
|
class: |
Source code in src/pypinergy/client.py
348 349 350 351 352 353 354 | |
get_balance()
Return the current credit balance and meter status.
Returns:
| Type | Description |
|---|---|
BalanceResponse
|
class: |
Example::
bal = client.get_balance()
print(f"€{bal.credit_balance:.2f} — {bal.top_up_in_days} days remaining")
if bal.credit_low:
print("Warning: credit is low!")
Source code in src/pypinergy/client.py
329 330 331 332 333 334 335 336 337 338 339 340 341 342 | |
get_config_info()
Return valid top-up amounts and alert thresholds.
Returns:
| Type | Description |
|---|---|
ConfigInfoResponse
|
class: |
Source code in src/pypinergy/client.py
379 380 381 382 383 384 385 | |
get_defaults_info()
Return reference data for house and heating types.
Returns:
| Type | Description |
|---|---|
DefaultsInfoResponse
|
class: |
Source code in src/pypinergy/client.py
387 388 389 390 391 392 393 | |
get_level_pay_usage()
Return half-hourly interval data for level-pay customers.
Returns:
| Type | Description |
|---|---|
LevelPayUsageResponse
|
class: |
Source code in src/pypinergy/client.py
317 318 319 320 321 322 323 | |
get_notification_preferences()
Return the account's notification channel preferences.
Returns:
| Type | Description |
|---|---|
NotificationPreferences
|
class: |
Source code in src/pypinergy/client.py
399 400 401 402 403 404 405 | |
get_usage()
Return daily, weekly, and monthly aggregated usage.
Returns:
| Type | Description |
|---|---|
UsageResponse
|
class: |
UsageResponse
|
and |
Example::
usage = client.get_usage()
for entry in usage.day:
print(f"{entry.date:%Y-%m-%d} {entry.kwh:.2f} kWh €{entry.amount:.2f}")
Source code in src/pypinergy/client.py
302 303 304 305 306 307 308 309 310 311 312 313 314 315 | |
get_version()
Return the raw version config JSON (unauthenticated).
Returns:
| Type | Description |
|---|---|
Dict[str, Any]
|
Parsed JSON dict from |
Source code in src/pypinergy/client.py
496 497 498 499 500 501 502 | |
login()
Authenticate with the Pinergy API and store the session token.
Thread-safe — concurrent callers serialize on an internal lock.
Raises:
| Type | Description |
|---|---|
PinergyAuthError
|
If credentials are invalid, or this client was
explicitly logged out (credentials are discarded on
:meth: |
PinergyTimeoutError
|
If the request times out. |
PinergyHTTPError
|
On network-level errors. |
PinergyResponseError
|
If the response body is malformed or is
missing the |
Returns:
| Type | Description |
|---|---|
LoginResponse
|
class: |
Source code in src/pypinergy/client.py
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 | |
logout()
Clear the stored auth token, effectively ending the session.
Also clears the cached password hash so automatic re-login does not happen
transparently after explicit logout. Subsequent API calls raise
:class:PinergyAuthError immediately, without touching the network.
Source code in src/pypinergy/client.py
266 267 268 269 270 271 272 273 274 275 | |
top_up(amount, cc_token)
Initiate an instant top-up using a saved payment card.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
amount
|
float
|
The amount to top up (€). Must be a positive value from the
list of valid top-up amounts returned by :meth: |
required |
cc_token
|
str
|
The tokenised credit card identifier. Use
:attr: |
required |
Returns:
| Type | Description |
|---|---|
TopUpResponse
|
class: |
TopUpResponse
|
and transaction details. |
Source code in src/pypinergy/client.py
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 | |
update_device_token(device_token='', device_type='android', os_version='')
Register or update the FCM push-notification token.
For headless / server-side use you can pass an empty string for device_token or skip this call entirely.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
device_token
|
str
|
Firebase Cloud Messaging token. |
''
|
device_type
|
str
|
Platform string (e.g. |
'android'
|
os_version
|
str
|
OS version string. |
''
|
Returns:
| Type | Description |
|---|---|
bool
|
True on success. |
Source code in src/pypinergy/client.py
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 | |
update_notification_preferences(sms, email, phone)
Update the account's notification channel preferences.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sms
|
bool
|
Enable or disable SMS notifications. |
required |
email
|
bool
|
Enable or disable email notifications. |
required |
phone
|
bool
|
Enable or disable phone notifications. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True on success. |
Source code in src/pypinergy/client.py
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 | |
Exceptions
Bases: Exception
Base exception for all pypinergy errors.
Source code in src/pypinergy/exceptions.py
4 5 | |
Bases: PinergyError
Raised when the API returns a non-success response.
Attributes:
| Name | Type | Description |
|---|---|---|
error_code |
The integer error code returned by the API. |
|
message |
The human-readable error message from the API. |
Source code in src/pypinergy/exceptions.py
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | |
Bases: PinergyError
Raised when authentication fails or the session has expired.
Source code in src/pypinergy/exceptions.py
8 9 | |
Bases: PinergyError
Raised when an unexpected HTTP-level error occurs (e.g. 5xx, timeout).
Source code in src/pypinergy/exceptions.py
29 30 | |
Bases: PinergyHTTPError
Raised when a request exceeds the configured timeout.
Subclasses :class:PinergyHTTPError, so existing except PinergyHTTPError
handlers continue to catch timeouts exactly as before.
Source code in src/pypinergy/exceptions.py
33 34 35 36 37 38 | |
Bases: PinergyError, ValueError
Raised when the API returns a payload that cannot be interpreted.
Covers malformed JSON bodies, non-object top-level JSON, and successful
responses that are missing structurally required fields (e.g. a login
response without an auth_token).
Also subclasses :class:ValueError, so callers that previously caught the
raw JSON decoding error (a ValueError subclass) keep working.
Source code in src/pypinergy/exceptions.py
41 42 43 44 45 46 47 48 49 50 | |
Login Models
Successful login payload.
Source code in src/pypinergy/models.py
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | |
Authenticated user profile.
Source code in src/pypinergy/models.py
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | |
Property details associated with the account.
Source code in src/pypinergy/models.py
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | |
Saved payment card summary.
Source code in src/pypinergy/models.py
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | |
Usage Models
Aggregated usage across day / week / month buckets.
Source code in src/pypinergy/models.py
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 | |
day
instance-attribute
Last 7 days — one entry per day.
month
instance-attribute
Last 11 months — one entry per month.
week
instance-attribute
Last 8 weeks — one entry per week.
A single aggregated usage period (day / week / month).
Source code in src/pypinergy/models.py
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | |
amount
instance-attribute
Cost in euros (€).
co2
instance-attribute
CO₂ in kg (typically 0.0 for renewable supply).
date
instance-attribute
UTC datetime for the start of the period.
date_dt
property
Alias for :attr:date, following the *_dt naming convention.
:attr:date remains fully supported; both names refer to the same value.
date_ts
instance-attribute
Raw Unix timestamp (start of period).
kwh
instance-attribute
Energy consumed in kilowatt-hours.
Half-hourly interval data for level pay customers.
Source code in src/pypinergy/models.py
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 | |
Half-hourly label and kWh per tariff band.
Source code in src/pypinergy/models.py
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | |
day_kwh
instance-attribute
Mapping of tariff band name (e.g. "Standard") to kWh consumed.
Balance Model
Current account balance and meter status.
Source code in src/pypinergy/models.py
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 | |
credit_balance
instance-attribute
Current credit balance in euros (€).
credit_low
instance-attribute
True when balance is below the configured alert threshold.
emergency_credit
instance-attribute
True when the meter is drawing on emergency credit.
last_reading_dt
property
Alias for :attr:last_reading, following the *_dt naming convention.
:attr:last_reading remains fully supported; both names refer to the same value.
last_top_up_dt
property
Alias for :attr:last_top_up_time, following the *_dt naming convention.
:attr:last_top_up_time remains fully supported; both names refer to the same value.
power_off
instance-attribute
True when supply has been disconnected.
top_up_in_days
instance-attribute
Estimated days until credit is exhausted.
Top-Up Models
Scheduled and automatic top-up configurations.
Source code in src/pypinergy/models.py
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 | |
A top-up scheduled for a fixed calendar day.
Source code in src/pypinergy/models.py
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 | |
current_user
instance-attribute
False when this entry belongs to another resident on the same premises.
Comparison Models
Comparison of this home vs. similar homes.
Source code in src/pypinergy/models.py
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 | |
Comparison data for a single period (day / week / month).
Source code in src/pypinergy/models.py
454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 | |
Paired user vs. average-home figures for a metric.
Source code in src/pypinergy/models.py
438 439 440 441 442 443 444 445 446 447 448 449 450 451 | |
Configuration Models
Valid top-up amounts and balance alert thresholds.
Source code in src/pypinergy/models.py
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 | |
Reference data for house and heating types.
Source code in src/pypinergy/models.py
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 | |
Source code in src/pypinergy/models.py
517 518 519 520 521 522 523 524 525 | |
Source code in src/pypinergy/models.py
528 529 530 531 532 533 534 535 536 | |
Notification Model
User notification channel preferences.
Source code in src/pypinergy/models.py
576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 | |