octopus_energy_api_client 1.0.0
octopus_energy_api_client: ^1.0.0 copied to clipboard
A client for accessing the Octopus Energy API. Please note that Client for Octopus Energy API is unofficial and not endorsed by Octopus Energy.
Client for Octopus Energy API #
A client for accessing the Octopus Energy API.
Please note that Client for Octopus Energy API is unofficial and not endorsed by Octopus Energy.
Installation #
Add this package to your application.
dart pub add octopus_energy_api_client
Getting Started #
Most applications target a single version of the Octopus Energy API. Import that
version's library (for example v1.dart) and you have everything you need — the
client, the services, the models, and the helpers — from one import.
import 'package:octopus_energy_api_client/v1.dart';
Future<void> main() async {
// Your Octopus Energy API key.
final apiKey = 'sk_live_...';
// Obtain an HTTP client that authenticates every request with your API key.
final client = clientViaApiKey(apiKey);
// Create the API client for the v1 API.
final api = OctopusEnergyApiClient(client: client);
// Call an endpoint.
final account = await api.accounts.getAccount('A-1234ABCD');
// Release the underlying HTTP resources when you are done.
client.close();
}
That is all you need for everyday use. The rest of this document explains how the package is organized and why — read on if you want to understand the imports or if you ever need to work with more than one API version at the same time.
Library Structure and Versioning #
The Octopus Energy API is versioned (/v1/…, and newer /v2/… endpoints are
beginning to appear). A new API version is free to change the shape of its
data: a v2 model called Order may have entirely different fields from a v1
Order, and a service that exists in both versions may behave differently. If the
two versions shared a single set of types, every such change would be a breaking,
tangled mess.
To keep the versions cleanly separated, this package exposes one importable
library per API version, plus a small common library for the pieces that never
change between versions. You choose which version(s) to import, and Dart's
import ... as prefixes keep them from colliding.
Import Entry Points #
| Import | What it contains |
|---|---|
package:octopus_energy_api_client/octopus_energy_api_client.dart |
Common infrastructure only. Version-independent plumbing: clientViaApiKey, the exception type, and the API host constant. It contains no models and no client — those belong to a version. |
package:octopus_energy_api_client/v1.dart |
The complete v1 SDK. The v1 OctopusEnergyApiClient, every v1 service, and every v1 model and enum — plus a re-export of the common infrastructure above, so a single import is enough. |
package:octopus_energy_api_client/v2.dart |
The complete v2 SDK (planned). The same shape as v1.dart, for the v2 API. |
Everything under lib/src/ is private implementation detail; only the libraries
above are part of the public API.
Using a Single Version #
Import the version's library directly and use everything unprefixed, exactly as in Getting Started:
import 'package:octopus_energy_api_client/v1.dart';
final api = OctopusEnergyApiClient(client: clientViaApiKey(apiKey));
final products = await api.products.listProducts();
final product = await api.products.retrieveProduct('VAR-22-11-01');
final meterPoint = await api.electricityMeterPoints.getElectricityMeterPoint('1234567890123');
Using More Than One Version #
When you need two API versions in the same file, import each version's library with a prefix and import the common infrastructure once, unprefixed:
import 'package:octopus_energy_api_client/octopus_energy_api_client.dart';
import 'package:octopus_energy_api_client/v1.dart' as v1;
import 'package:octopus_energy_api_client/v2.dart' as v2; // illustrative
Future<void> main() async {
// One authenticated HTTP client, shared by every version's API client.
final client = clientViaApiKey('sk_live_...');
final v1Api = v1.OctopusEnergyApiClient(client: client);
final v2Api = v2.OctopusEnergyApiClient(client: client); // illustrative
final account = await v1Api.accounts.getAccount('A-1234ABCD');
final order = await v2Api.orders.getOrder('...'); // illustrative
client.close();
}
The v1. / v2. prefix is the single mechanism that resolves any name clash
between versions — whether it is the client, a service, or a model. Because the
prefix already carries the version, the type names themselves are deliberately
not version-suffixed: it is v1.OctopusEnergyApiClient and
v2.OctopusEnergyApiClient, not OctopusEnergyApiV1Client. This mirrors the
approach used by Google's official googleapis
package (e.g. package:googleapis/calendar/v3.dart exposes a CalendarApi, with
the version in the import path rather than the class name).
Some consequences worth knowing:
- Each version has its own client. There is no single object that spans
versions; you create one
OctopusEnergyApiClientper version. Pass them the samehttp.Client(as above) so authentication and connection pooling are shared. - The common library carries no client. Importing
package:octopus_energy_api_client/octopus_energy_api_client.darton its own gives youclientViaApiKeyand the exception type, but not a client — that is intentional. Reach for a version library (v1.dart) to get a client. clientViaApiKeylives in the common library and is re-exported by every version library, soclientViaApiKey,v1.clientViaApiKey, andv2.clientViaApiKeyall refer to the same helper.
Authentication #
clientViaApiKey returns an http.Client that attaches your API key to every
request:
final client = clientViaApiKey('sk_live_...');
You can pass any http.Client to OctopusEnergyApiClient(client: ...), so you are
free to wrap or substitute it — for example, to add logging, retries, or a mock
client in tests. Remember to close() the HTTP client when you are finished.
Errors #
Unsuccessful responses throw an OctopusEnergyApiClientException, which is
available from both the common library and every version library:
try {
await api.accounts.getAccount('A-1234ABCD');
} on OctopusEnergyApiClientException catch (e) {
print('Request failed: $e');
}
Services #
The v1 OctopusEnergyApiClient exposes the following services. Each is created
lazily on first access and reuses the client's http.Client.
| Service | Accessor | Example methods |
|---|---|---|
| Accounts | api.accounts |
getAccount, createAccount, renewBusinessTariff |
| Electricity meter points | api.electricityMeterPoints |
getElectricityMeterPoint, listElectricityMeterConsumption |
| Gas meter points | api.gasMeterPoints |
listGasMeterConsumption |
| Industry | api.industry |
listIndustryGridSupplyPoints |
| IVR support | api.ivrSupport |
minimalTwilioEnqueue |
| Products | api.products |
listProducts, retrieveProduct, listElectricityTariffStandardUnitRates, listGasTariffStandardUnitRates |
| Quotes | api.quotes |
createQuote, shareQuoteViaEmail |
| Voice | api.voice |
twilioEnqueueAudio |
Models #
Model fields mirror what the API actually returns, which is not always what the published schema declares. Two consequences worth knowing as a consumer:
- Nullability. A single model can serve both a request body and a response
body, and responses routinely omit fields the request requires. Response fields
are therefore typed as nullable wherever the API may omit them — so treat a
nullable field as genuinely optional and null-check it, even if the official
schema lists it as
required. - Numeric types. Some numeric values the schema declares as strings are
returned as JSON numbers (for example
Consumption.consumption, and theInstallationcapacity/generation figures). TheirfromJsonaccepts either form, so you do not need to handle the wire-type difference yourself.