Guide to the Octopus API

One of the impressive features of Octopus Energy is its REST API (Representational State Transfer Application Programming Interface), by which smart meter customers and developers can reliably access data to populate web and mobile apps. While Octopus do have their own guide to the API it isn't as helpful as I would like it to be. As a result, I've written this documentation in the hope that it will help new users getting started.

Some of what I write might be somewhat critical of the API as it currently stands. It should be remembered that even the most unintuitive or difficult to use API is a hundred times better than not having an API. I hope that by making clear the points that I find less helpful, it will help others getting started, and ultimately will feed into improvements that I know are in the pipeline. Also, if there is anything you find unclear in what I write, please ask on the Octopus forum and I or someone else will try and get it clarified.

For more general information on Octopus and its products, I have an Unofficial Guide that you may find useful.

Contents

Introduction to the APIs

The API offers a standardised way to request information from Octopus's system.

A user makes an http request. This request is essentially a URL, made up of three parts: a base url, the end-point, and the parameters. For example, if we request https://api.octopus.energy/v1/products/?brand=OCTOPUS_ENERGY&is_green=true, then https://api.octopus.energy/ is the base url, v1/products/ is the end-point, and ?brand=OCTOPUS_ENERGY&is_green=true contains the parameters. This request is for a list of all products that are green and for brand OCTOPUS_ENERGY. The first parameter is always preceded by a question mark, while subsequent parameters are preceded by ampersands, as in the example above.

The response comes back as json, which is a flexible format that can be directly read, or easily unpacked by a downstream application. For example, here is the response from https://api.octopus.energy/v1/products/ (formatted to look pretty - some applications will do this automatically):


{
    "count": 96,
    "next": null,
    "previous": null,
    "results": [
        {
            "code": "1201",
            "direction": "IMPORT",
            "full_name": "Affect Standard Tariff",
            "display_name": "Affect Standard Tariff",
            "description": "Affect Standard Tariff",
            "is_variable": true,
            "is_green": false,
            "is_tracker": false,
            "is_prepay": false,
            "is_business": false,
            "is_restricted": false,
            "term": null,
            "available_from": "2016-01-01T00:00:00Z",
            "available_to": null,
            "links": [
                {
                    "href": "https://api.octopus.energy/v1/products/1201/",
                    "method": "GET",
                    "rel": "self"
                }
            ],
            "brand": "AFFECT_ENERGY"
        },
        {
            "code": "AFFECT-FIX-12M-20-02-12",
            "direction": "IMPORT",

At the top of the response it will tell you the number of records returned in the response (in this case 103). If the number of records exceeds the page_size (usually 100), you will have to explicitly ask for the next page - if so this will be given in the "next" field of the response.

In many cases like this one, the data being requested won't be private, so it won't need any authentication. In other cases, you'll be requesting private data (like your consumption data), and your request will require authentication. The form of authentication the Octopus API uses is called "basic access", with a security key (but with the password left blank). You can find your security key from the Octopus website (you will need to log in). You shouldn't share your security key with others, and if you do suspect someone else knows it, you can generate a new key from that page.

You can make the request in a range of ways, a number of which are documented in the sections below. However, if you're just getting started I'd recommend trying in this Generic API tool. It lets you enter a url, your security key (if needed) and a choice of how you want the output formatted. This file just runs in your browser, but if you feel safer you can save down generic.html and just run it on your own machine.

If that doesn't work, you can just put the API endpoint directly in your web browser. If it is an end-point that requires authentication, your browser should prompt you for your username and password, in which case just enter your security key in the username field and leave the password blank.

I have two final general points on the API. First, each request you make of the API has a performance impact on Octopus's servers. If too many requests are made, the service won't be sustainable. As a result, when designing any applications that make requests, try to not to overwhelm the API (for example, don't create something that sends a request to the API every second). Second, try to make any applications that process API responses as robust as possible. For example, if you use a few elements from the json response, try to code things so that it won't break if the json contains extra elements. On the other hand, if they are removing data from the response, you can usually expect that they'll notify you before they do it.

The basics of mpans/meters/tariffs/products/timezones/units

Before I describe the various API end-points, I think it is helpful to distinguish a few terms. Each customer has an account number, which will be of the form A-AAAA1111. If you login to your account dashboard you will see the account number in the URL. Next, each each account will have one or more meter points, each with an mpan (meter point administration number). If you are paid for the electricity you export (as opposed to being on a Feed-in Tariff), you will have a second mpan for your export.

Each mpan will generally be populated a meter, and each meter will have a meter serial number. There may be multiple meters for a single mpan, and the same meter may populate multiple The same meter can apply to multiple mpans. There is more information about mpans on wikipedia.

For gas, it works similarly, but instead of mpans there are mprns (meter point reference numbers) and you can't export.

Each mpan is in a region, and has a region code, which is a letter from A to P. You can lookup the region code from the first two digits of the mpan in this table.

Each mpan/mprn will be be subject to a single tariff code at a time (though you can change tariff codes over time). Each tariff will have defined standing charges and usage charges, though these can change over time.

Each tariff belongs to a product. There are multiple tariffs for each product, mostly distinguished by the region, whether it is a single or dual register (economy 7 is an example of dual register) and whether it electricity or gas. To identify the product code for a particular tariff, you can usually take off the first few letters of the tariff (E-1R-, E-2R- or G-1R) which indicate if it is electricity single register, electricity dual register (eg economy7) or gas single register, and the letter at the end (eg -A) which indicates the region code. So, for example, E-1R-VAR-19-04-12-N is one of the tariffs for product VAR-19-04-12.

When dealing with the API, you're going to need to get used to working in two different time formats. The first is known as UTC or GMT or Zulu. In this format, you can enter a datetime with a Z on the end, like 2018-11-10T00:00:00Z. The second format is UK summer time, which looks like 2019-04-12T13:40:00+01:00 (to indicate that it is one hour ahead of UTC. In requests, you should always put any datetime parameters in UTC format, with a Z at the end, otherwise they may behave inconsistently. With results, all end-points return dates in UTC format in winter, while in summer some end-points return dates in UTC format while others return them in local format. Local time jumps from 1am to 2am on the last Sunday of March, and from 2am back to 1am on the last Sunday of October. There is talk about ending the clock change in the UK, which would make dealing with APIs so much easier!

Electricity is typically measured in kwh (kilowatt hour), which is the amount of electricity you get if you use 1 kilowatt for an hour. It is a bit of a crazy unit - but if it helps, 1kwh is equal to 3600 kilojoules. We typically quote the price of electricity in pence/kwh. Wholesale electricity is typcially measured in mwh (megawatt hour), and priced in £/mwh. £10/mwh is equivalent to 1p/kwh (ie you divide by 1000 and multiply by 10).

Gas is more complicated and depends on the country. In the UK, retail gas is priced in pence/kwh, but is metered in cubic metres. As a result, you need to use a calorific value to convert between cubic metres to kwh - it is roughly 10kwh per cubic metre. Wholesale gas is priced in pence per therm. There are 29.3071 kwh per therm.

API end-points

There are a lot of end-points available via the Octopus API - here I will run through the main ones that are likely to be useful to Octopus customers.

A very useful end-point is https://api.octopus.energy/v1/accounts/< ACCOUNT >/ - this provides you with mpan/mprn and serial numbers for each of your meters, as well as what tariffs you are currently on (and those that you were previously on). You will need to replace with your actual account, which should be something like A-AAAA1111, and you will need to authenticate using your security key. The response will look something like:


{
	"number":"A-AAAA1111",
	"properties":[
		{
			"id":123455,
			"moved_in_at":"2018-10-19T00:00:00+01:00",
			"moved_out_at":null,
			"address_line_1":"1 SMITH STREET",
			"address_line_2":"",
			"address_line_3":"",
			"town":"LONDON",
			"county":"",
			"postcode":"W1 1AA",
			"electricity_meter_points":[
				{
					"mpan":"1200000000000",
					"profile_class":0,
					"consumption_standard":1428,
					"meters":[
						{
							"serial_number":"1111111111",
							"registers":[
								{
									"identifier":"01",
									"rate":"STANDARD",
									"is_settlement_register":true
								}
								]
						}
						],
					"agreements":[
						{
							"tariff_code":"E-1R-VAR-18-10-05-C",
							"valid_from":"2018-11-10T00:00:00Z",
							"valid_to":"2018-11-27T00:00:00Z"
						},
						{
							"tariff_code":"E-1R-AGILE-18-02-21-C",
							"valid_from":"2018-11-27T00:00:00Z",
							"valid_to":"2019-11-27T00:00:00Z"
						},
						{
							"tariff_code":"E-1R-AGILE-18-02-21-C",
							"valid_from":"2019-11-27T00:00:00Z",
							"valid_to":"2020-11-27T00:00:00Z"
						}
						]
				}
				],
			"gas_meter_points":[
				]
		}
		]
}

One thing to be aware of with this response is that if you have mutliple mpans, it may not be completely obvious which is which. You may be able to work it out by looking at the tariff codes for each mpan. Another thing to be aware of is that variable tariffs will auto-extend when they reach the end, while I expect fixed tariffs switch to the variable tariff when they reach the end of the term.

One of the most useful end-points is the one to get consumption data for a particular mpan and meter: https://api.octopus.energy/v1/electricity-meter-points/< mpan >/meters/< meter serial number >/consumption/. This is discussed in much more detail below.

To get the region code, I'd suggest looking up the first two digits of the mpan in this table. However, there are also two API end-points for finding out the region code. The first is useful if you know the postcode but not the mpan: https://api.octopus.energy/v1/industry/grid-supply-points/?postcode=W1A1AA (replace with the postcode you want it for). The second can work if you have the mpan: https://api.octopus.energy/v1/electricity-meter-points/1200000000000/ (replace the code at the end with your mpan). This second end-point isn't always complete, so occasionally this doesn't return a result. (If this is causing a problem for you, contact Octopus and they can add it manually.) Neither of these end-points require authentication.

To get a list of all currently active products, use end-point https://api.octopus.energy/v1/products/. This endpoint doesn't require authentication. For each record it will give you, among other things, the product code, display name, full name, and a url to get all the tariffs for that product. Don't forget that if it returns more than 100 records, you will have to look at page=2 for the subsequent entries. There are a few parameters that may be useful for this end-point:

A sample response from this is:

{
	"count":3,
	"next":null,
	"previous":null,
	"results":[
		{
			"code":"AGILE-18-02-21",
			"direction":"IMPORT",
			"full_name":"Agile Octopus February 2018",
			"display_name":"Agile Octopus",
			"description":"",
			"is_variable":true,
			"is_green":true,
			"is_tracker":false,
			"is_prepay":false,
			"is_business":false,
			"is_restricted":false,
			"term":12,
			"available_from":"2017-01-01T00:00:00Z",
			"available_to":null,
			"links":[{"href":"https://api.octopus.energy/v1/products/AGILE-18-02-21/","method":"GET","rel":"self"}],
			"brand":"OCTOPUS_ENERGY"
		},
		{
			"code":"GO-18-06-12",
			"direction":"IMPORT",
			"full_name":"Octopus Go June 2018",
			"display_name":"Octopus Go",
			"description":"",
			"is_variable":true,
			"is_green":true,
			"is_tracker":false,
			"is_prepay":false,
			"is_business":false,
			"is_restricted":false,
			"term":12,
			"available_from":"2018-06-13T00:00:00+01:00",
			"available_to":null,
			"links":[{"href":"https://api.octopus.energy/v1/products/GO-18-06-12/","method":"GET","rel":"self"}],
			"brand":"OCTOPUS_ENERGY"
		},
		{
			"code":"VAR-19-04-12",
			"direction":"IMPORT",
			"full_name":"Flexible Octopus April 2019 v1",
			"display_name":"Flexible Octopus",
			"description":"Flexible Octopus offers great value and 100% renewable electricity. As a variable tariff, your prices can rise and fall with wholesale prices - but we'll always give you at least 30 days' notice of a change, and you can switch to a fixed tariff at any time.",
			"is_variable":true,
			"is_green":false,
			"is_tracker":false,
			"is_prepay":false,
			"is_business":false,
			"is_restricted":false,
			"term":null,
			"available_from":"2019-04-12T13:40:00+01:00",
			"available_to":null,
			"links":[{"href":"https://api.octopus.energy/v1/products/VAR-10-04-12/","method":"GET","rel":"self"}],
			"brand":"OCTOPUS_ENERGY"
		}
		]
}

If you know the product name, you can get a list of all the tariffs available - mostly split by region, and whether single register electricity, dual register electricity or gas. The end-point for this is https://api.octopus.energy/v1/products/AGILE-18-02-21/ (or replace with a different product name). Again, this end-point doesn't require authentication. In all cases these results show the current standing charges, and in some cases it also shows the current unit rates (though you can include the parameter tariffs_active_at=2019-01-01T00:00Z to see it as of that historic date). However, it also shows the urls to get the history of standing charges and unit rates for each tariff, which is especially useful for tariffs that change price frequently like AGILE or GO. A sample response from this is:

{
	"code":"AGILE-18-02-21",
	"full_name":"Agile Octopus February 2018",
	"display_name":"Agile Octopus",
	"description":"",
	"is_variable":true,
	"is_green":true,
	"is_tracker":false,
	"is_prepay":false,
	"is_business":false,
	"is_restricted":false,
	"term":12,
	"available_from":"2017-01-01T00:00:00Z",
	"available_to":null,
	"tariffs_active_at":"2020-06-03T03:38:24.818834Z",
	"single_register_electricity_tariffs":{
			"_A":{
					"direct_debit_monthly":{
							"code":"E-1R-AGILE-18-02-21-A",
							"standing_charge_exc_vat":20.0,
							"standing_charge_inc_vat":21.0,
							"online_discount_exc_vat":0,
							"online_discount_inc_vat":0,
							"dual_fuel_discount_exc_vat":0,
							"dual_fuel_discount_inc_vat":0,
							"exit_fees_exc_vat":0,
							"exit_fees_inc_vat":0,
							"links":[
								{
									"href":"https://api.octopus.energy/v1/products/AGILE-18-02-21/electricity-tariffs/E-1R-AGILE-18-02-21-A/standing-charges/",
									"method":"GET",
									"rel":"standing_charges"
								},
								{
									"href":"https://api.octopus.energy/v1/products/AGILE-18-02-21/electricity-tariffs/E-1R-AGILE-18-02-21-A/standard-unit-rates/",
									"method":"GET",
									"rel":"standard_unit_rates"
								}
								],
							"standard_unit_rate_exc_vat":3.36,
							"standard_unit_rate_inc_vat":3.528
						}
				},
                        ...
			},

	"brand":"OCTOPUS_ENERGY"
}

The final end-point I mention are those for price history for each tariff. You can get them from the links within the product response (as shown above). These take one of the following forms:

None of these require authentication, and they will be discussed in more detail below.

The Consumption end-point

The most useful API end-point is the consumption API. At its simplest, this provides half-hourly consumption data for any electricity mpan/meter or gas mprn/meter. As an example, you could request https://api.octopus.energy/v1/electricity-meter-points/< MPAN >/meters/< meter serial number >/consumption/?page_size=100&period_from=2020-03-29T00:00Z&period_to=2020-03-29T01:29Z&order_by=period, with authentication. A few comments on these parameter options:

The example above was intentionally chosen to show the clock's jumping forward in March. I asked for the periods from the half hour starting 00:00 UTC to the half hour starting before 01:29 UTC - this returns 3 results, but you can see the output format shifting from UTC format to summertime format in the following response. It would probably be better practice for the API to return all times in UTC and let end users convert to local time if need be, which is what the price end-point does.

{
	"count":3,
	"next":null,
	"previous":null,
	"results":[
		{
			"consumption":0.016,
			"interval_start":"2020-03-29T00:00:00Z",
			"interval_end":"2020-03-29T00:30:00Z"
		},
		{
			"consumption":0.028,
			"interval_start":"2020-03-29T00:30:00Z",
			"interval_end":"2020-03-29T02:00:00+01:00"
		},
		{
			"consumption":1.547,
			"interval_start":"2020-03-29T02:00:00+01:00",
			"interval_end":"2020-03-29T02:30:00+01:00"
		}
		]
}

If you don't want to get back your data at half-hourly granularity, you can include a parameter group_by=day, or week or month or quarter. This aggregates half hours into days based on the local time, not the UTC time, so there will be one fewer hour included on 29 March 2020. In practice I don't think many people use the group_by option, since anyone on a time-of-use tariff won't care about their daily consumption, but instead when in the day it occurs.

This same approach works for an export mpan - it still reports it as "consumption", but it will actually be the amount exported.

For gas, you can use an equivalent request: https://api.octopus.energy/v1/gas-meter-points/< MPRN >/meters/< meter serial number >/consumption/?page_size=100&period_from=2020-03-29T00:00:00Z&period_to=2020-03-29T01:00:00Z&order_by=period. For this there is probably a bit more benefit aggregating by day, as customers are charged the same amount all day (or even all month if they're not on a tracker). One further complication with gas is that customers on SMETS1 meters get their consumption data pre-converted to kwh, while customers on SMETS2 meters get their consumption data in cubic meters and have to convert.

Electricity consumption data is returned to the nearest 0.001kwh. However, when they do billing, they round to the nearest 0.01kwh before multiplying by the price. The way Octopus round is known as unbiased rounding, where numbers ending in 5 are rounded up or down, to whichever is even. As a result, 0.015 would be rounded up to 0.02, while 0.025 is rounded down to 0.02.

One of the biggest issues that crops up with consumption data is when it is missing. Octopus collect the half hourly data from our meters through an extremely messy process, which differs depending on whether you are SMETS1 or SMETS2. For SMETS1, usually in the early hours of the morning they will collect all the half-hourly consumption data up until midnight UTC (1am local time if it is summer). However, there are often delays in this process, I'd say 50% of the time I have that data available in the API by 9am, 30% of the time I have it 6pm, 15% of the time I have it the next day, and 5% it takes longer, or I have to chase it up. For SMETS2 it seems to be even worse, for example almost never available in the morning, though I know Octopus is working hard on improving the process. My main point is that you shouldn't be surprised if there are gaps in your half-hourly data where you are missing certain periods.

The Price end-point

One of the complications of the price end-points is that they vary a bit between tariffs. I will first describe the Agile tariff, and then move to other tariffs in turn. I note that none of price end-points require authentication.

Agile prices

The Agile tariff allows users to get all the half hourly prices between two times by making a request of form https://api.octopus.energy/v1/products/AGILE-18-02-21/electricity-tariffs/E-1R-AGILE-18-02-21-C/standard-unit-rates/?period_from=2020-03-29T00:00Z&period_to=2020-03-29T01:29Z. A few comments on these parameter options:

This example above was intentionally chosen to show the clock's jumping forward in March. I asked for the periods from the half hour starting 00:00 UTC to the half hour starting before 01:29 UTC - this returns 3 results despite the clock change. You can see the output format stays in UTC format throughout (unlike the consumption end-point).

{
	"count":3,
	"next":null,
	"previous":null,
	"results":[
		{
			"value_exc_vat":0.6,
			"value_inc_vat":0.63,
			"valid_from":"2020-03-29T01:00:00Z",
			"valid_to":"2020-03-29T01:30:00Z"
		},
		{
			"value_exc_vat":3.6,
			"value_inc_vat":3.78,
			"valid_from":"2020-03-29T00:30:00Z",
			"valid_to":"2020-03-29T01:00:00Z"
		},
		{
			"value_exc_vat":1.5,
			"value_inc_vat":1.575,
			"valid_from":"2020-03-29T00:00:00Z",
			"valid_to":"2020-03-29T00:30:00Z"
		}
		]
}

The results include a value excluding VAT, and one including 5% VAT. I would recommend using the VAT exclusive prices, and multiply the final cost by 1.05, as this will ensure your rounding matches that on the Octopus bill.

Every day at some point between 4pm and 8pm local time (usually much closer to 4pm), Octopus will receive the latest half-hourly day ahead wholesale auction prices from EPEXSPOT, and will calculate the retail prices. These will cover from 11pm local time that night, until 11pm local time the following night. The reason it runs to 11pm rather than midnight is to tie in with European wholesale markets.

If you ever hae the wholesale prices but not the retail prices, you can calculate the VAT exclusive prices by dividing the wholesale prices by 10 (to convert from $/MWh to p/kwh), and then multiplying by the multiplier in the following table. If it is for a time between 4 and 7pm, add the peak adder. Finally, the price excluding VAT is capped at 33.33.

RegionMultiplierPeak Adder
A2.113
B2.014
C2.012
D2.213
E2.112
F2.112
G2.112
H2.112
J2.212
K2.212
L2.311
M2.213
N2.113
P2.412

You can also always convert from region C prices to other regions by subtracting 12 (if during peak), dividing by 2, multiplying by the new region's multiplier, adding the new region's peak adder (if during peak), and if need be capping at 33.33p/kwh.

Go prices

The original GO tariff charges a price of 5p (including VAT) for 4 hours (from 00:30-4:30 local time), and a slightly higher than normal rate the rest of the time. There have subsequently been a range of different GO tariffs that have 3, 4 or 5 hours of offpeak pricing, and start at different times.

You can request the prices similarly to how you would do it with Agile, eg https://api.octopus.energy/v1/products/GO-4H-0030/electricity-tariffs/E-1R-GO-4H-0030-A/standard-unit-rates/?period_from=2020-03-29T00:00Z&period_to=2020-03-29T01:29Z. Unlike Agile, there isn't a record for every half hour, but the response will still give you all the prices you need. In this example, since we have requested prices covering 00:00 until 1:29, it tells us the higher price from the previous morning until 00:30, and then the low price from 00:30 UTC until 3:30 UTC (that is, 4:30 local time).

{
	"count":2,
	"next":null,
	"previous":null,
	"results":[
		{
			"value_exc_vat":4.76,
			"value_inc_vat":4.998,
			"valid_from":"2020-03-29T00:30:00Z",
			"valid_to":"2020-03-29T03:30:00Z"
		},
		{
			"value_exc_vat":13.45,
			"value_inc_vat":14.1225,
			"valid_from":"2020-03-28T04:30:00Z",
			"valid_to":"2020-03-29T00:30:00Z"
		}
		]
}

If you are wanting to identify the half-hourly GO prices to match up with half-hourly consumption, you will have to expand these yourself.

Fixed price contracts / standard variable price contracts / standing charges

There are a number of fixed price tariffs or standard variable tariffs. For example:

If you request these without a period_start/period_to, the response will show how the priced price has changed. Alternative, you can request it for a particular date range and the format will be consistent with GO, for example https://api.octopus.energy/v1/products/VAR-19-04-12/electricity-tariffs/E-1R-VAR-19-04-12-A/standard-unit-rates/?period_from=2020-03-29T00:00Z&period_to=2020-03-29T01:29Z will return:

{
	"count":1,
	"next":null,
	"previous":null,
	"results":[
		{
			"value_exc_vat":14.78,
			"value_inc_vat":15.519,
			"valid_from":"2020-01-15T00:00:00Z",
			"valid_to":null
		}
		]
}

Note that the null value for valid_to indicates that that price is still the active price.

Unlike GO, which shows interchanging peak and offpeak prices, the economy7 tariffs (the ones starting with E-2R) have separate URLs for the day unit rates and the night unit rates.

Gas Tracker

The Gas tracker prices are not currently available from the main Octopus API. They are available from an alternative API, but I haven't had a chance to use these - if you want to understand this you are best to ask on the forum.

Accessing the API

The sections above go into detail about how each of the API end-points work. However, there are lots of different ways to request that data and process it. As mentioned above, the simplest way to access the data is in your web browser. If it is an end-point that requires authentication, your browser should prompt you for your username and password, in which case just enter your security key in the username field and leave the password blank.

However, having the json response in the browser isn't always the easiest to read or to do anything with (for example, to get into Excel). For this reason, once you start wanting to do something with the data, you will probably want to use some other method. The subsections below describe some methods for doing this.

Accessing the API via a REST Client

There is a free website called ExtendsClass that allows you to enter an API request, and get the response.

Make sure you have selected GET, then enter your API request (base url, end-point and parameters) in the URL field. If your request requires authentication, enter your security key in the username field, as shown in the screenshot below.

Then, you will get your response as per the screenshot below (if you click on Format the Response it will make it look more readable.

Accessing the API via cURL

cURL is a free command line tool that comes with a lot of systems, and allows you to make API requests and process responses.

For example, in my command line interface, I entered the following command and got back the json response:

curl "https://api.octopus.energy/v1/products/?is_prepay=true&brand=OCTOPUS_ENERGY"

If it is a request that requires authentication, you can do this replacing XXXXXXXX with your security key, and including your account number, in:

curl -u "XXXXXXXXXX:" "https://api.octopus.energy/v1/accounts/A-AAAA1111/"

cURL has a lot of other functionality, for example to parse the response and do calculations and save it into csv format.

Accessing the API via python

Python is a powerful programming language, which allows you to perform analysis and produce charts. It has a library called requests (you will probably find it is already installed) that lets you make requests to the Octopus API. This section contains some bits of code to get you started.

This first bit of code makes a request without authentication.

import requests
url = 'https://api.octopus.energy/v1/products'
r = requests.get(url)
output_dict = r.json()

This next bit of code makes a request with authentication.

import requests
APIKEY = 'asdfasdfasdf'
url = 'https://api.octopus.energy/v1/accounts/A-AAAA1111/'
r = requests.get(url, auth=(APIKEY,''))
output_dict = r.json()

This final bit of code makes a request without authentication, and then produces a Pandas series containing the prices for each period.

import requests 
import pandas as pd
url = ('https://api.octopus.energy/v1/products/AGILE-18-02-21/' + 
         'electricity-tariffs/E-1R-AGILE-18-02-21-C/standard-unit-rates/' + 
         '?period_from=2020-03-29T00:00Z&period_to=2020-03-29T02:29Z')
r = requests.get(url)
output_dict = r.json()
print('output_dict=')
print(output_dict)

valid_from = [x['valid_from'] for x in output_dict['results']]
value_exc_vat = [x['value_exc_vat'] for x in output_dict['results']]
prices = pd.Series(value_exc_vat, index=valid_from)
print('prices=')
print(prices)

which produces the output:

Accessing the API via javascript

While python is my programming language of choice, I have recently started developing tools using javascript. This allows people to run them locally or from my website, through their Chrome browser, without having to have other software installed on their computer.

The way this works is the javascript in the html file makes the request to the Octopus API. The following example shows how the request can be done where authentication isn't required:

   var xhttp = new XMLHttpRequest();
   var output = {status: 0, content: "empty"};
   xhttp.open("GET", url , false);
   xhttp.send(); 
   response = JSON.parse(xhttp.response);
The following example shows how the request can be done where authentication is required:
   var xhttp = new XMLHttpRequest();
   var output = {status: 0, content: "empty"};
   xhttp.open("GET", url , false);
   xhttp.setRequestHeader("Authorization", "Basic " + btoa(urlParams['key'] ) + ":");
   xhttp.send();	
   response = JSON.parse(xhttp.response);

Note that this way of requesting code uses a synchronoous connection, which can make the user experience a bit worse, but it is good enough for me and makes the code easier to follow.

If you look at the source code for the Generic API tool you will see both of these being done. Other examples of websites that I have built that use javascript to access the Octopus API include prices.html and consumption.html(you will need to add your security key, mpan and meter number for it to load your consumption data).

Accessing the API via Google Sheets

It is possible to access the Octopus API via a Google Sheet.

To do this, I have saved a google sheet. This version is read only, but you can create your own copy of it (File, Make a Copy) and insert your security key and account details on the Settings tab. This works for the endpoints that produce a table of data (eg consumption and price data). I based this on a google sheet I found here.

This spreadsheet won’t work in Excel (as it has google sheets code in the background to get the data from the API). I believe it is also possible to access the API in the Windows version of Excel using a web query.

Notes on reconciling to Octopus bills

In case anyone is trying to use Octopus API data to reconcile their bill, I have built a javascript website that reconciles their Agile bill between two dates (you will need to include your security key, mpan and meter serial number for this to load your data). This website always seems to get the right bill calculation within a penny.

A few tips that I worked out while building this tool:

There is one other complexity on the bills that should be noted. Each half hour of the bill is displayed in the timezone of the start of the bill. This means that if you have a bill covering from 15th of March to the 15th of April, the whole bill will be in UTC, each day will have 48 half-hourly periods, with the exception of the very last day which will have 46 half-hourly periods. Similarly, if you have a bill covering 15 October to 15 November, the whole bill will be in summer time, each day will 48 half-hourly periods, with the exception of an extra 'day' at the end with just 2 half-hourly periods. It is a confusing way to display it, but it doesn't change the overall amount being charged.