{"openapi":"3.1.0","info":{"title":"Axle API","description":"For full documentation please see our official docs at <a href='http://docs.axle.energy'>docs.axle.energy</a>","version":"1.4.6"},"servers":[{"url":"https://api.axle.energy"}],"paths":{"/entities/asset":{"get":{"tags":["4. Assets"],"summary":"Get Assets","description":"Get all assets with pagination.\n\nReturns a page of assets with the total count and the requested subset of asset records. Use the limit and offset parameters to navigate through pages of results.","operationId":"get_assets_entities_asset_get","parameters":[{"description":"Maximum number of assets to return (1-5000)","required":false,"schema":{"type":"integer","maximum":5000.0,"minimum":1.0,"title":"Limit","description":"Maximum number of assets to return (1-5000)","default":10},"name":"limit","in":"query"},{"description":"Number of assets to skip for pagination","required":false,"schema":{"type":"integer","minimum":0.0,"title":"Offset","description":"Number of assets to skip for pagination","default":0},"name":"offset","in":"query"}],"responses":{"200":{"description":"Page of assets with pagination info","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetResponsePage"}}}},"500":{"description":"Server error while retrieving assets"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"post":{"tags":["4. Assets"],"summary":"Create Asset","description":"Create a new asset.\n\nThe asset must be associated with an existing site. Returns the created asset details including the assigned UUID.","operationId":"create_asset_entities_asset_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetRequest"}}},"required":true},"responses":{"200":{"description":"Successfully created asset","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetResponse"}}}},"400":{"description":"Invalid request"},"404":{"description":"Referenced site not found"},"409":{"description":"Asset already exists"},"500":{"description":"Server error while creating asset"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/asset/{asset_id}":{"get":{"tags":["4. Assets"],"summary":"Get Asset","description":"Get a specific asset by its Axle UUID.\n\nReturns the asset details if it exists.","operationId":"get_asset_entities_asset__asset_id__get","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"},"name":"asset_id","in":"path"}],"responses":{"200":{"description":"Asset details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetResponse"}}}},"404":{"description":"Asset not found or not authorized to access"},"500":{"description":"Server error while retrieving asset"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"delete":{"tags":["4. Assets"],"summary":"Delete Asset","description":"Delete an asset by its Axle UUID.\n\nThe asset will be deleted if it exists. Returns a confirmation message upon successful deletion.","operationId":"delete_asset_entities_asset__asset_id__delete","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"},"name":"asset_id","in":"path"}],"responses":{"204":{"description":"Asset successfully deleted"},"404":{"description":"Asset not found or not authorized to access"},"500":{"description":"Server error while deleting asset"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"patch":{"tags":["4. Assets"],"summary":"Update Asset","description":"Update an existing asset's properties, asset model, and/or installation date.\n\nAll fields are optional. Returns the updated asset details.","operationId":"update_asset_entities_asset__asset_id__patch","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"},"name":"asset_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetUpdateRequest"}}},"required":true},"responses":{"200":{"description":"Successfully updated asset","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetResponse"}}}},"400":{"description":"Invalid request data"},"404":{"description":"Asset not found or not authorized to access"},"500":{"description":"Server error while updating asset"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/asset/external-id/{external_id}":{"get":{"tags":["4. Assets"],"summary":"Get Asset By External Id","description":"Get a specific asset by its external ID (vendor-specific identifier).\n\nReturns the asset details if it exists. This is useful for integrations where the external system ID is known but not the Axle UUID.","operationId":"get_asset_by_external_id_entities_asset_external_id__external_id__get","parameters":[{"required":true,"schema":{"type":"string","title":"External Id"},"name":"external_id","in":"path"}],"responses":{"200":{"description":"Asset details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetResponse"}}}},"404":{"description":"Asset not found or not authorized to access"},"500":{"description":"Server error while retrieving asset"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/asset/{asset_id}/callback/{event_id}":{"post":{"tags":["4. Assets"],"summary":"Event Handling Status Update","description":"Provide an update on the handling of a given event by a given asset.\n\nThis endpoint allows asset controllers to report back the status of event handling. The `asset_id` can be either the Axle UUID or an external ID if `asset_id_is_external` is true.\n\nNote: This will not work for non-UUID external asset IDs.","operationId":"event_handling_status_update_entities_asset__asset_id__callback__event_id__post","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"},"name":"asset_id","in":"path"},{"required":true,"schema":{"type":"string","title":"Event Id"},"name":"event_id","in":"path"},{"required":false,"schema":{"type":"boolean","title":"Asset Id Is External","default":false},"name":"asset_id_is_external","in":"query"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventResponse"}}},"required":true},"responses":{"200":{"description":"Status update successfully recorded","content":{"application/json":{"schema":{}}}},"404":{"description":"Asset not found or not authorized to access"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/asset/{asset_id}/event":{"post":{"tags":["4. Assets"],"summary":"Asset Event","description":"Send notification of an event happening on an asset.\n\nThis endpoint allows reporting various events related to an asset, such as:\n- Plug-in/plug-out events\n- Updates to charging intent\n- Charge now events\n\nIf a tariff is included, it must comply with the OSM opening hours standard (https://wiki.openstreetmap.org/wiki/Key:opening_hours) for off-peak times and have a valid timezone, or a 400 error will be returned.","operationId":"asset_event_entities_asset__asset_id__event_post","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"},"name":"asset_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetEventRequest"}}},"required":true},"responses":{"200":{"description":"Event successfully processed","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid event data"},"404":{"description":"Asset not found or not authorized to access"},"500":{"description":"Server error while processing event"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/asset/{asset_id}/event/plug-in":{"post":{"tags":["4. Assets"],"summary":"Asset Plug In Event","description":"Send notification of a car being plugged in.\n\nTariff, vehicle and intent information may be optionally provided.\nIf a tariff is included, it must comply with the OSM opening hours standard (https://wiki.openstreetmap.org/wiki/Key:opening_hours) for off-peak times and have a valid timezone, or a 400 error will be returned.","operationId":"asset_plug_in_event_entities_asset__asset_id__event_plug_in_post","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"},"name":"asset_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlugInEventRequest"}}},"required":true},"responses":{"200":{"description":"Plug-in event successfully processed","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid tariff format or timezone"},"404":{"description":"Asset not found or not authorized to access"},"500":{"description":"Server error while processing event"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/asset/{asset_id}/event/plug-out":{"post":{"tags":["4. Assets"],"summary":"Asset Plug Out Event","description":"Send notification of a car being unplugged from an asset.","operationId":"asset_plug_out_event_entities_asset__asset_id__event_plug_out_post","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"},"name":"asset_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlugOutEventRequest"}}},"required":true},"responses":{"200":{"description":"Plug-out event successfully processed","content":{"application/json":{"schema":{}}}},"404":{"description":"Asset not found or not authorized to access"},"500":{"description":"Server error while processing event"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/asset/{asset_id}/event/intent":{"post":{"tags":["4. Assets"],"summary":"Asset Intent Update Event","description":"Send notification of an intent being updated on an asset.","operationId":"asset_intent_update_event_entities_asset__asset_id__event_intent_post","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"},"name":"asset_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntentEventRequest"}}},"required":true},"responses":{"200":{"description":"Intent event successfully processed","content":{"application/json":{"schema":{}}}},"404":{"description":"Asset not found or not authorized to access"},"500":{"description":"Server error while processing event"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/asset/{asset_id}/event/charge-now":{"post":{"tags":["4. Assets"],"summary":"Asset Charge Now Event","description":"Send notification of a charge now request for an asset.","operationId":"asset_charge_now_event_entities_asset__asset_id__event_charge_now_post","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"},"name":"asset_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChargeNowEventRequest"}}},"required":true},"responses":{"200":{"description":"Charge now event successfully processed","content":{"application/json":{"schema":{}}}},"404":{"description":"Asset not found or not authorized to access"},"500":{"description":"Server error while processing event"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/asset/{asset_id}/event/charge-now-deleted":{"post":{"tags":["4. Assets"],"summary":"Asset Charge Now Deleted Event","description":"Send notification of a charge now request being deleted for an asset.","operationId":"asset_charge_now_deleted_event_entities_asset__asset_id__event_charge_now_deleted_post","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"},"name":"asset_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChargeNowDeletedEventRequest"}}},"required":true},"responses":{"200":{"description":"Charge now deleted event successfully processed","content":{"application/json":{"schema":{}}}},"404":{"description":"Asset not found or not authorized to access"},"500":{"description":"Server error while processing event"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/asset/{asset_id}/event/tariff-update":{"post":{"tags":["4. Assets"],"summary":"Asset Tariff Update Event","description":"Send notification of a tariff update for an asset.\n\nThe `off_peak_times` field must comply with the OSM opening hours standard (https://wiki.openstreetmap.org/wiki/Key:opening_hours) and have a valid timezone, or a 400 error will be returned.\n\nThe same off-peak times apply every day, day-of-week selectors are not supported. Use `,` to separate multiple time ranges. Common examples:\n- Same-day off-peak (e.g. midnight to 7am): `00:00-07:00`\n- Overnight off-peak (e.g. 11:30pm to 5:30am): `00:00-05:30, 23:30-24:00`","operationId":"asset_tariff_update_event_entities_asset__asset_id__event_tariff_update_post","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"},"name":"asset_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TariffUpdateEventRequest"}}},"required":true},"responses":{"200":{"description":"Tariff update event successfully processed","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid tariff format or timezone"},"404":{"description":"Asset not found or not authorized to access"},"500":{"description":"Server error while processing event"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/asset/{asset_id}/intent":{"get":{"tags":["4. Assets"],"summary":"Get Latest Intent","description":"Get the last recorded intent.","operationId":"get_latest_intent_entities_asset__asset_id__intent_get","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"},"name":"asset_id","in":"path"}],"responses":{"200":{"description":"Last intent successfully retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntentResponse"}}}},"404":{"description":"Intent not found or not authorized to access"},"500":{"description":"Server error while retrieving event"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/asset/{asset_id}/battery-schedule":{"get":{"tags":["4. Assets"],"summary":"Get Battery Schedule","description":"Get the active battery schedule.","operationId":"get_battery_schedule_entities_asset__asset_id__battery_schedule_get","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"},"name":"asset_id","in":"path"}],"responses":{"200":{"description":"Battery schedule successfully retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatteryScheduleResponse"}}}},"403":{"description":"Permission denied"},"404":{"description":"Battery not found or not authorized to access"},"500":{"description":"Server error while retrieving event"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/asset/{asset_id}/event/plug-in-schedule":{"post":{"tags":["4. Assets"],"summary":"Asset Plug In Schedule Event","description":"Submit a charging schedule and receive a modified schedule.","operationId":"asset_plug_in_schedule_event_entities_asset__asset_id__event_plug_in_schedule_post","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"},"name":"asset_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlugInScheduleEventRequest"}}},"required":true},"responses":{"200":{"description":"Modified charging schedule successfully retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlugInScheduleEventResponse"}}}},"403":{"description":"Site lacking required limited_pause dispatch consent"},"404":{"description":"Charger not found or not authorized to access"},"500":{"description":"Server error while scheduling charging"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/asset/{asset_id}/price-curve":{"get":{"tags":["4. Assets"],"summary":"Get Price Curve","description":"Half-hourly data of prices per MWh of flexed energy for the asset. Prices are returned from the current Settlement Period until 23:00 UK time on the same day or next day. Next day prices are available from 14:00 UK time.","operationId":"get_price_curve_entities_asset__asset_id__price_curve_get","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"},"name":"asset_id","in":"path"}],"responses":{"200":{"description":"Price curve successfully retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceCurveResponse"}}}},"403":{"description":"Permission denied"},"404":{"description":"Asset not found or not authorized to access"},"500":{"description":"Server error while retrieving price curve"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/asset/{asset_id}/todays-dispatch-schedule":{"get":{"tags":["4. Assets"],"summary":"Get Todays Dispatch Schedule","description":"Get today's dispatch plan for a battery: the ordered periods describing how the inverter and battery are scheduled to operate today (in UK time), each with a start time, an end time and an action of CHARGE, DISCHARGE, LOCK, FEED_IN or SELF_USE. LOCK holds the battery at its current state of charge.\n\nPlans are only generated in the production environment: anywhere else, including the sandbox, this returns an empty plan (`{\"periods\": []}`).\n\nThe `asset_id` is the one returned when the asset was onboarded, and can also be found via `GET /entities/asset`. Only batteries have a plan of this shape, so any other asset type is a 404, indistinguishable from an unknown asset.\n\nAn empty plan is also returned when a battery has no plan for today: it is not optimised (no asset model recorded, or no full schedule control or wholesale market consent), or today's plan has not been generated yet. The response does not distinguish between these.","operationId":"get_todays_dispatch_schedule_entities_asset__asset_id__todays_dispatch_schedule_get","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"},"name":"asset_id","in":"path"}],"responses":{"200":{"description":"Today's dispatch plan retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlainDispatchScheduleResponse"}}}},"403":{"description":"Permission denied"},"404":{"description":"Asset not found, not a battery, or not authorized to access"},"500":{"description":"Server error while retrieving dispatch schedule"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/site":{"get":{"tags":["3. Sites"],"summary":"Get Sites","description":"Retrieve sites, optionally filtering by MPAN or postcode.\n\nReturns a page of sites with the total count and the requested subset of site records. Use the limit and offset parameters to navigate through pages of results.","operationId":"get_sites_entities_site_get","parameters":[{"description":"Filter sites by MPAN","required":false,"schema":{"type":"string","title":"Mpan","description":"Filter sites by MPAN"},"name":"mpan","in":"query"},{"description":"Filter sites by postcode","required":false,"schema":{"type":"string","title":"Postcode","description":"Filter sites by postcode"},"name":"postcode","in":"query"},{"description":"Maximum number of sites to return (1-5000)","required":false,"schema":{"type":"integer","maximum":5000.0,"minimum":1.0,"title":"Limit","description":"Maximum number of sites to return (1-5000)","default":10},"name":"limit","in":"query"},{"description":"Number of sites to skip for pagination","required":false,"schema":{"type":"integer","minimum":0.0,"title":"Offset","description":"Number of sites to skip for pagination","default":0},"name":"offset","in":"query"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteResponsePage"}}}},"500":{"description":"Internal server error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"post":{"tags":["3. Sites"],"summary":"Create Site","description":"Register a new site.\n\nThe site must have a valid address and postcode. If a site with the same address already exists, a 409 error will be returned with the existing site ID.","operationId":"create_site_entities_site_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteResponse"}}}},"400":{"description":"Invalid request or site already exists"},"404":{"description":"Referenced entity not found"},"409":{"description":"Site with same address already exists"},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorWithDetail"}}}},"500":{"description":"Internal server error"}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/site/initialise":{"post":{"tags":["3. Sites"],"summary":"Initialise Site","description":"Initialise a site with one or more assets.\n\nThis endpoint upserts the site and assets (creating them if they don't exist, or filling in missing fields if they do), and returns eligibility information.\n\n**No enrollment side effects**: Use the `/enrol` endpoint to commit to enrollment.","operationId":"initialise_site_entities_site_initialise_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InitialiseRequest"}}},"required":true},"responses":{"200":{"description":"Successfully initialised site and assets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InitialiseResponse"}}}},"400":{"description":"Invalid request (e.g. missing boundary meter consent T&Cs)"},"404":{"description":"Referenced entity not found"},"409":{"description":"Asset conflict (e.g. asset type mismatch or asset registered to a different site)"},"500":{"description":"Server error during initialisation"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/site/check-eligibility":{"post":{"tags":["3. Sites"],"summary":"Check Eligibility","description":"Check whether an MPAN, optionally combined with an asset model, is eligible for enrolment. No data is persisted.","operationId":"check_eligibility_entities_site_check_eligibility_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EligibilityCheckRequest"}}},"required":true},"responses":{"200":{"description":"Eligibility evaluated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EligibilityCheckResponse"}}}},"404":{"description":"Referenced entity not found (e.g. unknown asset_model)"},"500":{"description":"Server error during eligibility check"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/site/{site_id}/enrol":{"post":{"tags":["3. Sites"],"summary":"Enrol Site","description":"Enrol a site in a proposition.\n\nThis is the commitment point — it activates the proposition for the site.\n\nIdempotent: if the site is already enrolled, returns `already_enrolled` without making changes.\n\nIf the site previously withdrew from this proposition, returns 422. Set `override_withdrawal` to true to re-enrol.","operationId":"enrol_site_entities_site__site_id__enrol_post","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Site Id"},"name":"site_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrolRequest"}}},"required":true},"responses":{"200":{"description":"Successfully enrolled or already enrolled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrolResponse"}}}},"404":{"description":"Site not found or not authorized"},"422":{"description":"Eligibility prerequisites not met or previously withdrew consent"},"500":{"description":"Internal server error"}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/site/onboard":{"post":{"tags":["3. Sites"],"summary":"Onboard","description":"Initialise a site and its assets, and enrol them in a proposition in a single call.\n\nThis endpoint will:\n1. Upsert the site and asset(s)\n2. Enrol in the relevant flex proposition\n\nThe response returns the site and asset IDs you'll use in subsequent calls, and the enrolment outcome.\n\nOnboarding is idempotent and atomic — sending the same site or asset returns the existing record with any new fields merged in; if enrolment fails, nothing is stored.","operationId":"onboard_entities_site_onboard_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardRequest"}}},"required":true},"responses":{"200":{"description":"Site and assets persisted, site enrolled in proposition","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardResponse"},"example":{"site":{"site_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","site_created":true,"fields_updated":[],"warnings":[]},"assets":[{"asset_id":"b2c3d4e5-f6a7-8901-bcde-f23456789012","external_id":"charger-001","asset_created":true,"fields_updated":[],"warnings":[]}],"enrolment":{"site_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","status":"enrolled"}}}}},"400":{"description":"Invalid request (missing meter consent, invalid email, etc.)"},"404":{"description":"Referenced entity not found"},"409":{"description":"Asset conflict (e.g. asset type mismatch or asset registered to a different site)"},"422":{"description":"Eligibility prerequisites not met or previously withdrew consent"},"500":{"description":"Server error"}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/site/{site_id}/unenrol":{"post":{"tags":["3. Sites"],"summary":"Unenrol Site","description":"Unenrol a site from a proposition.\n\nWithdraws the site from the proposition and prevents further scheduling. Does not delete the site or its assets.\n\nUse when the user is opting out of this proposition specifically — for example, they toggled it off in your app. The site and assets are kept, any other propositions they're enrolled in (such as Capacity Market) are unaffected, and the user can re-enrol later and still access their payments.\n\nIf the user is leaving entirely (moving house, support-led removal, etc.), use `offboard-site-and-assets` instead.\n\nIdempotent: if the site is already unenrolled, returns `already_unenrolled` without making changes.","operationId":"unenrol_site_entities_site__site_id__unenrol_post","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Site Id"},"name":"site_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnenrolRequest"}}},"required":true},"responses":{"200":{"description":"Successfully unenrolled or already unenrolled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnenrolResponse"}}}},"404":{"description":"Site not found or not authorized"},"500":{"description":"Internal server error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/site/onboard-site-and-asset":{"post":{"tags":["3. Sites"],"summary":"Onboard Site And Asset","description":"**Deprecated** — prefer [`/onboard`](/api-reference/entities/site/onboard) instead.\n\nThe new `/onboard` endpoint supports multiple assets per site in a single call and includes improvements in idempotency, resilience and response details.\n\n---\n\nRegister a site, asset, and dispatch consent in a single call.\n\nCreates the site and asset, grants consent, and enrols in the relevant flex proposition.\n\nThis endpoint will:\n1. Create the site\n2. Create the asset associated with the site\n3. Enrol in the relevant flex proposition\n\nReturns the created site and asset, including their IDs. Fails if the site or asset already exists.","operationId":"onboard_site_and_asset_entities_site_onboard_site_and_asset_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingRequest"}}},"required":true},"responses":{"200":{"description":"Successfully onboarded site and asset","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingResponse"}}}},"400":{"description":"Invalid request"},"409":{"description":"Site or asset already exists"},"422":{"description":"Eligibility prerequisites not met for the requested dispatch method"},"500":{"description":"Server error during onboarding"}},"deprecated":true,"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/site/{site_id}/offboard-site-and-assets":{"post":{"tags":["3. Sites"],"summary":"Offboard Site And Assets","description":"Offboard a site and all its associated assets in a single operation.\n\nUnenrols from every proposition, and deletes the site and assets in accordance with data retention policies.\n\nUse when the user is leaving entirely — for example, they've moved house, or your support team is removing them. Payments can no longer be accessed afterwards.\n\nIf the user is only opting out of one proposition (e.g. toggling Flex Lite off in your app), use `unenrol` instead — it preserves the site and any other propositions they're enrolled in.","operationId":"offboard_site_and_assets_entities_site__site_id__offboard_site_and_assets_post","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Site Id"},"name":"site_id","in":"path"}],"responses":{"200":{"description":"Successfully offboarded site and asset","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingResponse"}}}},"400":{"description":"Invalid request"},"404":{"description":"Site not found or not authorized to access"},"500":{"description":"Server error during offboarding"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/site/{site_id}":{"get":{"tags":["3. Sites"],"summary":"Get Site","description":"Retrieve a specific site by its UUID.\n\nReturns the site details if it exists.","operationId":"get_site_entities_site__site_id__get","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Site Id"},"name":"site_id","in":"path"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteResponse"}}}},"404":{"description":"Site not found or not authorized to access"},"500":{"description":"Internal server error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"delete":{"tags":["3. Sites"],"summary":"Delete Site","description":"Delete an existing site by its UUID.\n\nThe site will only be deleted if it has no associated assets or other objects. Returns a confirmation message upon successful deletion.","operationId":"delete_site_entities_site__site_id__delete","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Site Id"},"name":"site_id","in":"path"}],"responses":{"204":{"description":"Site successfully deleted"},"400":{"description":"Site cannot be deleted due to associated objects"},"404":{"description":"Site not found or not authorized to access"},"500":{"description":"Internal server error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"patch":{"tags":["3. Sites"],"summary":"Update Site","description":"Update an existing site's information.\n\nOnly fields included in the request will be updated. Returns the updated site details.","operationId":"update_site_entities_site__site_id__patch","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Site Id"},"name":"site_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteUpdateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteResponse"}}}},"404":{"description":"Site not found or not authorized to access"},"500":{"description":"Internal server error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/site/{site_id}/eligibility":{"get":{"tags":["3. Sites"],"summary":"Get Site Eligibility","description":"Read-only eligibility breakdown for a site and its assets. Returns the list of propositions the site can enrol in, along with per-asset eligibility detail.","operationId":"get_site_eligibility_entities_site__site_id__eligibility_get","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Site Id"},"name":"site_id","in":"path"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteEligibilityDetail"}}}},"404":{"description":"Site not found or not authorized"},"500":{"description":"Internal server error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/site/{site_id}/meter-consent":{"post":{"tags":["3. Sites"],"summary":"Add Site Meter Consent","description":"Add boundary meter consent for a site.\n\nConfirm that the site has consented for Axle to retrieve its boundary meter readings. This is required for participation in the wholesale market for assets that do not have CoP11 approval, but may also be provided via other endpoints (e.g. during site onboarding). Returns the updated site details with the new consent timestamp.","operationId":"add_site_meter_consent_entities_site__site_id__meter_consent_post","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Site Id"},"name":"site_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteMeterConsentRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteResponse"}}}},"400":{"description":"Invalid request"},"404":{"description":"Site not found or not authorized to access"},"500":{"description":"Internal server error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/site/{site_id}/dispatch-consent":{"post":{"tags":["3. Sites"],"summary":"Add Site Dispatch Consent","description":"Add dispatch consent for a site to particpate in flex markets.\n\nThis enables the site to participate with the specified dispatch consent methods. Returns the updated site details with the new dispatch consent information.","operationId":"add_site_dispatch_consent_entities_site__site_id__dispatch_consent_post","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Site Id"},"name":"site_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteDispatchConsentRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteResponse"}}}},"404":{"description":"Site not found or not authorized to access"},"500":{"description":"Internal server error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/site/{site_id}/dispatch-deconsent":{"post":{"tags":["3. Sites"],"summary":"Remove Site Dispatch Consent","description":"Remove dispatch consent for a site to stop participation in flex markets.\n\nThis disables the site's participation with the specified dispatch consent methods. Returns the updated site details with the consent information removed.","operationId":"remove_site_dispatch_consent_entities_site__site_id__dispatch_deconsent_post","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Site Id"},"name":"site_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteDispatchConsentRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteResponse"}}}},"404":{"description":"Site not found or not authorized to access"},"500":{"description":"Internal server error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/site/{site_id}/token":{"post":{"tags":["3. Sites"],"summary":"Add Site Auth Token","description":"Provide an auth token to Axle, for dispatching the site's assets.\n\nThis token should provide access to all of the assets registered against the specified site.\n\nThis is only required where Axle is not able to access this site via an aggregated API in your systems.","operationId":"add_site_auth_token_entities_site__site_id__token_post","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Site Id"},"name":"site_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteAuthTokenRequest"}}},"required":true},"responses":{"200":{"description":"Token successfully processed","content":{"application/json":{"schema":{}}}},"404":{"description":"Site not found or not authorized to access"},"500":{"description":"Internal server error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/site/{site_id}/flex-events":{"get":{"tags":["3. Sites"],"summary":"Get Site Flex Events","description":"Get info on flex events the site has participated in, including estimated and final gross revenues.\n\nThese estimates can be used for a variety of purposes, including paying out end-users before the final settlement data is available.However, to avoid overpayments it is recommended to only pay out a percentage of the estimated revenue initially, and top-up once final revenues are available.\n\nNote: it is possible for gross revenues to be negative in some scenarios, e.g. if the site flexed in the wrong direction by consuming more energy while it was instructed to consume less.","operationId":"get_site_flex_events_entities_site__site_id__flex_events_get","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Site Id"},"name":"site_id","in":"path"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteFlexEventsResponse"}}}},"404":{"description":"Site not found or not authorized to access"},"500":{"description":"Internal server error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/site/{site_id}/price-curve":{"get":{"tags":["3. Sites"],"summary":"Get Price Curve","description":"Half-hourly data of prices per MWh of flexed energy for the asset. Prices are returned from the current Settlement Period until 23:00 UK time on the same day or next day. Next day prices are available from 14:00 UK time.","operationId":"get_price_curve_entities_site__site_id__price_curve_get","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Site Id"},"name":"site_id","in":"path"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceCurveResponse"}}}},"404":{"description":"Site not found or not authorized to access"},"500":{"description":"Internal server error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/entities/site/{site_id}/oauth/{provider}/initiate":{"get":{"tags":["3. Sites"],"summary":"Initiate Site Oauth","description":"Initiates OAuth flow by returning the provider's authorisation URL for the client to redirect to","operationId":"initiate_site_oauth_entities_site__site_id__oauth__provider__initiate_get","parameters":[{"required":true,"schema":{"$ref":"#/components/schemas/OAuthProvider"},"name":"provider","in":"path"},{"required":true,"schema":{"type":"string","format":"uuid","title":"Site Id"},"name":"site_id","in":"path"}],"responses":{"200":{"description":"Returns OAuth authorisation URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthInitiateResponse"}}}},"400":{"description":"Unsupported OAuth provider or not configured"},"500":{"description":"Internal server error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/meter/by-address":{"post":{"tags":["2. Meters"],"summary":"Get Meter Info By Address","description":"Retrieve detailed information about a meter using its address.\n\nThis endpoint allows direct lookup of meter information by address, when the MPAN is not already known (if the MPAN is known, use the /meter/{mpan} endpoint).","operationId":"get_meter_info_by_address_meter_by_address_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeterByAddressRequest"}}},"required":true},"responses":{"200":{"description":"Meter information for the requested address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeterResponse"}}}},"202":{"description":"Unique meter was not found for the requested address (no meter or ambiguous address)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorWithDetail"}}}},"422":{"description":"Provided address input was invalid/ ambiguous","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorWithDetail"}}}},"500":{"description":"Something went wrong whilst processing the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorWithDetail"}}}},"503":{"description":"Request to meter data provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorWithDetail"}}}},"504":{"description":"Request to meter data provider timed out","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorWithDetail"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/meter/by-mpan":{"post":{"tags":["2. Meters"],"summary":"Get Meter Info By Mpan","description":"Retrieve detailed information about a meter using its MPAN.\n\nThis endpoint allows direct lookup of meter information when the MPAN is already known.","operationId":"get_meter_info_by_mpan_meter_by_mpan_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeterByMPANRequest"}}},"required":true},"responses":{"200":{"description":"Meter information for the requested MPAN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeterResponse"}}}},"202":{"description":"No meter was found for the requested MPAN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorWithDetail"}}}},"422":{"description":"Invalid MPAN or meter not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorWithDetail"}}}},"504":{"description":"Request to meter data provider timed out"}},"security":[{"OAuth2PasswordBearer":[]}]}},"/meter/":{"get":{"tags":["2. Meters"],"summary":"Get Meter Info By Address Deprecated","description":"Retrieve detailed information about a meter using its address.\n\nThis endpoint allows direct lookup of meter information by address, when the MPAN is not already known (if the MPAN is known, use the /meter/{mpan} endpoint).","operationId":"get_meter_info_by_address_deprecated_meter__get","parameters":[{"description":"Full address string, e.g. '221B Baker Street, London, NW1 6XE'. Must include postcode and begin with house number/ name or other uniquely-identifying information. May be constructed from individual address components, concatenated with separating commas. Better formatting may increase the chance of a meter being found.","required":true,"schema":{"type":"string","title":"Address","description":"Full address string, e.g. '221B Baker Street, London, NW1 6XE'. Must include postcode and begin with house number/ name or other uniquely-identifying information. May be constructed from individual address components, concatenated with separating commas. Better formatting may increase the chance of a meter being found."},"name":"address","in":"query"}],"responses":{"200":{"description":"Meter information for the requested address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeterResponse"}}}},"422":{"description":"Invalid/ ambiguous address, or no meter found at address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorWithDetail"}}}},"500":{"description":"Something went wrong whilst processing the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorWithDetail"}}}},"503":{"description":"Request to meter data provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorWithDetail"}}}},"504":{"description":"Request to meter data provider timed out","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorWithDetail"}}}}},"deprecated":true,"security":[{"OAuth2PasswordBearer":[]}]}},"/meter/search":{"get":{"tags":["2. Meters"],"summary":"Search Meters","description":"Search for all electricity meters in the vicinity of a given postcode/ address.\n\nThis endpoint allows searching for meters by postcode and optionally by building identifier. For data protection and contractual reasons, meter details are returned in an encrypted format that can be used in subsequent API calls to retrieve the full meter information.\n\nThe search works in three steps:\n1. Search for meters at the specified address using this endpoint\n2. Ask the end-user to select the correct address from the list\n3. Call the `/meter/by-ref/{meter_ref}` endpoint with the corresponding reference to get the full meter details\n\nNB: This should not be used with procedural address matching; it is intended for end-user interaction only. For precise address matching, use the `/meter/by-address` endpoint instead, which will perform matching for you.","operationId":"search_meters_meter_search_get","parameters":[{"description":"Postcode at which the requested meter is registered","required":true,"schema":{"type":"string","title":"Postcode","description":"Postcode at which the requested meter is registered"},"name":"postcode","in":"query"},{"description":"House number or house/building name, e.g. '3', '10A', 'Flat 4', 'The Old Barn'","required":false,"schema":{"type":"string","title":"Building Identifier","description":"House number or house/building name, e.g. '3', '10A', 'Flat 4', 'The Old Barn'"},"name":"building_identifier","in":"query"}],"responses":{"200":{"description":"List of meters matching the address; may be empty","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/MeterSearchResponse"},"type":"array","title":"Response 200 Search Meters Meter Search Get"}}}},"422":{"description":"Invalid postcode or no meters found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorWithDetail"}}}},"500":{"description":"Something went wrong whilst processing the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorWithDetail"}}}},"503":{"description":"Request to meter data provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorWithDetail"}}}},"504":{"description":"Request to meter data provider timed out","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorWithDetail"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/meter/{meter_ref}/mpan":{"get":{"tags":["2. Meters"],"summary":"Get Meter Info By Meter Ref","description":"This endpoint is deprecated. Use the `/by-ref/{meter_ref}` instead.","operationId":"get_meter_info_by_meter_ref_meter__meter_ref__mpan_get","parameters":[{"description":"Encrypted reference of the meter whose info is requested, as returned from the /meter/search endpoint","required":true,"schema":{"type":"string","title":"Meter Ref","description":"Encrypted reference of the meter whose info is requested, as returned from the /meter/search endpoint"},"name":"meter_ref","in":"path"}],"responses":{"200":{"description":"Meter information for the requested reference","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeterResponse"}}}},"422":{"description":"Invalid meter reference","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorWithDetail"}}}}},"deprecated":true,"security":[{"OAuth2PasswordBearer":[]}]}},"/meter/by-ref/{meter_ref}":{"get":{"tags":["2. Meters"],"summary":"Get Meter Info By Meter Ref","description":"Retrieve meter information using an encrypted reference.","operationId":"get_meter_info_by_meter_ref_meter_by_ref__meter_ref__get","parameters":[{"description":"Encrypted reference of the meter whose info is requested, as returned from the /meter/search endpoint","required":true,"schema":{"type":"string","title":"Meter Ref","description":"Encrypted reference of the meter whose info is requested, as returned from the /meter/search endpoint"},"name":"meter_ref","in":"path"}],"responses":{"200":{"description":"Meter information for the requested reference","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeterResponse"}}}},"422":{"description":"Invalid meter reference","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorWithDetail"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/meter/{mpan}":{"get":{"tags":["2. Meters"],"summary":"Get Meter Info By Mpan Deprecated","description":"Retrieve detailed information about a meter using its MPAN.\n\nThis endpoint allows direct lookup of meter information when the MPAN is already known.","operationId":"get_meter_info_by_mpan_deprecated_meter__mpan__get","parameters":[{"description":"13-digit Meter Point Administration Number (MPAN) whose meter info is requested","required":true,"schema":{"type":"string","title":"Mpan","description":"13-digit Meter Point Administration Number (MPAN) whose meter info is requested"},"name":"mpan","in":"path"}],"responses":{"200":{"description":"Meter information for the requested MPAN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeterResponse"}}}},"422":{"description":"Invalid MPAN or meter not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorWithDetail"}}}},"500":{"description":"Something went wrong whilst processing the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorWithDetail"}}}},"503":{"description":"Request to meter data provider failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorWithDetail"}}}},"504":{"description":"Request to meter data provider timed out","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorWithDetail"}}}}},"deprecated":true,"security":[{"OAuth2PasswordBearer":[]}]}},"/auth/token-form":{"post":{"tags":["1. Authentication"],"summary":"Login For Access Token Form","description":"Authenticate using username and password submitted via form data.\n\nThis endpoint is compatible with standard OAuth2 clients that use form-based authentication. Returns an access token upon successful authentication.\n\nThe returned token is valid for 1 hour, after which a new token must be requested.","operationId":"login_for_access_token_form_auth_token_form_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_login_for_access_token_form_auth_token_form_post"}}},"required":true},"responses":{"200":{"description":"Successfully authenticated with access token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Token"}}}},"401":{"description":"Incorrect username or password"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/users/me/":{"get":{"tags":["1. Authentication"],"summary":"Read Users Me","description":"Get information about the currently authenticated user.\n\nReturns the user details for the authenticated user based on the provided access token.","operationId":"read_users_me_auth_users_me__get","responses":{"200":{"description":"Current user information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}},"401":{"description":"Not authenticated"}},"security":[{"OAuth2PasswordBearer":[]}]}},"/auth/component-token":{"post":{"tags":["1. Authentication"],"summary":"Create Component Token","description":"Authenticate on behalf of an end user by supplying their external user ID.\n\nThis endpoint is used by authenticated API clients to create a user-scoped access token for a specific end user (referenced by their external ID) in the API client's organisation. If no such end user exists, one will be created on demand.\n\nReturns a bearer access token scoped to this end user upon success.\n\nThis token is site-scoped and valid for 24 hours, longer-lived than the standard organisation token (1 hour) as it is intended for end-user sessions.","operationId":"create_component_token_auth_component_token_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_create_component_token_auth_component_token_post"}}},"required":true},"responses":{"200":{"description":"Successfully authenticated with a user-scoped access token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComponentToken"}}}},"404":{"description":"Error trying to find organisation"},"500":{"description":"Server error when trying to find or create the user"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/data/readings":{"post":{"tags":["5. Data"],"summary":"Post Readings","description":"Send asset readings data to Axle using the generic readings format.\n\nThis endpoint accepts compressed data using gzip encoding. Returns statuses of the processed readings, indicating whether each reading was accepted or rejected.\n\n**Direction convention:** for readings that can be either positive or negative (e.g. `boundary_import_kw`, `battery_inverter_import_kw`), a positive value denotes *import* (power flowing in from the grid, or into the battery) and a negative value denotes *export* (power flowing out to the grid, or out of the battery). All other reading types are unidirectional; the required sign for each `label` is documented in the `ReadingDataPointLabel` schema below.","operationId":"post_readings_data_readings_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadingsDataPoints"}}},"required":true},"responses":{"200":{"description":"Successfully recorded readings with processing summary","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadingsResponse"}}}},"400":{"description":"Invalid data format or validation error"},"403":{"description":"Permission denied"},"500":{"description":"Server error while recording readings"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/rewards/{site_id}/info":{"get":{"tags":["6. Rewards"],"summary":"Get Balance Info","description":"Get info about current balance and total earnings for the site. Requires an organisational bearer token.","operationId":"get_balance_info_rewards__site_id__info_get","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Site Id"},"name":"site_id","in":"path"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BalanceInfoResponse"}}}},"404":{"description":"Site not found or not authorized to access"},"500":{"description":"Internal server error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/rewards/{site_id}/url/balance":{"get":{"tags":["6. Rewards"],"summary":"Get Rewards Balance Withdrawal Url","description":"Get a temporary link to an Axle-hosted form through which users can view and withdraw rewards. Requires an organisational bearer token.","operationId":"get_rewards_balance_withdrawal_url_rewards__site_id__url_balance_get","parameters":[{"description":"The ID on Axle's system for this user. The site_id can be easily retrieved from the get-by-external-id endpoint.","required":true,"schema":{"type":"string","format":"uuid","title":"Site Id","description":"The ID on Axle's system for this user. The site_id can be easily retrieved from the get-by-external-id endpoint."},"name":"site_id","in":"path"},{"description":"Require email verification before the user can link a bank account. Balance and transaction-history views are not gated. When omitted, falls back to the organisation's configured 2FA posture.","required":false,"schema":{"type":"boolean","title":"Enforce Two Factor Auth","description":"Require email verification before the user can link a bank account. Balance and transaction-history views are not gated. When omitted, falls back to the organisation's configured 2FA posture."},"name":"enforce_two_factor_auth","in":"query"},{"description":"Where to redirect after completion","required":true,"schema":{"type":"string","title":"Redirect Uri","description":"Where to redirect after completion"},"name":"redirect_uri","in":"query"},{"description":"Hide transaction history from the user","required":false,"schema":{"type":"boolean","title":"Hide Transactions","description":"Hide transaction history from the user","default":false},"name":"hide_transactions","in":"query"},{"description":"Skip the balance page and go straight to bank setup if no account exists","required":false,"schema":{"type":"boolean","title":"Auto Redirect To Setup","description":"Skip the balance page and go straight to bank setup if no account exists","default":false},"name":"auto_redirect_to_setup","in":"query"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BalanceWithdrawalURLResponse"}}}},"404":{"description":"Site not found or not authorized to access"},"500":{"description":"Internal server error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/rewards/{site_id}/transactions":{"get":{"tags":["6. Rewards"],"summary":"Get Transaction History","description":"Get history of transactions for the site. Requires an organisational bearer token.","operationId":"get_transaction_history_rewards__site_id__transactions_get","parameters":[{"required":true,"schema":{"type":"string","format":"uuid","title":"Site Id"},"name":"site_id","in":"path"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionDataResponse"}}}},"404":{"description":"Site not found or not authorized to access"},"500":{"description":"Internal server error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/examples/dispatch-event":{"get":{"tags":["8. Examples"],"summary":"Get Example Dispatch Event","description":"Get an example dispatch event.\n\nReturns a pre-filled DispatchEvent object that can be used as a reference for the expected format and structure of dispatch events.","operationId":"get_example_dispatch_event_examples_dispatch_event_get","responses":{"200":{"description":"Example dispatch event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DispatchEvent"}}}},"500":{"description":"Server error while generating example"}},"security":[{"OAuth2PasswordBearer":[]}]}},"/examples/ocpp-charging-profile":{"get":{"tags":["8. Examples"],"summary":"Get Example Ocpp Charging Profile","description":"Get an example OCPP charging profile.\n\nReturns a pre-filled SetChargingProfileRequest object that can be used as a reference for the expected format and structure of OCPP charging profiles.","operationId":"get_example_ocpp_charging_profile_examples_ocpp_charging_profile_get","responses":{"200":{"description":"Example OCPP charging profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetChargingProfileRequest"}}}},"500":{"description":"Server error while generating example"}},"security":[{"OAuth2PasswordBearer":[]}]}},"/validation/mpan":{"post":{"tags":["7. Validation"],"summary":"Validate Mpan","description":"Validates the provided MPAN as one that is well-formatted and is associated with a connected import meter","operationId":"validate_mpan_validation_mpan_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MPANValidationRequest"}}},"required":true},"responses":{"200":{"description":"The provided MPAN is of valid format and has been verified as connected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MPANValidationResponse"}}}},"400":{"description":"The provided MPAN has an invalid format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MPANValidationError"}}}},"404":{"description":"The provided MPAN is formatted correctly, but a connected import meter could not be found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MPANValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}}},"components":{"schemas":{"AssetEligibilityDetail":{"properties":{"asset_id":{"type":"string","format":"uuid","title":"Asset Id","examples":["b2c3d4e5-f6a7-8901-bcde-f23456789012"]},"external_id":{"type":"string","title":"External Id","examples":["charger-001"]},"propositions":{"items":{"$ref":"#/components/schemas/PropositionEligibility"},"type":"array","title":"Propositions","default":[]}},"type":"object","required":["asset_id","external_id"],"title":"AssetEligibilityDetail","description":"Eligibility detail for a single asset across all propositions."},"AssetEventRequest":{"properties":{"event_type":{"$ref":"#/components/schemas/AssetEventType"},"intent":{"allOf":[{"$ref":"#/components/schemas/Intent"}],"title":"Intent","description":"Intent to charge the vehicle. This should only be included for \"plug_in\" and \"intent_update\" events"},"vehicle":{"allOf":[{"$ref":"#/components/schemas/Vehicle"}],"title":"Vehicle","description":"Vehicle information. This should only be included for \"plug_in\" and \"intent_update\" events"},"tariff":{"allOf":[{"$ref":"#/components/schemas/Tariff"}],"title":"Tariff","description":"Tariff information. This should only be included for \"plug_in\" and \"intent_update\" events"},"end_at":{"type":"string","format":"date-time","title":"End At","description":"End time for the charge. This should only be included for \"charge_now\" events"}},"type":"object","required":["event_type"],"title":"AssetEventRequest"},"AssetEventType":{"type":"string","enum":["plug_in","plug_out","intent_update","charge_now","charge_now_deleted"],"title":"AssetEventType","description":"An enumeration."},"AssetProperties":{"properties":{"power_kw":{"type":"number","minimum":0.0,"title":"Power Kw","description":"Power rating in kW"},"capacity_kwh":{"type":"number","minimum":0.0,"title":"Capacity Kwh","description":"Capacity in kWh"}},"type":"object","title":"AssetProperties","description":"Optional properties for an asset."},"AssetRequest":{"properties":{"external_id":{"type":"string","title":"External Id","description":"Vendor-specific identifier for the asset"},"type":{"allOf":[{"$ref":"#/components/schemas/CreatableAssetType"}],"description":"Type of asset being created"},"site_id":{"type":"string","format":"uuid","title":"Site Id","description":"ID of the site where the asset is located"},"properties":{"allOf":[{"$ref":"#/components/schemas/AssetProperties"}],"title":"Properties","description":"Optional asset properties"},"asset_model":{"type":"string","title":"Asset Model","description":"Name of the AssetModel to assign (looked up by name)"},"installation_date":{"type":"string","format":"date","title":"Installation Date","description":"Date when the asset was installed"},"serial_number":{"type":"string","title":"Serial Number","description":"The serial number of the asset"}},"type":"object","required":["external_id","type","site_id"],"title":"AssetRequest","description":"Request model for creating a new asset."},"AssetResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id","description":"Axle's internal UUID for the asset"},"external_id":{"type":"string","title":"External Id","description":"Vendor-specific identifier for the asset"},"type":{"allOf":[{"$ref":"#/components/schemas/AssetType"}],"description":"Type of asset"},"site_id":{"type":"string","format":"uuid","title":"Site Id","description":"ID of the site where the asset is located"},"properties":{"allOf":[{"$ref":"#/components/schemas/AssetProperties"}],"title":"Properties","description":"Optional asset properties"}},"type":"object","required":["id","external_id","type","site_id"],"title":"AssetResponse","description":"Response model for asset information."},"AssetResponsePage":{"properties":{"assets":{"items":{"$ref":"#/components/schemas/AssetResponse"},"type":"array","title":"Assets","description":"List of assets for the current page"},"total_num_assets":{"type":"integer","title":"Total Num Assets","description":"Total number of assets available"},"total_num_pages":{"type":"integer","title":"Total Num Pages","description":"Total number of pages available"},"page_number":{"type":"integer","title":"Page Number","description":"Current page number (1-based)"}},"type":"object","required":["assets","total_num_assets","total_num_pages","page_number"],"title":"AssetResponsePage","description":"Paginated response for asset listings."},"AssetType":{"type":"string","enum":["boundary meter","charger","battery","heat pump","hot water tank","frequency meter","electric_vehicle","pv inverter"],"title":"AssetType","description":"An enumeration."},"AssetUpdateRequest":{"properties":{"properties":{"allOf":[{"$ref":"#/components/schemas/AssetProperties"}],"title":"Properties","description":"Asset properties to update"},"asset_model":{"type":"string","title":"Asset Model","description":"Name of the AssetModel to assign (looked up by name)"},"installation_date":{"type":"string","format":"date","title":"Installation Date","description":"Date when the asset was installed"}},"type":"object","title":"AssetUpdateRequest","description":"Request model for updating an existing asset."},"BalanceInfoResponse":{"properties":{"current_balance_pence":{"type":"integer","title":"Current Balance Pence","description":"Current balance of the site in pence (total earnings minus total withdrawals)"},"total_earnings_pence":{"type":"integer","title":"Total Earnings Pence","description":"Lifetime earnings of the site in pence"},"minimum_withdrawal_threshold_pence":{"type":"integer","title":"Minimum Withdrawal Threshold Pence","description":"The minimum a user can withdraw in one transaction, in pence"},"withdrawal_min_wait_days":{"type":"integer","title":"Withdrawal Min Wait Days","description":"The number of days a user must wait to withdraw after their first reward"},"can_withdraw":{"type":"boolean","title":"Can Withdraw","description":"Whether the user can withdraw their balance"}},"type":"object","required":["current_balance_pence","total_earnings_pence","minimum_withdrawal_threshold_pence","withdrawal_min_wait_days","can_withdraw"],"title":"BalanceInfoResponse","description":"Response model for site balance information."},"BalanceWithdrawalURLResponse":{"properties":{"balance_withdrawal_url":{"type":"string","title":"Balance Withdrawal Url","description":"Temporary standalone URL via which an end-user may enter their bank details to withdraw their balance"},"url_expiry_timestamp":{"type":"string","format":"date-time","title":"Url Expiry Timestamp","description":"Time at which the given URL will expire"}},"type":"object","required":["balance_withdrawal_url","url_expiry_timestamp"],"title":"BalanceWithdrawalURLResponse","description":"Response model for balance withdrawal URL."},"BatteryScheduleAction":{"type":"string","enum":["charge_max","discharge_max","avoid_export","avoid_import"],"title":"BatteryScheduleAction","description":"Action to be taken during a schedule step.\n\n- charge_max: Charge the battery at maximum capacity.\n- discharge_max: Discharge the battery at maximum capacity.\n- avoid_export: Avoid exporting energy, but allow import.\n- avoid_import: Avoid importing energy, but allow export."},"BatteryScheduleResponse":{"properties":{"schedule_steps":{"items":{"$ref":"#/components/schemas/BatteryScheduleStep"},"type":"array","title":"Schedule Steps","description":"List of schedule steps for the asset"},"schedule_last_updated":{"type":"string","format":"date-time","title":"Schedule Last Updated","description":"When the schedule was last recalculated"}},"type":"object","required":["schedule_steps","schedule_last_updated"],"title":"BatteryScheduleResponse"},"BatteryScheduleStep":{"properties":{"start_timestamp":{"type":"string","format":"date-time","title":"Start Timestamp","description":"Start timestamp of the schedule step, tz-aware"},"end_timestamp":{"type":"string","format":"date-time","title":"End Timestamp","description":"End timestamp of the schedule step, tz-aware"},"action":{"allOf":[{"$ref":"#/components/schemas/BatteryScheduleAction"}],"description":"Action to be taken during this schedule step"},"allow_deviation":{"type":"boolean","title":"Allow Deviation","description":"Whether the battery is allowed to deviate from the schedule"}},"type":"object","required":["start_timestamp","end_timestamp","action","allow_deviation"],"title":"BatteryScheduleStep"},"Body_create_component_token_auth_component_token_post":{"properties":{"external_user_id":{"type":"string","title":"External User Id","description":"Your ID for this end user; a site is created on demand if unknown"},"allowed_origin":{"type":"string","title":"Allowed Origin","description":"Origin allowed to embed the Axle-hosted flow"},"user_email":{"type":"string","title":"User Email","description":"The email of the user, to be added for new users or upserted for existing users."},"gave_boundary_meter_consent_at":{"type":"string","format":"date-time","title":"Gave Boundary Meter Consent At","description":"Timezone-aware ISO 8601 timestamp (e.g. '2026-01-01T12:34:56Z') indicating when the household gave consent for Axle to access readings from their boundary meter, if consent was given.\n\nUnless explicitly exempted, this must be provided on the first call for a new `external_user_id`. It can optionally be included in later calls for the same `external_user_id`; the value submitted most recently will be kept on record."}},"type":"object","required":["external_user_id","allowed_origin"],"title":"Body_create_component_token_auth_component_token_post"},"Body_login_for_access_token_form_auth_token_form_post":{"properties":{"username":{"type":"string","title":"Username"},"password":{"type":"string","title":"Password"},"grant_type":{"type":"string","pattern":"^password$","title":"Grant Type","default":"password"}},"type":"object","required":["username","password"],"title":"Body_login_for_access_token_form_auth_token_form_post"},"ChargeNowDeletedEventRequest":{"properties":{},"type":"object","title":"ChargeNowDeletedEventRequest","description":"Request model for charge-now-deleted events.\n\nThis is an empty request model to allow for future updates."},"ChargeNowEventRequest":{"properties":{"end_at":{"type":"string","format":"date-time","title":"End At","description":"End time for the charge now request."}},"type":"object","required":["end_at"],"title":"ChargeNowEventRequest","description":"Request model for a user's charge now request."},"ChargingMode":{"type":"string","enum":["maximise_charging_time","minimise_charging_time"],"title":"ChargingMode","description":"An enumeration."},"ChargingProfile":{"properties":{"chargingProfileId":{"type":"integer","title":"Chargingprofileid","description":"Unique identifier for this profile."},"transactionId":{"type":"integer","title":"Transactionid","description":"Only valid if ChargingProfilePurpose is set to TxProfile, the transactionId MAY be used to match the profile to a specific transaction."},"stackLevel":{"type":"integer","title":"Stacklevel","description":"Value determining level in hierarchy stack of profiles. Higher values have precedence over lower values. Lowest level is 0."},"chargingProfilePurpose":{"allOf":[{"$ref":"#/components/schemas/ChargingProfilePurposeType"}],"description":"Defines the purpose of the schedule transferred by this message."},"chargingProfileKind":{"allOf":[{"$ref":"#/components/schemas/ChargingProfileKindType"}],"description":"Indicates the kind of schedule."},"recurrencyKind":{"allOf":[{"$ref":"#/components/schemas/RecurrencyKindType"}],"description":"Indicates the start point of a recurrence."},"validFrom":{"type":"string","format":"date-time","title":"Validfrom","description":"Point in time at which the profile starts to be valid. If absent, the profile is valid as soon as it is received by the Charge Point."},"validTo":{"type":"string","format":"date-time","title":"Validto","description":"Point in time at which the profile stops to be valid. If absent, the profile is valid until it is replaced by another profile."},"chargingSchedule":{"allOf":[{"$ref":"#/components/schemas/ChargingSchedule"}],"title":"Chargingschedule","description":"Contains limits for the available power or current over time."}},"type":"object","required":["chargingProfileId","stackLevel","chargingProfilePurpose","chargingProfileKind","chargingSchedule"],"title":"ChargingProfile","description":"A ChargingProfile consists of a ChargingSchedule, describing the amount of power or current that can be delivered per time interval."},"ChargingProfileKindType":{"type":"string","enum":["Absolute","Recurring","Relative"],"title":"ChargingProfileKindType","description":"Kind of charging profile\n\nAbsolute: Schedule periods are relative to a fixed point in time defined in the schedule.\nRecurring: The schedule restarts periodically at the first schedule period.\nRelative: Schedule periods are relative to a situation-specific start point (such as the start of a Transaction) that is determined by the charge point."},"ChargingProfilePurposeType":{"type":"string","enum":["ChargePointMaxProfile","TxDefaultProfile","TxProfile"],"title":"ChargingProfilePurposeType","description":"Purpose of the charging profile\n\nChargePointMaxProfile: Configuration for the maximum power or current available for an entire Charge Point.\nTxDefaultProfile: Default profile that can be configured in the Charge Point. When a new transaction is started, this profile SHALL be used, unless it was a transaction that was started by a RemoteStartTransaction.req with a ChargeProfile that is accepted by the Charge Point.\nTxProfile: Profile with constraints to be imposed by the Charge Point on the current transaction, or on a new transaction when this is started via a RemoteStartTransaction.req with a ChargeProfile. A profile with this purpose SHALL cease to be valid when the transaction terminates."},"ChargingRateUnitType":{"type":"string","enum":["W","A"],"title":"ChargingRateUnitType","description":"Unit in which a charging schedule is defined\n\nW: Watts (power). This is the TOTAL allowed charging power. It is usually more convenient to use this for DC charging.\nA: Amperes (current). The amount of Ampere per phase, not the sum of all phases. It is usually more convenient to use this for AC charging."},"ChargingSchedule":{"properties":{"duration":{"type":"integer","title":"Duration","description":"Duration of the charging schedule in seconds. If the duration is left empty, the last period will continue indefinitely or until end of the transaction in case startSchedule is absent."},"startSchedule":{"type":"string","format":"date-time","title":"Startschedule","description":"Starting point of an absolute schedule. If absent the schedule will be relative to start of charging."},"chargingRateUnit":{"allOf":[{"$ref":"#/components/schemas/ChargingRateUnitType"}],"description":"The unit of measure Limit is expressed in."},"chargingSchedulePeriod":{"items":{"$ref":"#/components/schemas/ChargingSchedulePeriod"},"type":"array","title":"Chargingscheduleperiod","description":"List of ChargingSchedulePeriod elements defining maximum power or current usage over time. The startSchedule of the first ChargingSchedulePeriod SHALL always be 0."},"minChargingRate":{"type":"number","title":"Minchargingrate","description":"Minimum charging rate supported by the electric vehicle. The unit of measure is defined by the chargingRateUnit. This parameter is intended to be used by a local smart charging algorithm to optimize the power allocation for in the case a charging process is inefficient at lower charging rates. Accepts at most one digit fraction (e.g. 8.1)"}},"type":"object","required":["chargingRateUnit","chargingSchedulePeriod"],"title":"ChargingSchedule","description":"Charging schedule structure defines a list of charging periods"},"ChargingScheduleBlock":{"properties":{"start_timestamp":{"type":"string","title":"Start Timestamp"},"end_timestamp":{"type":"string","title":"End Timestamp"}},"type":"object","required":["start_timestamp","end_timestamp"],"title":"ChargingScheduleBlock","description":"Sync has defined this simple schedule structure which we will use for initial WSLite integration."},"ChargingSchedulePeriod":{"properties":{"startPeriod":{"type":"integer","title":"Startperiod","description":"Start of the period, in seconds from the start of schedule. The value of StartPeriod also defines the stop time of the previous period."},"limit":{"type":"number","title":"Limit","description":"Charging rate limit during the schedule period, in the applicable chargingRateUnit, for example in Amperes or Watts. Accepts at most one digit fraction (e.g. 8.1)."},"numberPhases":{"type":"integer","title":"Numberphases","description":"The number of phases that can be used for charging. If a number of phases is needed, numberPhases=3 will be assumed unless another number is given."}},"type":"object","required":["startPeriod","limit"],"title":"ChargingSchedulePeriod","description":"Charging schedule period structure defines a time period in a charging schedule"},"ComponentToken":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"access_token":{"type":"string","title":"Access Token"},"token_type":{"type":"string","title":"Token Type"}},"type":"object","required":["id","access_token","token_type"],"title":"ComponentToken","description":"Organisation scoped token. Includes internal user ID so clients can make futher\nAPI requests regarding this user if needed."},"CreatableAssetType":{"type":"string","enum":["charger","battery","heat pump","electric_vehicle","hot water tank"],"title":"CreatableAssetType","description":"Asset types that can be created through the API."},"DispatchEvent":{"properties":{"asset_id":{"type":"string","format":"uuid","title":"Asset Id","description":"Asset or aggregate to which this event pertains"},"event_id":{"type":"string","format":"uuid","title":"Event Id","description":"UID of this event"},"issued_timestamp":{"type":"string","format":"date-time","title":"Issued Timestamp","description":"When the event was published (UTC)"},"event_timestamp":{"type":"string","format":"date-time","title":"Event Timestamp","description":"When the event occurred, if different from publication (UTC)"},"market_id":{"type":"string","title":"Market Id","description":"Market from which this dispatch originates"},"level_kw":{"type":"number","title":"Level Kw","description":"Desired power output of asset"},"from_time":{"type":"string","format":"date-time","title":"From Time","description":"Start time of event (UTC)"},"to_time":{"type":"string","format":"date-time","title":"To Time","description":"End time of event (UTC)"},"update_status_callback":{"anyOf":[{"type":"string"},{"type":"string","maxLength":2083,"minLength":1,"format":"uri"}],"title":"Update Status Callback","description":"Callback to change status of event to RECEIVED, ACCEPTED, REJECTED, FAILED, or EXECUTED"}},"type":"object","required":["asset_id","event_id","issued_timestamp","event_timestamp","market_id","level_kw","from_time","to_time","update_status_callback"],"title":"DispatchEvent"},"DispatchMethodResponse":{"type":"string","enum":["cm_infrequent_dispatch","full_asset_schedule_control","limited_pause","price_curve","vpp_limited_control"],"title":"DispatchMethodResponse","description":"Axle propositions that a site can enrol into."},"DispatchScheduleAction":{"type":"string","enum":["CHARGE","DISCHARGE","LOCK","FEED_IN","SELF_USE","PAUSE"],"title":"DispatchScheduleAction","description":"An enumeration."},"EligibilityCheckRequest":{"properties":{"mpan":{"type":"string","title":"Mpan","description":"Meter Point Administration Number. Used to determine whether the site is half-hourly settled.","examples":["1234567890123"]},"asset_model":{"type":"string","title":"Asset Model","description":"Optional value of the AssetModel to evaluate against. Required for CoP11-route eligibility; half-hourly settled sites qualify regardless of asset model.","examples":["axle_charger_v1"]}},"type":"object","required":["mpan"],"title":"EligibilityCheckRequest","description":"Request model for the ephemeral eligibility check endpoint."},"EligibilityCheckResponse":{"properties":{"is_half_hourly_settled":{"type":"boolean","title":"Is Half Hourly Settled","description":"Whether the site is half-hourly settled, per ECOES."},"propositions":{"items":{"$ref":"#/components/schemas/PropositionEligibility"},"type":"array","title":"Propositions","description":"Per-proposition eligibility for the supplied MPAN + asset model combination.","default":[]}},"type":"object","required":["is_half_hourly_settled"],"title":"EligibilityCheckResponse","description":"Response model for the ephemeral eligibility check endpoint."},"EligibilityCode":{"type":"string","enum":["asset_model_not_set","asset_model_not_found","asset_model_not_cop11_qualified","asset_installation_date_not_set","asset_model_enrol_eligibility_override","non_domestic_site","mpan_not_set"],"title":"EligibilityCode","description":"Codes identifying specific eligibility issues for an asset."},"EligibleMarket":{"type":"string","enum":["cm","dno","wholesale"],"title":"EligibleMarket","description":"An enumeration."},"EnrolRequest":{"properties":{"proposition":{"type":"string","enum":["limited_pause","full_asset_schedule_control","price_curve"],"title":"Proposition","description":"Proposition to enrol for"},"override_withdrawal":{"type":"boolean","title":"Override Withdrawal","description":"Set to true to re-enrol regardless of previous withdrawals. If this is a user-initated action, overriding previous withdrawals is recommended.","default":false,"examples":[false]},"gave_boundary_meter_consent_at":{"type":"string","format":"date-time","title":"Gave Boundary Meter Consent At","description":"Optional timezone-aware ISO 8601 timestamp recording when the household gave boundary meter consent. If provided, overwrites any existing meter consent timestamp on the site."}},"type":"object","required":["proposition"],"title":"EnrolRequest","description":"Request model for enrolling a site in a proposition."},"EnrolResponse":{"properties":{"site_id":{"type":"string","format":"uuid","title":"Site Id","description":"ID of the enrolled site","examples":["a1b2c3d4-e5f6-7890-abcd-ef1234567890"]},"status":{"type":"string","enum":["enrolled","already_enrolled"],"title":"Status","description":"Outcome of the enrolment attempt. Both `enrolled` and `already_enrolled` indicate success.","examples":["enrolled"]}},"type":"object","required":["site_id","status"],"title":"EnrolResponse","description":"Outcome of an enrolment attempt."},"ErrorWithDetail":{"properties":{"detail":{"type":"string","title":"Detail"}},"type":"object","required":["detail"],"title":"ErrorWithDetail","description":"Standard error response with a detailed message."},"EventResponse":{"properties":{"timestamp":{"type":"string","format":"date-time","title":"Timestamp","description":"Timestamp for the response (UTC)"},"status":{"$ref":"#/components/schemas/EventStatus"}},"type":"object","required":["timestamp","status"],"title":"EventResponse","description":"Response for an asset event status update."},"EventStatus":{"type":"string","enum":["RECEIVED","ACCEPTED","REJECTED","FAILED","EXECUTED"],"title":"EventStatus","description":"Status values for asset event handling.\n\n- RECEIVED: Event was received by the system\n- ACCEPTED: Event was accepted for processing\n- REJECTED: Event was rejected (invalid or not applicable)\n- FAILED: Event processing failed\n- EXECUTED: Event was successfully executed"},"FlexEventResponse":{"properties":{"start_at":{"type":"string","format":"date-time","title":"Start At","description":"UTC start time of the flex event"},"end_at":{"type":"string","format":"date-time","title":"End At","description":"UTC end time of the flex event"},"estimated_gross_revenue_gbp":{"type":"number","title":"Estimated Gross Revenue Gbp","description":"Estimated gross revenue earned in GBP for the event, before data has been submitted and reviewed by the relevant market bodies. Gross earnings are total flex earnings before any Axle and end-user revenue sharing deductions."},"final_gross_revenue_gbp":{"type":"number","title":"Final Gross Revenue Gbp","description":"Final gross revenue earned in GBP for the event. This will be completed before the final settlement run of the event month (in UK Time), which runs at the end of the following month. Gross earnings are total flex earnings before any Axle and end-user revenue sharing deductions."}},"type":"object","required":["start_at","end_at","estimated_gross_revenue_gbp"],"title":"FlexEventResponse"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HalfHourlyPrice":{"properties":{"start_timestamp":{"type":"string","format":"date-time","title":"Start Timestamp"},"price_gbp_per_mwh":{"type":"number","title":"Price Gbp Per Mwh","description":"Price in £/MWh (2dp)"}},"type":"object","required":["start_timestamp","price_gbp_per_mwh"],"title":"HalfHourlyPrice","description":"Represents the market price for a given half-hour period.\n\nIf the asset is not participating in the market for that period, price_gbp_per_mwh will be None."},"InitialiseAssetResult":{"properties":{"asset_id":{"type":"string","format":"uuid","title":"Asset Id","description":"Axle's internal UUID for the asset"},"external_id":{"type":"string","title":"External Id","description":"Vendor-specific identifier for the asset"},"asset_created":{"type":"boolean","title":"Asset Created","description":"True if the asset was newly created, False if it was upserted"},"fields_updated":{"items":{"type":"string"},"type":"array","title":"Fields Updated","description":"List of fields that were updated on upsert"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings","description":"Per-asset warnings generated during initialisation"}},"type":"object","required":["asset_id","external_id","asset_created"],"title":"InitialiseAssetResult","description":"Result metadata for a single asset after upsert."},"InitialiseRequest":{"properties":{"site":{"allOf":[{"$ref":"#/components/schemas/SiteRequest"}],"title":"Site","description":"Site information","examples":[{"mpan":"1234567890123","postcode":"SW1A 1AA","street_address":"10 Downing Street","email":"resident@example.com","gave_boundary_meter_consent_at":"2026-01-15T10:30:00Z"}]},"assets":{"items":{"$ref":"#/components/schemas/OnboardingAssetRequest"},"type":"array","title":"Assets","description":"One or more assets to register at the site","examples":[[{"external_id":"charger-001","type":"charger","asset_model":"zappi","installation_date":"2025-06-15","properties":{"power_kw":7.4}}]]}},"type":"object","required":["site","assets"],"title":"InitialiseRequest","description":"Request model for initialising a site with one or more assets.\n\nUpserts the site and assets, returning eligibility information.\nNo enrollment side effects (no dispatch consent, no bonus, no email)."},"InitialiseResponse":{"properties":{"site":{"allOf":[{"$ref":"#/components/schemas/InitialiseSiteResult"}],"title":"Site","description":"Site result metadata"},"assets":{"items":{"$ref":"#/components/schemas/InitialiseAssetResult"},"type":"array","title":"Assets","description":"Per-asset result metadata"},"eligibility":{"allOf":[{"$ref":"#/components/schemas/SiteEligibilityDetail"}],"title":"Eligibility","description":"Eligibility information for the site and its assets"}},"type":"object","required":["site","assets","eligibility"],"title":"InitialiseResponse","description":"Response model for the initialise endpoint."},"InitialiseSiteResult":{"properties":{"site_id":{"type":"string","format":"uuid","title":"Site Id","description":"Axle's internal UUID for the site"},"site_created":{"type":"boolean","title":"Site Created","description":"True if the site was newly created, False if it was upserted"},"fields_updated":{"items":{"type":"string"},"type":"array","title":"Fields Updated","description":"List of site fields that were updated on upsert"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings","description":"Site-level warnings generated during initialisation"}},"type":"object","required":["site_id","site_created"],"title":"InitialiseSiteResult","description":"Result metadata for a site after upsert."},"Intent":{"properties":{"energy_required_kwh":{"type":"number","title":"Energy Required Kwh"},"ready_by":{"type":"string","format":"date-time","title":"Ready By","description":"Deprecated: use ready_by_local_time instead. The date component is discarded; only used to derive local time when ready_by_local_time is absent."},"ready_by_local_time":{"type":"string","format":"time","title":"Ready By Local Time","description":"Local time by which energy is required (wall time)"},"energy_estimated":{"type":"boolean","title":"Energy Estimated","description":"False if energy_required_kwh is derived from target %SOC set on vehicle (e.g. via Enode), True if the energy_required_kwh is purely a user input"},"may_charge_peak":{"type":"boolean","title":"May Charge Peak","description":"If True, the vehicle may be charged in peak periods but only if all off-peak periods are used up and the energy requirement is not met.","default":false},"charging_mode":{"allOf":[{"$ref":"#/components/schemas/ChargingMode"}],"description":"Charging strategy: maximise_charging_time (charge all available periods) or minimise_charging_time (charge only up to the user's stated intent in kWh)","default":"maximise_charging_time"}},"type":"object","required":["energy_required_kwh","ready_by"],"title":"Intent","description":"This is the received intent from a user"},"IntentEventRequest":{"properties":{"intent":{"allOf":[{"$ref":"#/components/schemas/Intent"}],"title":"Intent","description":"Intent to charge the vehicle."}},"type":"object","required":["intent"],"title":"IntentEventRequest","description":"This event should be triggered when the end user updates their charging preferences."},"IntentResponse":{"properties":{"intent":{"$ref":"#/components/schemas/Intent"},"received_at":{"type":"string","format":"date-time","title":"Received At"}},"type":"object","required":["intent","received_at"],"title":"IntentResponse","description":"An intent and the time it was received."},"MPANValidationError":{"properties":{"detail":{"items":{"type":"string"},"type":"array","title":"Detail","description":"Errors when trying to validate the MPAN"}},"type":"object","required":["detail"],"title":"MPANValidationError","description":"Error(s) when trying to validate an MPAN"},"MPANValidationRequest":{"properties":{"mpan":{"type":"string","title":"Mpan","description":"MPAN to be validated"}},"type":"object","required":["mpan"],"title":"MPANValidationRequest","description":"Request model for validating an MPAN"},"MPANValidationResponse":{"properties":{"isValid":{"type":"boolean","title":"Isvalid","description":"If the provided MPAN is valid and supported by Axle"}},"type":"object","required":["isValid"],"title":"MPANValidationResponse","description":"Response for a correctly validated MPAN"},"MarketResponse":{"type":"string","enum":["cm","dfs","dno","lcm","sffr","wholesale"],"title":"MarketResponse","description":"Market types available for participation.\n\n- CM: Capacity Market\n- DFS: Dynamic Frequency Service\n- DNO: Distribution Network Operator flexibility services\n- LCM: Local Capacity Market\n- SFFR: Static Firm Frequency Response\n- WHOLESALE: Wholesale energy market"},"MeterByAddressRequest":{"properties":{"address":{"type":"string","title":"Address","description":"Full address of the meter, e.g. '221B Baker Street, London, NW1 6XE'. Must include postcode and begin with house number/ name or other uniquely-identifying information. May be constructed from individual address components, concatenated with separating commas. Better formatting may increase the chance of a meter being found."}},"type":"object","required":["address"],"title":"MeterByAddressRequest"},"MeterByMPANRequest":{"properties":{"mpan":{"type":"string","title":"Mpan","description":"13-digit Meter Point Administration Number (MPAN) whose meter info is requested"}},"type":"object","required":["mpan"],"title":"MeterByMPANRequest"},"MeterResponse":{"properties":{"mpan":{"type":"string","title":"Mpan","description":"Meter Point Administration Number"},"half_hourly_settled":{"type":"boolean","title":"Half Hourly Settled","description":"Whether the meter is half-hourly settled"},"supplier_mpid":{"type":"string","title":"Supplier Mpid","description":"Market Participant ID of the supplier"},"supplier_name":{"type":"string","title":"Supplier Name","description":"Name of the electricity supplier"},"eligible_markets":{"items":{"$ref":"#/components/schemas/EligibleMarket"},"type":"array","uniqueItems":true,"description":"Markets in which the meter is eligible to participate"}},"type":"object","required":["mpan","eligible_markets"],"title":"MeterResponse","description":"Response model for meter information.\n\nContains details about a meter including its MPAN, settlement status, and supplier information."},"MeterSearchResponse":{"properties":{"ref":{"type":"string","title":"Ref","description":"Encrypted reference to the meter that can be used in subsequent API calls"},"address":{"type":"string","title":"Address","description":"Full address where the meter is registered"}},"type":"object","required":["ref","address"],"title":"MeterSearchResponse","description":"Response model for meter search results.\n\nContains a reference to the meter and its associated address."},"OAuthInitiateResponse":{"properties":{"authorization_url":{"type":"string","title":"Authorization Url","description":"Third party URL to redirect the user to for OAuth authorisation"}},"type":"object","required":["authorization_url"],"title":"OAuthInitiateResponse","description":"Response for initiating OAuth flow with a third party service (e.g. FoxESS)"},"OAuthProvider":{"type":"string","enum":["foxess","solaredge","solax","huawei","myenergi","nexblue","givenergy","volvo","deye","ideal","alpha"],"title":"OAuthProvider","description":"OAuth 2 providers supported for asset connections."},"OnboardRequest":{"properties":{"site":{"allOf":[{"$ref":"#/components/schemas/SiteRequest"}],"title":"Site","description":"Site information","examples":[{"mpan":"1234567890123","postcode":"SW1A 1AA","street_address":"10 Downing Street","email":"resident@example.com","gave_boundary_meter_consent_at":"2026-01-15T10:30:00Z"}]},"assets":{"items":{"$ref":"#/components/schemas/OnboardingAssetRequest"},"type":"array","title":"Assets","description":"One or more assets to register at the site","examples":[[{"external_id":"charger-001","type":"charger","asset_model":"zappi","installation_date":"2025-06-15","properties":{"power_kw":7.4}}]]},"proposition":{"type":"string","enum":["limited_pause","full_asset_schedule_control","price_curve"],"title":"Proposition","description":"Proposition to enrol the site in"},"override_withdrawal":{"type":"boolean","title":"Override Withdrawal","description":"Set to true to re-enrol regardless of previous withdrawals.","default":false,"examples":[false]}},"type":"object","required":["site","assets","proposition"],"title":"OnboardRequest","description":"Request model for the onboard endpoint."},"OnboardResponse":{"properties":{"site":{"allOf":[{"$ref":"#/components/schemas/InitialiseSiteResult"}],"title":"Site","description":"Site result metadata"},"assets":{"items":{"$ref":"#/components/schemas/InitialiseAssetResult"},"type":"array","title":"Assets","description":"Per-asset result metadata"},"enrolment":{"allOf":[{"$ref":"#/components/schemas/EnrolResponse"}],"title":"Enrolment","description":"Enrolment result"}},"type":"object","required":["site","assets","enrolment"],"title":"OnboardResponse","description":"Response model for the onboard endpoint."},"OnboardingAssetRequest":{"properties":{"external_id":{"type":"string","title":"External Id","description":"Vendor-specific identifier for the asset","examples":["charger-001"]},"type":{"allOf":[{"$ref":"#/components/schemas/CreatableAssetType"}],"description":"Type of asset being created","examples":["charger"]},"properties":{"allOf":[{"$ref":"#/components/schemas/AssetProperties"}],"title":"Properties","description":"Optional asset properties","examples":[{"power_kw":7.4}]},"asset_model":{"type":"string","title":"Asset Model","description":"Name of the AssetModel to assign (looked up by name). Required for CoP11 eligibility.","examples":["axle_charger_v1"]},"installation_date":{"type":"string","format":"date","title":"Installation Date","description":"Date when the asset was installed. Required alongside asset_model for CoP11 eligibility.","examples":["2025-06-15"]}},"type":"object","required":["external_id","type"],"title":"OnboardingAssetRequest","description":"Request model for creating an asset during onboarding (without site_id)."},"OnboardingRequest":{"properties":{"site":{"allOf":[{"$ref":"#/components/schemas/SiteRequest"}],"title":"Site","description":"Site information","examples":[{"mpan":"1234567890123","postcode":"SW1A 1AA","street_address":"10 Downing Street","gave_boundary_meter_consent_at":"2025-01-01T12:00:00Z","email":"test@example.com"}]},"asset":{"allOf":[{"$ref":"#/components/schemas/OnboardingAssetRequest"}],"title":"Asset","description":"Asset information","examples":[{"external_id":"charger-001","type":"charger","properties":{"power_kw":7.4}}]},"dispatch_consent":{"allOf":[{"$ref":"#/components/schemas/SiteDispatchConsentRequest"}],"title":"Dispatch Consent","description":"Dispatch consent methods","examples":[{"dispatch_methods":["limited_pause"]}]}},"type":"object","required":["site","asset","dispatch_consent"],"title":"OnboardingRequest","description":"Request model for onboarding a site with an asset and dispatch consent in a single call."},"OnboardingResponse":{"properties":{"site":{"allOf":[{"$ref":"#/components/schemas/SiteResponse"}],"title":"Site","description":"Created site details"},"asset":{"allOf":[{"$ref":"#/components/schemas/AssetResponse"}],"title":"Asset","description":"Created asset details"}},"type":"object","required":["site","asset"],"title":"OnboardingResponse","description":"Response model for onboarding operation."},"PaymentStatus":{"type":"string","enum":["pending_approval","approved","processing","posted","failed","rejected","cancelled","returned"],"title":"PaymentStatus","description":"Payment lifecycle states"},"PlainDispatchSchedulePeriodResponse":{"properties":{"start_timestamp":{"type":"string","format":"date-time","title":"Start Timestamp"},"end_timestamp":{"type":"string","format":"date-time","title":"End Timestamp"},"action":{"$ref":"#/components/schemas/DispatchScheduleAction"}},"type":"object","required":["start_timestamp","end_timestamp","action"],"title":"PlainDispatchSchedulePeriodResponse","description":"One period of the battery's day plan: a plan action over a time window."},"PlainDispatchScheduleResponse":{"properties":{"periods":{"items":{"$ref":"#/components/schemas/PlainDispatchSchedulePeriodResponse"},"type":"array","title":"Periods"}},"type":"object","required":["periods"],"title":"PlainDispatchScheduleResponse","description":"A battery's dispatch plan for today: an ordered list of periods, each with a plan action and\ntime window. `periods` is empty when no plan is available for today."},"PlugInEventRequest":{"properties":{"intent":{"allOf":[{"$ref":"#/components/schemas/Intent"}],"title":"Intent","description":"Intent to charge the vehicle."},"vehicle":{"allOf":[{"$ref":"#/components/schemas/Vehicle"}],"title":"Vehicle","description":"Vehicle information."},"tariff":{"allOf":[{"$ref":"#/components/schemas/Tariff"}],"title":"Tariff","description":"Tariff information."}},"type":"object","title":"PlugInEventRequest","description":"A minimal plug-in event requires no data.\nOptionally `intent`, `tariff` and `vehicle` information can be supplied here too."},"PlugInScheduleEventRequest":{"properties":{"charging_schedule":{"items":{"$ref":"#/components/schemas/ChargingScheduleBlock"},"type":"array","title":"Charging Schedule"}},"type":"object","required":["charging_schedule"],"title":"PlugInScheduleEventRequest","description":"This is the original charging schedule which will be modified and returned to the client in the response.\nUsed in WSLite integration model."},"PlugInScheduleEventResponse":{"properties":{"modified_charging_schedule":{"items":{"$ref":"#/components/schemas/ChargingScheduleBlock"},"type":"array","title":"Modified Charging Schedule"}},"type":"object","required":["modified_charging_schedule"],"title":"PlugInScheduleEventResponse","description":"This is the modified charging schedule which will be returned to the client.\nUsed in WSLite integration model."},"PlugOutEventRequest":{"properties":{},"type":"object","title":"PlugOutEventRequest","description":"Request model for plug-out events.\n\nThis is an empty request model to allow for future updates."},"PriceCurveResponse":{"properties":{"half_hourly_traded_prices":{"items":{"$ref":"#/components/schemas/HalfHourlyPrice"},"type":"array","title":"Half Hourly Traded Prices"}},"type":"object","required":["half_hourly_traded_prices"],"title":"PriceCurveResponse","description":"Response model for getting the price curve for a dispatchable asset (battery / charger)."},"PropositionEligibility":{"properties":{"proposition":{"type":"string","enum":["limited_pause","full_asset_schedule_control","price_curve"],"title":"Proposition","examples":["limited_pause"]},"is_eligible":{"type":"boolean","title":"Is Eligible"},"issues":{"items":{"$ref":"#/components/schemas/EligibilityCode"},"type":"array","default":[]}},"type":"object","required":["proposition","is_eligible"],"title":"PropositionEligibility","description":"Eligibility detail for a single proposition."},"PropositionRequest":{"type":"string","enum":["mileage_subscription","supplier_ev_tariff"],"title":"PropositionRequest","description":"Commercial propositions a site can be enrolled in (org-scoped; see `PropositionConfig`).\n\nDeliberately separate from `DispatchMethodResponse`: propositions are single-choice and\nmutually exclusive per site, unlike dispatch consents which are set-based."},"ReadingDataPoint":{"properties":{"asset_id":{"type":"string","format":"uuid","title":"Asset Id","description":"ID of the asset"},"start_timestamp":{"type":"string","format":"date-time","title":"Start Timestamp","description":"Start time of the reading"},"end_timestamp":{"type":"string","format":"date-time","title":"End Timestamp","description":"End time of the reading"},"value":{"type":"number","title":"Value","description":"Value of the reading"},"label":{"allOf":[{"$ref":"#/components/schemas/ReadingDataPointLabel"}],"description":"Label for the reading"}},"type":"object","required":["asset_id","start_timestamp","end_timestamp","value","label"],"title":"ReadingDataPoint","description":"Reading data for a single asset."},"ReadingDataPointLabel":{"type":"string","enum":["boundary_import_kw","battery_inverter_import_kw","charger_consumption_energy_kwh","charger_lifetime_consumption_energy_kwh","boundary_lifetime_import_energy_kwh","boundary_lifetime_export_energy_kwh","boundary_import_energy_kwh","boundary_export_energy_kwh","provisional_consumption_kwh","solar_power_kw","battery_state_of_charge_pct","battery_stored_energy_kwh"],"title":"ReadingDataPointLabel","description":"The type of reading being submitted.\n\n- boundary_import_kw: Instantaneous power import from the grid in kW. Positive indicates power imported from the grid, negative indicates power exported to the grid.\n- battery_inverter_import_kw: Instantaneous inverter power into the battery in kW. Positive indicates power into the battery (charging), negative indicates power out of the battery (discharging).\n- charger_consumption_energy_kwh: Total energy consumed by the charger in kWh in a 30min interval. Must be >= 0.\n- charger_lifetime_consumption_energy_kwh: Total energy consumed by the charger in kWh in its lifetime. Must be >= 0.\n- boundary_lifetime_import_energy_kwh: Cumulative lifetime energy imported across the site boundary in kWh. A monotonic non-decreasing register; must be >= 0.\n- boundary_lifetime_export_energy_kwh: Cumulative lifetime energy exported across the site boundary in kWh. A monotonic non-decreasing register; must be >= 0.\n- boundary_import_energy_kwh: Energy imported across the site boundary in kWh over a half-hourly interval. Must be >= 0.\n- boundary_export_energy_kwh: Energy exported across the site boundary in kWh over a half-hourly interval. Must be >= 0.\n- provisional_consumption_kwh: Provisional consumption data in kWh. Must be >= 0.\n- solar_power_kw: Instantaneous solar generation in kW. Must be >= 0.\n- battery_state_of_charge_pct: Instantaneous state of charge of the battery in percentage. Must be between 0 and 100 (inclusive).\n- battery_stored_energy_kwh: Stored energy in the battery in kWh. Must be >= 0."},"ReadingResponse":{"properties":{"asset_id":{"type":"string","format":"uuid","title":"Asset Id","description":"ID of the asset"},"start_timestamp":{"type":"string","format":"date-time","title":"Start Timestamp","description":"Start time of the reading"},"end_timestamp":{"type":"string","format":"date-time","title":"End Timestamp","description":"End time of the reading"},"label":{"allOf":[{"$ref":"#/components/schemas/ReadingDataPointLabel"}],"description":"Label for the reading"},"accepted":{"type":"boolean","title":"Accepted","description":"Whether the reading was accepted"},"error":{"type":"string","title":"Error","description":"Error message if the reading was rejected"}},"type":"object","required":["asset_id","start_timestamp","end_timestamp","label","accepted"],"title":"ReadingResponse","description":"Response model for a single reading submission."},"ReadingsDataPoints":{"properties":{"readings":{"items":{"$ref":"#/components/schemas/ReadingDataPoint"},"type":"array","title":"Readings","description":"List of readings to be submitted"}},"type":"object","required":["readings"],"title":"ReadingsDataPoints","description":"Readings data for multiple assets."},"ReadingsResponse":{"properties":{"responses":{"items":{"$ref":"#/components/schemas/ReadingResponse"},"type":"array","title":"Responses","description":"List of responses for each reading submission"}},"type":"object","required":["responses"],"title":"ReadingsResponse","description":"Response model for a batch of readings submissions."},"RecurrencyKindType":{"type":"string","enum":["Daily","Weekly"],"title":"RecurrencyKindType","description":"Type of recurrence of a charging profile\n\nDaily: The schedule restarts every 24 hours, at the same time as in the startSchedule.\nWeekly: The schedule restarts every 7 days, at the same time and day-of-the-week as in the startSchedule."},"SetChargingProfileRequest":{"properties":{"connectorId":{"type":"integer","title":"Connectorid","description":"The connector to which the charging profile applies. If connectorId = 0, the message contains an overall limit for the Charge Point."},"csChargingProfiles":{"allOf":[{"$ref":"#/components/schemas/ChargingProfile"}],"title":"Cschargingprofiles","description":"The charging profile to be set at the Charge Point."}},"type":"object","required":["connectorId","csChargingProfiles"],"title":"SetChargingProfileRequest","description":"A SetChargingProfileRequest object, as defined in section 6.43 of the OCPP 1.6 documentation at https://openchargealliance.org/protocols/open-charge-point-protocol/#OCPP1.6\n\nThis is used by the central system to send charging profiles to an EV charger."},"SiteAuthTokenRequest":{"properties":{"refresh_token":{"type":"string","title":"Refresh Token","description":"Refresh token for acquiring fresh access tokens after they expire; required, except for 'API_KEY'-type submissions"},"access_token":{"type":"string","title":"Access Token","description":"Access token for dispatching and monitoring assets"},"token_type":{"type":"string","title":"Token Type","description":"Type of token (e.g. 'Bearer' or 'API_KEY')"},"expires_utc":{"type":"string","format":"date-time","title":"Expires Utc","description":"Time in UTC at which the token expires"},"expires_in":{"type":"integer","title":"Expires In","description":"Time in seconds until the token expires"}},"type":"object","title":"SiteAuthTokenRequest","description":"Request model for providing an auth token to enable Axle to access assets at a site."},"SiteDispatchConsentRequest":{"properties":{"dispatch_methods":{"items":{"$ref":"#/components/schemas/DispatchMethodResponse"},"type":"array","uniqueItems":true,"description":"Dispatch methods to consent to or remove consent from. Leave empty to not consent to any dispatch methods."}},"type":"object","required":["dispatch_methods"],"title":"SiteDispatchConsentRequest","description":"Request model for updating dispatch consent for a site."},"SiteEligibilityDetail":{"properties":{"eligible_propositions":{"items":{"type":"string","enum":["limited_pause","full_asset_schedule_control","price_curve"]},"type":"array","title":"Eligible Propositions","default":[]},"site_id":{"type":"string","format":"uuid","title":"Site Id","examples":["a1b2c3d4-e5f6-7890-abcd-ef1234567890"]},"site_properties":{"allOf":[{"$ref":"#/components/schemas/SiteProperties"}],"title":"Site Properties","examples":[{"is_half_hourly_settled":false,"has_meter_consent":true}]},"assets":{"items":{"$ref":"#/components/schemas/AssetEligibilityDetail"},"type":"array","title":"Assets","default":[]}},"type":"object","required":["site_id","site_properties"],"title":"SiteEligibilityDetail","description":"Eligibility detail for a site's proposition eligibility check."},"SiteFlexEventsResponse":{"properties":{"site_id":{"type":"string","format":"uuid","title":"Site Id","description":"ID of the site"},"events":{"items":{"$ref":"#/components/schemas/FlexEventResponse"},"type":"array","title":"Events","description":"List of flex events the site participated in"}},"type":"object","required":["site_id","events"],"title":"SiteFlexEventsResponse"},"SiteMeterConsentRequest":{"properties":{"gave_boundary_meter_consent_at":{"type":"string","format":"date-time","title":"Gave Boundary Meter Consent At","description":"Timezone-aware ISO 8601 timestamp (e.g. '2026-01-01T12:34:56Z') indicating when the household gave consent for Axle to access readings from their boundary meter, if consent was given."}},"type":"object","required":["gave_boundary_meter_consent_at"],"title":"SiteMeterConsentRequest","description":"Request model for adding boundary meter consent for a site."},"SiteProperties":{"properties":{"is_half_hourly_settled":{"type":"boolean","title":"Is Half Hourly Settled"},"has_meter_consent":{"type":"boolean","title":"Has Meter Consent"}},"type":"object","required":["is_half_hourly_settled","has_meter_consent"],"title":"SiteProperties","description":"Site-level properties relevant to eligibility evaluation."},"SiteRequest":{"properties":{"mpan":{"type":"string","title":"Mpan","description":"Meter Point Administration Number"},"postcode":{"type":"string","title":"Postcode","description":"UK postcode for the site"},"street_address":{"type":"string","title":"Street Address","description":"Street address for the site"},"email":{"type":"string","title":"Email","description":"Email address for the site. Include to enable 2FA for payment withdrawals."},"gave_boundary_meter_consent_at":{"type":"string","format":"date-time","title":"Gave Boundary Meter Consent At","description":"Timezone-aware ISO 8601 timestamp (e.g. '2026-01-01T12:34:56Z') indicating when the household gave consent for Axle to access readings from their boundary meter, if consent was given."}},"type":"object","required":["mpan","postcode"],"title":"SiteRequest","description":"Request model for creating a new site."},"SiteResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id","description":"Axle's internal UUID for the site"},"mpan":{"type":"string","title":"Mpan","description":"Meter Point Administration Number for the site"},"postcode":{"type":"string","title":"Postcode","description":"UK postcode for the site"},"address":{"type":"string","title":"Address","description":"Full address for the site"},"asset_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Asset Ids","description":"List of asset IDs associated with this site","default":[]},"markets":{"items":{"$ref":"#/components/schemas/MarketResponse"},"type":"array","uniqueItems":true,"description":"Markets the site is participating in"},"dispatch_methods":{"items":{"$ref":"#/components/schemas/DispatchMethodResponse"},"type":"array","uniqueItems":true,"description":"Dispatch methods allowed for the site"},"tariff":{"allOf":[{"$ref":"#/components/schemas/TariffResponse"}],"title":"Tariff","description":"Tariff information for the site"},"gave_boundary_meter_consent_at":{"type":"string","format":"date-time","title":"Gave Boundary Meter Consent At","description":"Timestamp when boundary meter consent was given"}},"type":"object","required":["id"],"title":"SiteResponse","description":"Response model for site information."},"SiteResponsePage":{"properties":{"sites":{"items":{"$ref":"#/components/schemas/SiteResponse"},"type":"array","title":"Sites","description":"List of sites for the current page"},"total_num_sites":{"type":"integer","title":"Total Num Sites","description":"Total number of sites available"},"total_num_pages":{"type":"integer","title":"Total Num Pages","description":"Total number of pages available"},"page_number":{"type":"integer","title":"Page Number","description":"Current page number (1-based)"}},"type":"object","required":["sites","total_num_sites","total_num_pages","page_number"],"title":"SiteResponsePage","description":"Paginated response for site listings."},"SiteUpdateRequest":{"properties":{"tariff":{"anyOf":[{"$ref":"#/components/schemas/TariffWithRates"},{"$ref":"#/components/schemas/TariffRequest"}],"title":"Tariff","description":"Tariff to set for the site: a full tariff (rates + periods) or window-only (off-peak times + type). Full tariffs are persisted and pushed to the scheduler."},"address":{"type":"string","title":"Address","description":"Full address for the site"},"postcode":{"type":"string","title":"Postcode","description":"UK postcode for the site"},"mpan":{"type":"string","title":"Mpan","description":"Meter Point Administration Number"},"email":{"type":"string","title":"Email","description":"Email address for the site"},"proposition":{"allOf":[{"$ref":"#/components/schemas/PropositionRequest"}],"description":"Commercial proposition to enrol this site in. Set once per site; enrolling in a different proposition requires unenrolling from the current one first (POST /entities/site/{site_id}/unenrol)."}},"type":"object","title":"SiteUpdateRequest","description":"Request model for updating site information."},"SupplierName":{"type":"string","enum":["AIRA","British Gas","Ecotricity","EDF Energy","E.ON Next","Fuse Energy","Good Energy","Octopus Energy","Other","OVO Energy","Scottish Power","So Energy","Utility Warehouse"],"title":"SupplierName","description":"An enumeration."},"Tariff":{"properties":{"off_peak_times":{"type":"string","title":"Off Peak Times"},"timezone":{"type":"string","title":"Timezone"},"tariff_type":{"$ref":"#/components/schemas/TariffType"}},"type":"object","required":["off_peak_times","timezone"],"title":"Tariff"},"TariffKind":{"type":"string","enum":["published","custom"],"title":"TariffKind","description":"The kind of tariff, i.e. whether it's a standard tariff published by the\nsupplier, or a custom tariff entered by the end user"},"TariffPeriod":{"properties":{"start_time":{"type":"string","format":"time","title":"Start Time"},"end_time":{"type":"string","format":"time","title":"End Time"},"rate_name":{"type":"string","title":"Rate Name"}},"type":"object","required":["start_time","end_time","rate_name"],"title":"TariffPeriod"},"TariffRequest":{"properties":{"tariff_cheap_start_time":{"type":"string","format":"time","title":"Tariff Cheap Start Time","description":"Start time for off-peak/cheap rate period"},"tariff_cheap_end_time":{"type":"string","format":"time","title":"Tariff Cheap End Time","description":"End time for off-peak/cheap rate period"},"tariff_type":{"allOf":[{"$ref":"#/components/schemas/TariffType"}],"description":"Type of tariff"}},"type":"object","required":["tariff_type"],"title":"TariffRequest","description":"Request model for updating tariff information."},"TariffResponse":{"properties":{"tariff_type":{"allOf":[{"$ref":"#/components/schemas/TariffType"}],"description":"Type of tariff"},"tariff_cheap_start_time":{"type":"string","format":"time","title":"Tariff Cheap Start Time","description":"Start time for off-peak/cheap rate period"},"tariff_cheap_end_time":{"type":"string","format":"time","title":"Tariff Cheap End Time","description":"End time for off-peak/cheap rate period"}},"type":"object","title":"TariffResponse","description":"Response model for tariff information."},"TariffType":{"type":"string","enum":["single_rate","dual_rate","dynamic","smart","unknown"],"title":"TariffType","description":"An enumeration."},"TariffUpdateEventRequest":{"properties":{"tariff":{"allOf":[{"$ref":"#/components/schemas/Tariff"}],"title":"Tariff","description":"Updated tariff information."}},"type":"object","required":["tariff"],"title":"TariffUpdateEventRequest","description":"Request model for a user's tariff update."},"TariffWithRates":{"properties":{"kind":{"$ref":"#/components/schemas/TariffKind"},"supplier":{"$ref":"#/components/schemas/SupplierName"},"name":{"type":"string","title":"Name"},"is_import":{"type":"boolean","title":"Is Import","default":true},"available_from":{"type":"string","format":"date","title":"Available From"},"available_until":{"type":"string","format":"date","title":"Available Until"},"periods":{"items":{"$ref":"#/components/schemas/TariffPeriod"},"type":"array","title":"Periods"},"rate_prices":{"additionalProperties":{"type":"number"},"type":"object","title":"Rate Prices"},"standing_charge_pence_per_day":{"type":"number","title":"Standing Charge Pence Per Day"},"timezone":{"$ref":"#/components/schemas/TzName"},"tariff_type":{"$ref":"#/components/schemas/TariffType"}},"type":"object","required":["kind","periods","rate_prices","timezone"],"title":"TariffWithRates"},"Token":{"properties":{"access_token":{"type":"string","title":"Access Token"},"token_type":{"type":"string","title":"Token Type"}},"type":"object","required":["access_token","token_type"],"title":"Token","description":"Organisation scoped token."},"TransactionDataResponse":{"properties":{"site_id":{"type":"string","format":"uuid","title":"Site Id","description":"ID of the site"},"transactions":{"items":{"$ref":"#/components/schemas/TransactionDatumResponse"},"type":"array","title":"Transactions","description":"List of transactions for the site"},"is_below_withdrawal_minimum":{"type":"boolean","title":"Is Below Withdrawal Minimum","description":"If the user is below the minimum withdrawal threshold (if configured)","default":false},"days_until_minimum_wait_time_met":{"type":"integer","title":"Days Until Minimum Wait Time Met","description":"How many days the user needs to wait to withdraw (if configured)"}},"type":"object","required":["site_id","transactions"],"title":"TransactionDataResponse","description":"Response model for transaction history."},"TransactionDatumResponse":{"properties":{"transaction_type":{"allOf":[{"$ref":"#/components/schemas/UserTransactionType"}],"description":"Type of the transaction"},"transaction_id":{"type":"string","format":"uuid","title":"Transaction Id","description":"ID of the transaction"},"start_time":{"type":"string","format":"date-time","title":"Start Time","description":"For transaction_type = 'flex event': when the event started\nFor transaction_type = 'flex period': month start\nFor transaction_type = 'withdrawal': when the withdrawal happened"},"end_time":{"type":"string","format":"date-time","title":"End Time","description":"For transaction_type = 'flex event': when the event ended\nFor transaction_type = 'flex period': month end\nNot present for other transaction_type values"},"settlement_date":{"type":"string","format":"date","title":"Settlement Date","description":"Date on which the transaction was settled, if known. For flex periods this is the payout date — the period start for in-advance payments and the period end for arrears payments. Clients should prefer this over start_time/end_time when displaying a single date for the transaction."},"flex_kwh":{"type":"number","title":"Flex Kwh","description":"Stored to the nearest watt-hour (3dp)\nFor transaction_type = 'flex event': the change in energy flow during\nthe event relative to the baseline in kwh. +ve indicates additional energy\nimported (or less energy exported). -ve indicates additional energy\nexported (or less energy imported).\nNot present for other transaction_type values"},"credit_pence":{"type":"integer","title":"Credit Pence","description":"Amount credited in pence"},"payment_status":{"allOf":[{"$ref":"#/components/schemas/PaymentStatus"}],"description":"Payment lifecycle status. Only present for withdrawal transactions that have an associated payment record."}},"type":"object","required":["transaction_id","credit_pence"],"title":"TransactionDatumResponse","description":"Response model for single transaction."},"TzName":{"type":"string","enum":["UTC","Europe/London","Europe/Brussels"],"title":"TzName","description":"An enumeration."},"UnenrolRequest":{"properties":{"proposition":{"anyOf":[{"type":"string","enum":["limited_pause","full_asset_schedule_control","price_curve"]},{"$ref":"#/components/schemas/PropositionRequest"}],"title":"Proposition","description":"Proposition to unenrol from"}},"type":"object","required":["proposition"],"title":"UnenrolRequest","description":"Request model for unenrolling a site from a proposition."},"UnenrolResponse":{"properties":{"site_id":{"type":"string","format":"uuid","title":"Site Id","description":"ID of the unenrolled site","examples":["a1b2c3d4-e5f6-7890-abcd-ef1234567890"]},"status":{"type":"string","enum":["unenrolled","already_unenrolled"],"title":"Status","examples":["unenrolled"]}},"type":"object","required":["site_id","status"],"title":"UnenrolResponse","description":"Response model for the unenrol endpoint."},"User":{"properties":{"username":{"type":"string","title":"Username"},"roles":{"items":{"type":"string"},"type":"array","title":"Roles","description":"Set of roles assigned to the user; any of `entity_read`, `entity_write`, `rewards`, `lookup`, `metrics_write`, `components`, `dispatch_explanation`"}},"type":"object","required":["username","roles"],"title":"User","description":"Response model for info about the current API user, including their roles."},"UserTransactionType":{"type":"string","enum":["charge credit","flex period","flex period top-up","flex event","withdrawal","invoice paid","goodwill credit","signup bonus","correction","VPP Signup Bonus","Referred Credit","Referrer Credit","Recurring Referrer Credit","FR SC Referred Credit","FR SC Referrer Credit","FR SC Signup Bonus"],"title":"UserTransactionType","description":"An enumeration."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"Vehicle":{"properties":{"charging_rate_kw":{"type":"number","title":"Charging Rate Kw"}},"type":"object","required":["charging_rate_kw"],"title":"Vehicle"}},"securitySchemes":{"OAuth2PasswordBearer":{"type":"oauth2","flows":{"password":{"scopes":{},"tokenUrl":"auth/token-form"}}}}},"tags":[{"name":"1. Authentication","description":"Authenticate yourself with the Axle API"},{"name":"2. Meters","description":"Find key info about your sites"},{"name":"3. Sites","description":"Register your sites with Axle; configure market participation"},{"name":"4. Assets","description":"Register your assets with Axle"},{"name":"5. Data","description":"Send asset metrics to Axle, for analysis and optimisation purposes"},{"name":"6. Rewards","description":"Determine how much your users have earned by participating with Axle; allow balance withdrawal"},{"name":"7. Validation","description":"Validate structured data against Axle's rules"},{"name":"8. Examples","description":"Get example data for testing"}]}