Documentation
¶
Overview ¶
Package pinergy provides an idiomatic Go client for the Pinergy electricity API (https://api.pinergy.ie). The client handles authentication, rate limiting, exponential-backoff retries, and in-memory TTL caching so that callers receive current data without hammering the upstream service.
Quick start ¶
client := pinergy.NewClient()
ctx := context.Background()
if err := client.Login(ctx, "user@example.com", "password"); err != nil {
log.Fatal(err)
}
bal, err := client.GetBalance(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Balance: €%.2f\n", bal.Balance)
Authentication ¶
Call Client.Login once. The returned auth token is stored internally and attached as an auth_token header on all subsequent authenticated requests. The client is safe for concurrent use from multiple goroutines after Login.
Rate limiting ¶
The client enforces a token-bucket rate limit (default 2 req/s, burst 5) using golang.org/x/time/rate. Every request waits for a token before being dispatched. The wait respects the caller's context.Context, so cancellation propagates correctly.
Retries ¶
Transient failures (HTTP 5xx, network errors) are retried automatically with exponential back-off and jitter. 4xx responses are never retried.
Caching ¶
GET responses are cached in memory with per-endpoint TTLs. Caching reduces API calls when the same data is requested frequently. Use WithCacheDisabled to opt out, or WithCacheTTL to adjust individual TTLs.
Index ¶
- Constants
- Variables
- type APIError
- type ActiveTopUpsResponse
- type BalanceResponse
- type Client
- func (c *Client) CacheFlush()
- func (c *Client) CacheInvalidate(endpoint string)
- func (c *Client) CheckEmail(ctx context.Context, email string) error
- func (c *Client) GetActiveTopups(ctx context.Context) (*ActiveTopUpsResponse, error)
- func (c *Client) GetBalance(ctx context.Context) (*BalanceResponse, error)
- func (c *Client) GetCompare(ctx context.Context) (*CompareResponse, error)
- func (c *Client) GetConfigInfo(ctx context.Context) (*ConfigInfoResponse, error)
- func (c *Client) GetDefaultsInfo(ctx context.Context) (*DefaultsInfoResponse, error)
- func (c *Client) GetLevelPayUsage(ctx context.Context) (*LevelPayUsageResponse, error)
- func (c *Client) GetNotifications(ctx context.Context) (*NotificationResponse, error)
- func (c *Client) GetUsage(ctx context.Context) (*UsageResponse, error)
- func (c *Client) GetVersion(ctx context.Context) (*VersionResponse, error)
- func (c *Client) IsAuthenticated() bool
- func (c *Client) IsLevelPay() bool
- func (c *Client) Login(ctx context.Context, email, password string) error
- func (c *Client) LoginFull(ctx context.Context, email, password string) (*LoginResponse, error)
- func (c *Client) Logout()
- func (c *Client) TopUp(ctx context.Context, amount int, ccToken string) (*TopUpResponse, error)
- func (c *Client) UpdateDeviceToken(ctx context.Context, deviceToken, deviceType, osVersion string) error
- func (c *Client) UpdateNotificationPreferences(ctx context.Context, sms, email, phone bool) (*NotificationResponse, error)
- type CompareMetric
- type ComparePeriod
- type CompareResponse
- type ConfigInfoResponse
- type CreditCard
- type DefaultsInfoResponse
- type ErrorCode
- type House
- type LevelPayDaily
- type LevelPayDailyValue
- type LevelPayUsageData
- type LevelPayUsageResponse
- type LoginRequest
- type LoginResponse
- type NamedItem
- type NotificationResponse
- type Option
- func WithBaseURL(u string) Option
- func WithCacheDisabled() Option
- func WithCacheTTL(endpoint string, ttl time.Duration) Option
- func WithHTTPClient(hc *http.Client) Option
- func WithInsecureHTTP() Option
- func WithMaxResponseBytes(n int64) Option
- func WithMaxRetries(n int) Option
- func WithRateLimit(r rate.Limit, burst int) Option
- func WithRetryDelays(base, max time.Duration) Option
- func WithTimeout(d time.Duration) Option
- type ScheduledTopUp
- type TopUpRequest
- type TopUpResponse
- type UnixTime
- type UpdateDeviceTokenRequest
- type UpdateNotificationPreferencesRequest
- type UsageEntry
- type UsageResponse
- type User
- type VersionResponse
Constants ¶
const ( // DefaultBaseURL is the Pinergy API base URL. DefaultBaseURL = "https://api.pinergy.ie" // DefaultTimeout is the default HTTP request timeout. DefaultTimeout = 30 * time.Second // DefaultRateLimit is the default sustained request rate (requests per second). DefaultRateLimit = rate.Limit(2) // DefaultBurst is the default burst size for the rate limiter. DefaultBurst = 5 // DefaultMaxRetries is the default number of total attempts (1 initial + N-1 retries). DefaultMaxRetries = 3 // DefaultRetryBaseDelay is the base delay for exponential back-off. DefaultRetryBaseDelay = 500 * time.Millisecond // DefaultRetryMaxDelay caps the back-off delay. DefaultRetryMaxDelay = 10 * time.Second // DefaultMaxResponseBytes is the maximum number of bytes the client will // read from a single HTTP response body. Responses exceeding this limit // are truncated, which will typically cause a JSON decode error. DefaultMaxResponseBytes int64 = 2 << 20 // 2 MB )
Variables ¶
var ( ErrUnauthorized = &APIError{Code: ErrCodeUnauthorized} // ErrAuthRequired is returned when Login has not been called before an authenticated endpoint. ErrAuthRequired = &APIError{Code: ErrCodeAuthRequired} // ErrEmailNotFound is returned when CheckEmail finds the address is not registered. ErrEmailNotFound = &APIError{Code: ErrCodeEmailNotFound} // ErrRateLimited is returned when the API returns HTTP 429. ErrRateLimited = &APIError{Code: ErrCodeRateLimited} )
Sentinel errors for use with errors.Is.
Functions ¶
This section is empty.
Types ¶
type APIError ¶
type APIError struct {
// Code identifies the error category.
Code ErrorCode
// StatusCode is the HTTP status code, or 0 if not applicable.
StatusCode int
// Message is a human-readable description.
Message string
// Err is the underlying wrapped error, if any.
Err error
}
APIError is returned for all Pinergy client errors. Use errors.As to extract it, or errors.Is against the sentinel variables.
type ActiveTopUpsResponse ¶
type ActiveTopUpsResponse struct {
Success bool `json:"success"`
Scheduled []ScheduledTopUp `json:"scheduled"`
AutoTopUps []json.RawMessage `json:"auto_top_ups"`
}
ActiveTopUpsResponse is the response from GET /api/activetopups/.
type BalanceResponse ¶
type BalanceResponse struct {
Success bool `json:"success"`
Balance float64 `json:"balance"`
TopUpInDays int `json:"top_up_in_days"`
PendingTopUp bool `json:"pending_top_up"`
PendingTopUpBy string `json:"pending_top_up_by"`
LastTopUpTime UnixTime `json:"last_top_up_time"`
LastTopUpAmount float64 `json:"last_top_up_amount"`
CreditLow bool `json:"credit_low"`
EmergencyCredit bool `json:"emergency_credit"`
PowerOff bool `json:"power_off"`
LastReading UnixTime `json:"last_reading"`
}
BalanceResponse is the response from GET /api/balance/.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is the Pinergy API client. It is safe for concurrent use from multiple goroutines after a successful Client.Login.
func NewClient ¶
NewClient creates a new Client with the given options applied over the default configuration.
func (*Client) CacheFlush ¶
func (c *Client) CacheFlush()
CacheFlush clears all cached responses. Useful after a top-up to force a fresh balance read.
func (*Client) CacheInvalidate ¶
CacheInvalidate removes the cached response for a specific endpoint.
func (*Client) CheckEmail ¶
CheckEmail checks whether email is registered in the Pinergy system. This endpoint does not require authentication and is typically called before presenting the login screen.
Privacy note: the Pinergy API requires the email address to be sent as a custom HTTP header (email_address). HTTP headers are commonly captured by reverse proxies, CDNs, and WAFs, so the email may appear in infrastructure access logs with different retention policies than application data. Callers handling EU personal data should account for this in their GDPR data-flow documentation.
Returns ErrEmailNotFound if the address is not registered.
func (*Client) GetActiveTopups ¶
func (c *Client) GetActiveTopups(ctx context.Context) (*ActiveTopUpsResponse, error)
GetActiveTopups returns the scheduled and automatic top-up configurations for the account. Results are cached for 2 minutes by default.
func (*Client) GetBalance ¶
func (c *Client) GetBalance(ctx context.Context) (*BalanceResponse, error)
GetBalance returns the current credit balance and related information. Results are cached for 60 seconds by default.
Call Client.CacheInvalidate("/api/balance/") or Client.CacheFlush after a top-up to force a fresh read.
func (*Client) GetCompare ¶
func (c *Client) GetCompare(ctx context.Context) (*CompareResponse, error)
GetCompare returns daily, weekly, and monthly energy usage for the user's home compared against similar homes on the Pinergy network. Results are cached for 15 minutes by default.
func (*Client) GetConfigInfo ¶
func (c *Client) GetConfigInfo(ctx context.Context) (*ConfigInfoResponse, error)
GetConfigInfo returns the valid top-up amounts and credit alert thresholds configured for the account. Results are cached for 30 minutes by default.
func (*Client) GetDefaultsInfo ¶
func (c *Client) GetDefaultsInfo(ctx context.Context) (*DefaultsInfoResponse, error)
GetDefaultsInfo returns reference data for house types and heating types used when updating the account profile. Results are cached for 30 minutes by default.
func (*Client) GetLevelPayUsage ¶
func (c *Client) GetLevelPayUsage(ctx context.Context) (*LevelPayUsageResponse, error)
GetLevelPayUsage returns half-hourly interval data for level-pay customers. Results are cached for 5 minutes by default.
This endpoint is only relevant when LoginResponse.IsLevelPay is true. Its response does not use the standard success envelope.
func (*Client) GetNotifications ¶
func (c *Client) GetNotifications(ctx context.Context) (*NotificationResponse, error)
GetNotifications returns the current notification preferences for the account. Results are cached for 5 minutes by default.
func (*Client) GetUsage ¶
func (c *Client) GetUsage(ctx context.Context) (*UsageResponse, error)
GetUsage returns aggregated energy usage grouped by day (last 7 days), week (last 8 weeks), and month (last 11 months). Results are cached for 5 minutes by default.
func (*Client) GetVersion ¶
func (c *Client) GetVersion(ctx context.Context) (*VersionResponse, error)
GetVersion returns the minimum required and current app version information. This endpoint does not require authentication. Results are cached for 10 minutes by default.
func (*Client) IsAuthenticated ¶
IsAuthenticated reports whether the client currently holds a valid auth token. A true return does not guarantee the token is still accepted by the server.
func (*Client) IsLevelPay ¶ added in v1.2.0
IsLevelPay reports whether the authenticated account uses level-pay billing. The value is set during Client.Login or Client.LoginFull and reset by Client.Logout. Returns false if the client is not authenticated.
func (*Client) Login ¶
Login authenticates the client with the given credentials. The password is SHA-1 hashed internally before transmission.
On success the auth token is stored and attached to all subsequent authenticated requests. Login is safe to call concurrently but a subsequent call replaces the stored token.
Use Client.LoginFull instead if you need access to the full response (user profile, house info, credit cards, meter flags, etc.).
func (*Client) LoginFull ¶ added in v1.2.0
LoginFull authenticates the client and returns the full LoginResponse including the user profile, house info, saved credit cards, and meter type flags. Like Client.Login, the auth token is stored internally.
func (*Client) Logout ¶
func (c *Client) Logout()
Logout clears the stored auth token. Subsequent calls to authenticated endpoints will return ErrAuthRequired.
func (*Client) TopUp ¶ added in v1.3.0
TopUp initiates an instant top-up using a saved payment card. The ccToken is obtained from CreditCard.Token in the LoginResponse. On success the balance and active top-ups caches are invalidated.
func (*Client) UpdateDeviceToken ¶
func (c *Client) UpdateDeviceToken(ctx context.Context, deviceToken, deviceType, osVersion string) error
UpdateDeviceToken registers or updates the Firebase Cloud Messaging (FCM) token used for push notifications. For headless or server-side clients, pass an empty string for deviceToken.
deviceType should be "android" or "ios". osVersion is a free-form string, e.g. "Android SDK: 33 (13)".
func (*Client) UpdateNotificationPreferences ¶ added in v1.3.0
func (c *Client) UpdateNotificationPreferences(ctx context.Context, sms, email, phone bool) (*NotificationResponse, error)
UpdateNotificationPreferences updates the account's notification channel preferences and returns the resulting state. The notification cache is invalidated after a successful update.
type CompareMetric ¶
type CompareMetric struct {
UsersHome float64 `json:"users_home"`
AverageHome float64 `json:"average_home"`
}
CompareMetric holds the user's and the average home's value for one metric.
type ComparePeriod ¶
type ComparePeriod struct {
Available bool `json:"available"`
Euro CompareMetric `json:"euro"`
KWh CompareMetric `json:"kwh"`
CO2 CompareMetric `json:"co2"`
}
ComparePeriod holds comparison data for one time period.
type CompareResponse ¶
type CompareResponse struct {
Success bool `json:"success"`
Day ComparePeriod `json:"day"`
Week ComparePeriod `json:"week"`
Month ComparePeriod `json:"month"`
}
CompareResponse is the response from GET /api/compare/.
type ConfigInfoResponse ¶
type ConfigInfoResponse struct {
Success bool `json:"success"`
Thresholds []float64 `json:"thresholds"`
TopUpAmounts []float64 `json:"top_up_amounts"`
AutoUpAmounts []float64 `json:"auto_up_amounts"`
ScheduledTopUpAmounts []float64 `json:"scheduled_top_up_amounts"`
}
ConfigInfoResponse is the response from GET /api/configinfo/.
type CreditCard ¶
type CreditCard struct {
Token string `json:"cc_token"`
Name string `json:"name"`
Last4 string `json:"last_4_digits"`
}
CreditCard is a saved payment method returned by Login.
type DefaultsInfoResponse ¶
type DefaultsInfoResponse struct {
Success bool `json:"success"`
HouseTypes []NamedItem `json:"house_types"`
HeatingTypes []NamedItem `json:"heating_types"`
MaxBedrooms int `json:"max_bedrooms"`
DefaultBedrooms int `json:"default_bedrooms"`
MaxAdults int `json:"max_adults"`
DefaultAdults int `json:"default_adults"`
MaxChildren int `json:"max_children"`
DefaultChildren int `json:"default_children"`
}
DefaultsInfoResponse is the response from GET /api/defaultsinfo/.
type ErrorCode ¶
type ErrorCode int
ErrorCode identifies the category of a Pinergy API error.
const ( // ErrCodeUnknown is returned for unclassified errors. ErrCodeUnknown ErrorCode = iota ErrCodeUnauthorized // ErrCodeForbidden is returned for HTTP 403 responses. ErrCodeForbidden // ErrCodeNotFound is returned for HTTP 404 responses. ErrCodeNotFound // ErrCodeRateLimited is returned for HTTP 429 responses. ErrCodeRateLimited // ErrCodeServerError is returned for HTTP 5xx responses. ErrCodeServerError // ErrCodeInvalidResponse is returned when the response body cannot be decoded. ErrCodeInvalidResponse // ErrCodeContextCanceled is returned when the caller's context is canceled. ErrCodeContextCanceled // ErrCodeContextDeadline is returned when the caller's context deadline is exceeded. ErrCodeContextDeadline // ErrCodeNetworkError is returned for transient network-level errors. ErrCodeNetworkError // ErrCodeEmailNotFound is returned when CheckEmail finds the address is not registered. ErrCodeEmailNotFound // ErrCodeAuthRequired is returned when an authenticated endpoint is called before Login. ErrCodeAuthRequired )
type House ¶
type House struct {
Type int `json:"type"`
HeatingType int `json:"heating_type"`
BedroomCount int `json:"bedroom_count"`
AdultCount int `json:"adult_count"`
ChildrenCount int `json:"children_count"`
}
House contains the property profile returned by Login.
type LevelPayDaily ¶
type LevelPayDaily struct {
Labels []string `json:"labels"`
Flags []string `json:"flags"`
Values []LevelPayDailyValue `json:"values"`
}
LevelPayDaily holds the half-hourly time-of-use data structure.
type LevelPayDailyValue ¶
type LevelPayDailyValue struct {
Label string `json:"label"`
DayKWh map[string]float64 `json:"daykWh"`
}
LevelPayDailyValue holds kWh per tariff band for a single interval.
type LevelPayUsageData ¶
type LevelPayUsageData struct {
Daily LevelPayDaily `json:"daily"`
}
LevelPayUsageData wraps the daily interval data.
type LevelPayUsageResponse ¶
type LevelPayUsageResponse struct {
UsageData LevelPayUsageData `json:"usageData"`
}
LevelPayUsageResponse is the response from GET /api/levelpayusage/.
type LoginRequest ¶
type LoginRequest struct {
Email string `json:"email"`
Password string `json:"password"` // SHA-1 hex of plaintext password
DeviceToken string `json:"device_token"` // FCM token; empty string for headless use
}
LoginRequest is sent to POST /api/login/.
type LoginResponse ¶
type LoginResponse struct {
Success bool `json:"success"`
ErrorCode int `json:"error_code"`
Message *string `json:"message"`
AuthToken string `json:"auth_token"`
IsLegacyMeter bool `json:"is_legacy_meter"`
IsNoWANMeter bool `json:"is_no_wan_meter"`
IsLevelPay bool `json:"is_level_pay"`
IsChild bool `json:"is_child"`
IsBusinessConn bool `json:"is_business_connect"`
PremisesNumber string `json:"premises_number"`
AccountType string `json:"account_type"`
User User `json:"user"`
House House `json:"house"`
CreditCards []CreditCard `json:"credit_cards"`
}
LoginResponse is the response from POST /api/login/.
type NotificationResponse ¶
type NotificationResponse struct {
Success bool `json:"success"`
SMS bool `json:"sms"`
Email bool `json:"email"`
Phone bool `json:"phone"`
ShouldShow int `json:"should_show"`
ShouldShowMessage string `json:"should_show_message"`
}
NotificationResponse is the response from GET /api/getnotif/.
type Option ¶
type Option func(*Client)
Option configures a Client. Options are applied in order by NewClient.
func WithBaseURL ¶
WithBaseURL overrides the API base URL. Useful for testing or staging environments.
By default only HTTPS URLs are accepted. Use WithInsecureHTTP to allow plaintext HTTP (e.g. for local test servers).
func WithCacheDisabled ¶
func WithCacheDisabled() Option
WithCacheDisabled disables the in-memory response cache entirely. Every call will hit the upstream API.
func WithCacheTTL ¶
WithCacheTTL overrides the cache TTL for a specific endpoint path (e.g. "/api/balance/"). A TTL of 0 disables caching for that endpoint.
func WithHTTPClient ¶
WithHTTPClient replaces the underlying http.Client. The provided client's timeout takes precedence over WithTimeout.
func WithInsecureHTTP ¶ added in v1.2.0
func WithInsecureHTTP() Option
WithInsecureHTTP allows the client to connect over plaintext HTTP. This is intended only for local development and testing. Production callers should never enable this.
func WithMaxResponseBytes ¶ added in v1.2.0
WithMaxResponseBytes sets the maximum number of bytes read from a single HTTP response body. The default is DefaultMaxResponseBytes (2 MB).
func WithMaxRetries ¶
WithMaxRetries sets the maximum number of attempts for retryable requests. A value of 1 means no retries (only the initial attempt).
func WithRateLimit ¶
WithRateLimit configures the token-bucket rate limiter. r is the sustained rate in requests per second; burst is the maximum number of requests allowed to proceed without waiting.
func WithRetryDelays ¶
WithRetryDelays sets the base and maximum delay for exponential back-off.
func WithTimeout ¶
WithTimeout sets the HTTP request timeout.
type ScheduledTopUp ¶
type ScheduledTopUp struct {
CurrentUser bool `json:"current_user"`
TopUpAmount float64 `json:"top_up_amount"`
TopUpDay int `json:"top_up_day"`
Customer string `json:"customer"`
}
ScheduledTopUp is a top-up configured to run on a fixed day of the month.
type TopUpRequest ¶ added in v1.3.0
TopUpRequest is sent to POST /api/topup/.
type TopUpResponse ¶ added in v1.3.0
type TopUpResponse struct {
Success bool `json:"success"`
NewBalance float64 `json:"new_balance"`
Amount int `json:"amount"`
TransactionID string `json:"transaction_id"`
}
TopUpResponse is the response from POST /api/topup/.
type UnixTime ¶
UnixTime is a time.Time that unmarshals from a JSON string containing a Unix timestamp (e.g. "1773446400"). The Pinergy API returns all timestamps in this format rather than RFC 3339.
func (UnixTime) MarshalJSON ¶
MarshalJSON implements json.Marshaler.
func (*UnixTime) UnmarshalJSON ¶
UnmarshalJSON implements json.Unmarshaler.
type UpdateDeviceTokenRequest ¶
type UpdateDeviceTokenRequest struct {
DeviceToken string `json:"device_token"`
DeviceType string `json:"device_type"`
OSVersion string `json:"os_version"`
}
UpdateDeviceTokenRequest is the body sent to POST /api/updatedevicetoken/.
type UpdateNotificationPreferencesRequest ¶ added in v1.3.0
type UpdateNotificationPreferencesRequest struct {
SMS bool `json:"sms"`
Email bool `json:"email"`
Phone bool `json:"phone"`
}
UpdateNotificationPreferencesRequest is sent to POST /api/updatenotif/.
type UsageEntry ¶
type UsageEntry struct {
Available bool `json:"available"`
Amount float64 `json:"amount"` // cost in EUR
KWh float64 `json:"kwh"`
CO2 float64 `json:"co2"`
Date UnixTime `json:"date"`
}
UsageEntry is one data point in a usage period (day, week, or month).
type UsageResponse ¶
type UsageResponse struct {
Success bool `json:"success"`
Day []UsageEntry `json:"day"`
Week []UsageEntry `json:"week"`
Month []UsageEntry `json:"month"`
}
UsageResponse is the response from GET /api/usage/.
type User ¶
type User struct {
Title string `json:"title"`
Name string `json:"name"`
PineryID string `json:"pinergy_id"`
MobileNumber string `json:"mobile_number"`
SMSNotifications bool `json:"sms_notifications"`
EmailNotifications bool `json:"email_notifications"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
}
User contains the authenticated user's profile returned by Login.
type VersionResponse ¶
type VersionResponse struct {
MinVersion string `json:"min_version"`
CurrentVersion string `json:"current_version"`
ForceUpdate bool `json:"force_update"`
}
VersionResponse is the response from GET /version.json. The exact schema is not fully documented; fields are best-effort.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
basic
command
Command basic demonstrates how to log in and retrieve the current balance.
|
Command basic demonstrates how to log in and retrieve the current balance. |
|
monitor
command
Command monitor polls the Pinergy balance every 5 minutes and prints an alert if the credit is low or the meter is on emergency credit.
|
Command monitor polls the Pinergy balance every 5 minutes and prints an alert if the credit is low or the meter is on emergency credit. |