> ## Documentation Index
> Fetch the complete documentation index at: https://docs.auth.energy/llms.txt
> Use this file to discover all available pages before exploring further.

# Verify Access Record

> Returns the full access record for a given access key. Called by Data Providers
before releasing meter data.

**Authentication:** Unauthenticated by design. The access key acts as the
credential; treat it as a secret.

**Note on PII:** This endpoint returns no PII. The person-property relationship
(MPxN, address, move-in date, identity verification) is held in the linked
Identity Record, which is accessible only to authenticated Data Users via
`GET /identity-records/{ir}`. The `identity-record-ref` in `record-metadata`
provides the link.

**Verification checklist (all record types):**
1. `access-event.state` must be `ACTIVE`.
2. `access-event.expiry` must be in the future, or null.
3. At least one controller in `record-metadata.controller-arrangement.controllers`
   must match the organisation you have a verified commercial relationship with
   on your platform. For `joint` arrangements, verify against the `lead` entry.
4. The data types being requested must be within `processing.data-types`.
5. Log `response.transaction-id` for your audit trail.

**Additional checks by legal basis:**
- Consent records: confirm `access-event.consent.consent-type` is appropriate
  for the data category being released.
- Legitimate interests: confirm `lia-reference` is present on the lead
  controller entry in `record-metadata.controller-arrangement`.
- Public task / legal obligation: confirm `statutory-reference` is present
  on the lead controller entry in `record-metadata.controller-arrangement`.




## OpenAPI

````yaml /data-access-register/api/openapi-dar.yaml get /access-records/{ak}
openapi: 3.1.0
info:
  title: Data Access Register
  description: >
    Core APIs for the Central Data Access Register.


    The register records all lawful access to customer energy data by
    Controllers,

    regardless of the legal basis on which that access rests. It is not
    exclusively

    a consent register — legitimate interests, public task, legal obligation,
    and

    contract are all within scope alongside consent-based access.


    **Jurisdiction:** This is a UK-only solution. All Controllers, customers,
    and

    meter points are within Great Britain. The governing data protection
    framework

    is **UK GDPR** and the **Data Protection Act 2018**. EU GDPR does not apply.

    The jurisdiction field is fixed to `GB` and does not need to be supplied.


    ## Purpose


    The register provides a single, auditable source of truth for:


    - **Controllers** — to record and demonstrate the legal basis under which
    they
      access customer meter data.
    - **Data Providers** — to verify that a Controller has a registered, active
    access
      record before releasing data.
    - **Customers** — to view all parties registered as having lawful access to
    their
      meter point, on request via any Controller.

    ## Party Model


    | Party | UK GDPR Role | Description |

    |---|---|---|

    | **Data User** | Processor | Operates the register. Fetches and processes
    meter data on behalf of Controllers. Authenticated via bearer token. |

    | **Controller** | Data Controller | A B2B customer of the Data User. One or
    more Controllers may be registered per access record — sole, joint (Art.
    26), or group (trading name transparency). Bears GDPR accountability for the
    legal basis and its ongoing validity. |

    | **Customer** | Data Subject | The energy customer. Identified by MPxN to
    minimise PII held centrally. |

    | **Data Provider** | Data Source | Holds meter data. Verifies access
    records before releasing data via `GET /access-records/{ak}`. |


    ## Record Structure


    All access records share a single schema — `AccessRecord` — with four
    sections

    aligned to ISO/IEC TS 27560:2023:


    1. **`record-metadata`** — record identifier, creation timestamp, controller
       arrangement (sole, joint, or group), and a reference to the associated
       Identity Record. Present for all records.
    2. **`notice`** — the privacy notice(s) presented to the customer. Present
    only
       for consent-based records; null for all other legal bases. Supports a single
       shared notice (common) or per-controller notices (joint arrangements where
       controllers discharge Art. 13 obligations separately).
    3. **`processing`** — legal basis, purpose, data types, and related
    obligations.
       Present for all records. Per-controller compliance fields (privacy rights URL,
       LIA reference, statutory reference, storage conditions) are held on each
       controller entry within `record-metadata.controller-arrangement`.
    4. **`access-event`** — when and how access was registered or consent was
    obtained;
       current lifecycle state. Present for all records.

    The `notice` and `access-event.consent` sub-object are null for non-consent
    records.

    The `access-event.consent` sub-object is null for non-consent records and
    populated

    for consent records.


    ## Identity Records


    The person-property relationship — who the individual is and their occupancy
    of the

    meter point — is held separately in an **Identity Record**
    (`/identity-records`).

    This keeps PII (MPxN, address, move-in date) and identity verification
    evidence

    out of the access record entirely.


    Each `AccessRecord` carries an `identity-record-ref` (`ir` key) linking it
    to its

    Identity Record. Identity Records are accessible only to authenticated Data
    Users.

    The unauthenticated `GET /access-records/{ak}` endpoint used by Data
    Providers

    never returns PII.


    Identity Records support two re-identification flows to reconnect a
    returning

    customer to an existing record without re-collecting all their details:

    - **Magic link** — a short-lived email link triggers re-identification.

    - **Passkey** — initiates a WebAuthn registration or assertion ceremony.


    ## Legal Basis and Required Fields


    The `processing.legal-basis` value determines which fields within `notice`
    and

    `access-event.consent` are expected:


    | Legal basis | `notice` | `access-event.consent` |

    |---|---|---|

    | `uk-consent`, `uk-explicit-consent` | **Required** | **Required** |

    | All other bases | Must be null | Must be null |


    For legitimate interests records, `lia-reference` should be supplied on the

    lead controller entry within `record-metadata.controller-arrangement`.

    For public task or legal obligation records, `statutory-reference`

    should be supplied on the lead controller entry.


    ## Access Record Lifecycle


    Records are never hard-deleted. All state transitions are recorded with
    timestamps.


    ```

    [ACTIVE] ──revoke──▶ [REVOKED]

    [ACTIVE] ──expiry──▶ [EXPIRED]

    [DISCOVERED] ──claimed──▶ [ACTIVE]

    [DISCOVERED] ──expiry──▶ [EXPIRED]

    ```


    `REVOKED` represents consent withdrawal (consent records) or the Controller

    removing their registration (non-consent records). Data Providers must deny

    access for any record not in `ACTIVE` state with a future (or null) expiry.


    `DISCOVERED` is a sparse, read-only state created by the DCC when it detects

    historic meter data requests from an organisation that has not yet
    registered

    as a Data User. These records are visible to Customers for transparency but

    cannot be used to authorise data release. When the organisation onboards as

    a Data User and registers a full access record for the same MPxN, the

    DISCOVERED record is superseded and transitions to `ACTIVE`.


    ## Authentication


    All endpoints except `GET /access-records/{ak}` require a bearer token from

    `GET /auth/token`. Tokens expire after 7200 seconds.


    ## Versioning


    URI-based versioning. Current version: `v1`.
  version: 0.0.16
  contact:
    name: Auth Energy
    email: contact@auth.energy
    url: https://docs.auth.energy/consent
  license:
    name: Proprietary
servers:
  - url: https://api.central.consent/v1
    description: Production
security: []
tags:
  - name: Identity Records
    description: >
      Endpoints for Data Users to create and manage Identity Records, which hold
      the person-property relationship (MPxN, address, move-in date, identity
      verification evidence) separately from access records. Supports
      re-identification of returning customers via email magic link or WebAuthn
      passkey.
  - name: Re-identification
    description: >-
      Endpoints for initiating and confirming customer re-identification flows.
      Supports magic link, passkey assertion, and passkey registration — both
      for the same Data User (same-DUID) and for a second Data User linking to
      an existing Identity Record created by another Data User (cross-DUID). In
      the cross-DUID flow the `ir` key is never exposed to the initiating Data
      User — the register resolves it internally after the customer completes
      the challenge.
  - name: Authentication
    description: Obtain bearer tokens for authenticated endpoints.
  - name: Data Users
    description: >
      Endpoints for Data Users (Processors) to register and manage access
      records on behalf of their Controller customers.
  - name: Data Providers
    description: >
      Endpoints for Data Providers (EDPs) to verify access records and look up
      registered Data User organisations before releasing meter data. Includes
      access record verification via access key and Data User directory lookup
      by DUID, allowing EDPs to confirm both that a specific record is active
      and that the organisation behind it is in good standing.
  - name: DCC
    description: >
      Endpoints restricted to Smart DCC system credentials. Covers two
      responsibilities: (1) submitting discovered access records derived from
      historic meter transaction logs — sparse, read-only records that surface
      to customers for transparency but cannot authorise data release,
      superseded when the organisation registers as a Data User; and (2)
      submitting Change of Tenancy events, which trigger `tenancy.change`
      webhooks to all Data Users with active access records on the affected
      MPxN.
  - name: Customer Portal
    description: >
      The centralised Customer Consent Portal is a standalone web service at
      https://portal.central.consent. It has no API endpoints — Data Users link
      customers to the portal via a plain URL carrying `ir` or `mpxn` and an
      optional `return` parameter. The portal authenticates the customer
      directly using the re-identification mechanisms on their Identity Record
      (passkey, magic link, or supplier OAuth fallback). This tag documents the
      portal behaviour and the `consent.withdrawal` webhook it fires on
      revocation.
  - name: Webhooks
    description: >
      Endpoints for Controllers to register and manage webhook subscriptions.
      The register dispatches event payloads to registered callback URLs when
      consent records are approaching expiry or when a Change of Tenancy is
      recorded against an MPxN with active access records.
paths:
  /access-records/{ak}:
    get:
      tags:
        - Data Providers
      summary: Verify Access Record
      description: >
        Returns the full access record for a given access key. Called by Data
        Providers

        before releasing meter data.


        **Authentication:** Unauthenticated by design. The access key acts as
        the

        credential; treat it as a secret.


        **Note on PII:** This endpoint returns no PII. The person-property
        relationship

        (MPxN, address, move-in date, identity verification) is held in the
        linked

        Identity Record, which is accessible only to authenticated Data Users
        via

        `GET /identity-records/{ir}`. The `identity-record-ref` in
        `record-metadata`

        provides the link.


        **Verification checklist (all record types):**

        1. `access-event.state` must be `ACTIVE`.

        2. `access-event.expiry` must be in the future, or null.

        3. At least one controller in
        `record-metadata.controller-arrangement.controllers`
           must match the organisation you have a verified commercial relationship with
           on your platform. For `joint` arrangements, verify against the `lead` entry.
        4. The data types being requested must be within
        `processing.data-types`.

        5. Log `response.transaction-id` for your audit trail.


        **Additional checks by legal basis:**

        - Consent records: confirm `access-event.consent.consent-type` is
        appropriate
          for the data category being released.
        - Legitimate interests: confirm `lia-reference` is present on the lead
          controller entry in `record-metadata.controller-arrangement`.
        - Public task / legal obligation: confirm `statutory-reference` is
        present
          on the lead controller entry in `record-metadata.controller-arrangement`.
      operationId: verifyAccess
      parameters:
        - name: ak
          in: path
          description: The access key issued at registration.
          required: true
          schema:
            $ref: '#/components/schemas/AccessKey'
      responses:
        '200':
          description: Access record found and returned.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerifyAccessResponse'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  schemas:
    AccessKey:
      type: string
      pattern: ^ak_[0-9a-f]{24}$
      description: >
        Unique opaque identifier for an access record, issued by the register on
        creation. Treat as a secret — possession enables access verification.
      example: ak_691df0c788ca043403b7fa90
    VerifyAccessResponse:
      type: object
      description: >
        The full access record returned for verification. `notice` and
        `access-event.consent` will be null for non-consent records.
      properties:
        response:
          $ref: '#/components/schemas/ResponseMetadata'
        access-record:
          $ref: '#/components/schemas/AccessRecord'
      required:
        - response
        - access-record
    ResponseMetadata:
      type: object
      properties:
        resource:
          type: string
          example: /v1/access-records/ak_691df0c788ca043403b7fa90
        timestamp:
          type: string
          format: date-time
          example: '2026-03-11T12:00:00Z'
        transaction-id:
          type: string
          description: >-
            Unique identifier for this request/response pair. Quote in support
            enquiries.
          example: tid_691df0c788ca043403b7fa90
      required:
        - resource
        - timestamp
        - transaction-id
    AccessRecord:
      type: object
      description: |
        A data access record covering all lawful bases. The same schema is used
        regardless of `processing.legal-basis`. The `notice` field and
        `access-event.consent` sub-object are null for non-consent records and
        populated for consent records.
      properties:
        record-metadata:
          $ref: '#/components/schemas/RecordMetadata'
        notice:
          nullable: true
          description: |
            Populated for consent-based records; null for all other legal bases.
          allOf:
            - $ref: '#/components/schemas/NoticeFields'
        processing:
          $ref: '#/components/schemas/ProcessingFields'
        access-event:
          $ref: '#/components/schemas/AccessEventFields'
        reidentification-token:
          type: string
          nullable: true
          description: >-
            Cross-DUID only. A confirmed token-ref obtained via `POST
            /identity-records/reidentify`. When supplied, `identity-record-ref`
            in `record-metadata` must be omitted — the register resolves the
            `ir` internally. The token is single-use, scoped to the initiating
            Data User, and expires one hour after issuance.
      required:
        - record-metadata
        - notice
        - processing
        - access-event
    ErrorResponse:
      type: object
      properties:
        response:
          $ref: '#/components/schemas/ResponseMetadata'
        errors:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/ErrorDetail'
      required:
        - response
        - errors
    RecordMetadata:
      type: object
      description: >-
        **ISO 27560 Section 1 — Record Metadata**


        `record-identifier` and `created-at` are assigned by the register on
        creation

        and returned in responses; they must not be supplied in request bodies.


        `identity-record-ref` links this access record to the Identity Record
        that

        holds the person-property relationship (PII principal, move-in date,
        address,

        and identity verification evidence). Supply the `ir` key returned when
        the

        Identity Record was created. The linked Identity Record must have been

        registered by the same authenticated Data User.



        `identity-record-ref` is required when registering a new Access Record
        in the standard flow. It may be omitted when a `reidentification-token`
        is supplied in the `POST /access-records` request body — the register
        resolves the `ir` internally from the validated token.
      properties:
        schema-version:
          type: string
          description: Version of the schema profile this record conforms to.
          example: '1.0'
        record-identifier:
          $ref: '#/components/schemas/AccessKey'
          readOnly: true
        created-at:
          type: string
          format: date-time
          readOnly: true
          description: >
            UTC timestamp when this record was created in the register. May
            differ from `access-event.registered-at` for historic registrations.
          example: '2024-01-15T09:30:00Z'
        controller-arrangement:
          $ref: '#/components/schemas/ControllerArrangement'
        identity-record-ref:
          $ref: '#/components/schemas/IdentityRecordKey'
          description: >
            Reference to the Identity Record holding the person-property
            relationship for this access registration. The `ir` key is issued
            when the Identity Record is created via `POST /identity-records`.
          nullable: true
      required:
        - schema-version
        - controller-arrangement
    NoticeFields:
      type: object
      description: >
        **ISO 27560 Section 2 — Notice Fields**


        Records the privacy notice(s) presented to the customer at the point of

        consent. Must be populated for consent-based records (`uk-consent`,

        `uk-explicit-consent`). Must be null for all other legal bases.


        Exactly one of `shared-notice` or `notices` must be populated:


        - **`shared-notice`** — a single notice covering all controllers in the
          arrangement. Use this for `sole`, `group`, and `joint` arrangements where
          the lead controller's notice covers all parties. This is the common case.
        - **`notices`** — an array of per-controller notices. Use this only for
          `joint` arrangements where each controller has separately discharged their
          Art. 13 obligations with distinct privacy notices. Must contain one entry
          per controller in `controller-arrangement.controllers`.

        `notice-version` alongside `terms-url` provides a stable audit
        reference;

        notice content may change at the same URL over time.
      properties:
        shared-notice:
          nullable: true
          description: >
            A single notice covering all controllers. Populated for `sole`,
            `group`, and most `joint` arrangements. Null when `notices` is used
            instead.
          allOf:
            - $ref: '#/components/schemas/NoticeDetail'
        notices:
          type: array
          nullable: true
          minItems: 2
          description: >
            Per-controller notices. Used only for `joint` arrangements where
            controllers have separately discharged Art. 13 obligations. Null
            when `shared-notice` is used instead.
          items:
            $ref: '#/components/schemas/ControllerNotice'
      required: []
    ProcessingFields:
      type: object
      description: >
        **ISO 27560 Section 3 — Processing Fields**


        Defines the shared scope and legal basis of data access. These fields
        apply

        to the access registration as a whole regardless of how many controllers

        are involved.


        Per-controller compliance fields — `privacy-rights-url`,
        `lia-reference`,

        `statutory-reference`, and `storage-conditions` — are held on each

        `Controller` entry within `record-metadata.controller-arrangement`,
        where

        each controller bears individual accountability.


        `legal-basis` applies to all controllers in the arrangement. For `joint`

        arrangements, all controllers must share the same legal basis — if
        purposes

        or bases differ, separate Access Records are required.
      properties:
        legal-basis:
          $ref: '#/components/schemas/LegalBasis'
        purpose:
          type: string
          maxLength: 500
          description: >
            Human-readable description of why the Controller(s) are accessing
            this data. Required by GDPR Art. 13(1)(c). Shared across all
            controllers in the arrangement.
          example: Energy efficiency analysis and tariff recommendations
        data-types:
          $ref: '#/components/schemas/DataType'
        jurisdiction:
          type: string
          enum:
            - GB
          default: GB
          readOnly: true
          description: >
            Jurisdiction governing processing. Fixed to `GB` (Great Britain) as
            this is a UK-only register operating under UK GDPR and the Data
            Protection Act 2018. This field is set automatically and does not
            need to be supplied.
        data-source:
          type: string
          maxLength: 255
          description: Name of the organisation(s) from which meter data is sourced.
          example: National Grid ESO / MPAS
        recipients:
          type: array
          description: >
            Third parties to whom data may be disclosed by any controller in the
            arrangement. Omit if none.
          items:
            $ref: '#/components/schemas/Recipient'
      required:
        - legal-basis
        - purpose
        - data-types
    AccessEventFields:
      type: object
      description: >-
        **ISO 27560 Section 4 — Access Event Fields**


        Records when access was registered, its lifecycle state and duration,
        and

        (for consent records) the specific details of how consent was expressed.


        `registered-at` serves as the canonical event timestamp for all record
        types —

        for consent records it is the date the customer gave consent; for
        non-consent

        records it is the date the Controller registered their access.


        `revoked-at` is set by the register on revocation and must not be
        supplied

        in request bodies.



        `consent` is required when `legal-basis` is `uk-consent` or
        `uk-explicit-consent`. It must be omitted or null for all other legal
        bases (`uk-public-task`, `uk-legitimate-interests`,
        `uk-legal-obligation`, `uk-contract`).
      properties:
        state:
          $ref: '#/components/schemas/AccessState'
        registered-at:
          type: string
          format: date-time
          description: >
            For consent records: date and time the customer gave consent. For
            non-consent records: date and time the Controller registered access.
            May predate `record-metadata.created-at` for historic registrations.
          example: '2023-11-07T05:31:56Z'
        expiry:
          type: string
          format: date-time
          nullable: true
          description: >
            When this access registration expires. Null indicates no defined end
            date. Data Providers must deny access once this timestamp has
            passed.
          example: '2027-11-10T17:07:01.580Z'
        controller-reference:
          type: string
          maxLength: 255
          description: >
            Controller's internal reference for this registration (e.g. CRM ID,
            contract number, or LIA document reference).
          example: REF-00123
        consent:
          nullable: true
          description: |
            Populated for consent-based records; null for all other legal bases.
          allOf:
            - $ref: '#/components/schemas/ConsentDetails'
        revoked-at:
          type: string
          format: date-time
          readOnly: true
          description: >
            UTC timestamp of revocation. Set by the register; not accepted in
            requests.
          example: '2025-06-01T14:22:00Z'
      required:
        - state
        - registered-at
        - expiry
    ErrorDetail:
      type: object
      properties:
        error-code:
          type: string
          example: VAL001
        message:
          type: string
          example: Field 'mpxn' does not match the required pattern.
      required:
        - error-code
        - message
    ControllerArrangement:
      type: object
      description: >
        **ISO 27560 Section 1 — Controller Arrangement**


        Describes the controller(s) accountable for this access record. Supports

        three arrangement types:


        **`sole`** — single controller. `controllers` has exactly one entry with

        `role: sole`. `art26-reference` must be null.


        **`joint`** — two or more legally distinct controllers jointly
        determining

        the purposes and means of processing (UK GDPR Art. 26). Exactly one
        entry

        must carry `role: lead`; all others carry `role: joint`.
        `art26-reference`

        is required and must point to the inter-controller arrangement document.

        Each controller should supply their own `privacy-rights-url`,
        `lia-reference`,

        and `statutory-reference` as applicable.


        **`group`** — one accountable lead plus trading names or subsidiaries
        listed

        for customer transparency. Exactly one entry carries `role: lead`; all
        others

        carry `role: member`. `art26-reference` must be null. Per-controller

        compliance fields are only required on the lead entry.


        In all cases the customer can exercise their GDPR rights against any

        controller listed — the `contact-url` and `privacy-rights-url` on each

        entry (where present) are shown in the Customer Portal.
      properties:
        arrangement-type:
          $ref: '#/components/schemas/ControllerArrangementType'
        art26-reference:
          type: string
          maxLength: 500
          nullable: true
          description: >
            Reference to the Art. 26 inter-controller arrangement (e.g. a
            contract reference or document URL). Required when
            `arrangement-type` is `joint`; must be null for `sole` and `group`.
          example: JCA-2024-BrightGrid-001
        controllers:
          type: array
          minItems: 1
          description: >
            The controller entries for this arrangement. Must contain exactly
            one `lead` (or `sole`) entry. Joint arrangements require at least
            two entries.
          items:
            $ref: '#/components/schemas/Controller'
      required:
        - arrangement-type
        - controllers
    IdentityRecordKey:
      type: string
      pattern: ^ir_[0-9a-f]{24}$
      description: >
        Unique opaque identifier for an Identity Record, issued by the register
        on creation. Referenced from `record-metadata.identity-record-ref` on an
        AccessRecord to link the two resources.
      example: ir_a3c5e7f9b1d3a3c5e7f9b1d3
    NoticeDetail:
      type: object
      description: >
        The privacy notice presented to the customer at the point of consent.
        Used as the `shared-notice` on a single shared notice, or as entries
        within the `notices` array for per-controller notices.
      properties:
        terms-url:
          type: string
          format: uri
          description: >
            URL of the privacy notice the customer agreed to. Must remain
            publicly accessible for the duration of any audit obligation.
          example: https://bright-energy.com/privacy-v3.html
        notice-version:
          type: string
          maxLength: 50
          description: >
            Version identifier of the specific notice agreed to, independent of
            URL.
          example: v3.2
        notice-language:
          type: string
          description: ISO 639-1 language code of the notice presented to the customer.
          example: en
      required:
        - terms-url
        - notice-version
    ControllerNotice:
      type: object
      description: >
        A per-controller notice entry. Used within `NoticeFields.notices` when
        joint controllers have each discharged their Art. 13 obligations with
        separate privacy notices.
      properties:
        controller-name:
          type: string
          maxLength: 255
          description: >
            The `name` of the controller entry in
            `controller-arrangement.controllers` this notice belongs to. Used to
            associate the notice with the correct controller for display in the
            Customer Portal.
          example: Grid Analytics Ltd
        terms-url:
          type: string
          format: uri
          example: https://gridanalytics.com/privacy-v2.html
        notice-version:
          type: string
          maxLength: 50
          example: v2.0
        notice-language:
          type: string
          example: en
      required:
        - controller-name
        - terms-url
        - notice-version
    LegalBasis:
      type: string
      description: >
        The legal basis under which the Controller accesses customer data.


        **Consent bases** — `notice` and `access-event.consent` must be
        populated.


        | Value | Plain name | Article |

        |---|---|---|

        | `uk-consent` | UK Consent | UK GDPR Art. 6(1)(a) |

        | `uk-explicit-consent` | UK Explicit Consent | UK GDPR Art. 9(2)(a) |


        **Non-consent bases** — `notice` and `access-event.consent` must be
        null.


        | Value | Plain name | Article | Supporting field (on lead controller) |

        |---|---|---|---|

        | `uk-legitimate-interests` | UK Legitimate Interests | UK GDPR Art.
        6(1)(f) | `lia-reference` |

        | `uk-public-task` | UK Public Task | UK GDPR Art. 6(1)(e) |
        `statutory-reference` |

        | `uk-legal-obligation` | UK Legal Obligation | UK GDPR Art. 6(1)(c) |
        `statutory-reference` |

        | `uk-contract` | UK Contract | UK GDPR Art. 6(1)(b) | — |
      enum:
        - uk-consent
        - uk-explicit-consent
        - uk-legitimate-interests
        - uk-public-task
        - uk-legal-obligation
        - uk-contract
      example: uk-consent
    DataType:
      type: array
      minItems: 1
      description: One or more energy data categories covered by this access record.
      items:
        type: string
        enum:
          - HH-CONSUMPTION
          - HH-EXPORT
          - MTH-CONSUMPTION
          - MTH-EXPORT
          - ANNUAL-CONSUMPTION
          - ANNUAL-EXPORT
          - TARIFF-IMPORT
          - TARIFF-EXPORT
    Recipient:
      type: object
      description: A third party to whom customer data may be disclosed.
      properties:
        name:
          type: string
          maxLength: 255
          example: Analytics Co Ltd
        role:
          type: string
          maxLength: 100
          description: >
            Role of this recipient (e.g. "Sub-processor", "Joint Controller",
            "Third Party Recipient").
          example: Sub-processor
        privacy-url:
          type: string
          format: uri
          example: https://analyticsco.com/privacy
      required:
        - name
        - role
    AccessState:
      type: string
      description: >
        Lifecycle state of the access record.


        - `ACTIVE` — access is registered and in force.

        - `EXPIRED` — the record's `expiry` has passed.

        - `REVOKED` — the Controller has removed their registration, or the
        customer
          has withdrawn consent. Retained for audit with `access-event.revoked-at` set.
        - `DISCOVERED` — a sparse record created by the DCC from historic meter
          transaction logs. The organisation has not yet registered as a Data User.
          Visible to customers for transparency but cannot authorise data release.
          Transitions to superseded when the organisation registers a full record.
      enum:
        - ACTIVE
        - EXPIRED
        - REVOKED
        - DISCOVERED
    ConsentDetails:
      type: object
      description: >
        Consent-specific event details. Nested within `access-event`. Must be

        populated when `processing.legal-basis` is a consent value; must be null

        for all other legal bases.


        Identity verification evidence and the expressed-by party are held in
        the

        linked Identity Record (`record-metadata.identity-record-ref`), not
        here.

        This object records only the legal character of the consent event
        itself.
      properties:
        consent-type:
          $ref: '#/components/schemas/ConsentType'
        method:
          type: string
          maxLength: 100
          description: >
            Mechanism through which consent was expressed — how the principal
            indicated their agreement (e.g. "Explicit web checkbox", "Signed
            paper form", "Voice recording", "In-app toggle").
          example: Explicit web checkbox
      required:
        - consent-type
    ControllerArrangementType:
      type: string
      description: >
        The nature of the controller arrangement for this access record.


        - `sole` — a single Data Controller bears full GDPR accountability.

        - `joint` — two or more legally distinct Data Controllers jointly
        determine
          the purposes and means of processing under UK GDPR Art. 26. An
          `art26-reference` pointing to their inter-controller arrangement must
          be supplied. Each controller holds individual accountability.
        - `group` — one accountable lead controller plus one or more trading
        names
          or subsidiaries listed purely for customer transparency, so customers
          recognise the brands accessing their data. The lead bears all GDPR
          accountability; members inherit it. No Art. 26 arrangement required.
      enum:
        - sole
        - joint
        - group
    Controller:
      type: object
      description: >
        A single controller entry within a `ControllerArrangement`. The `role`
        field determines its position in the arrangement. Per-controller
        compliance fields (`privacy-rights-url`, `lia-reference`,
        `statutory-reference`, `storage-conditions`) are required on `sole` and
        `lead` entries; optional on `joint` entries (where each controller
        should hold their own); and omitted on `member` entries (which inherit
        from the lead).
      properties:
        name:
          type: string
          maxLength: 255
          description: Trading name of the Controller organisation.
          example: Bright Energy Ltd
        role:
          $ref: '#/components/schemas/ControllerRole'
        contact-url:
          type: string
          format: uri
          description: URL of the Controller's customer-facing contact or privacy page.
          example: https://bright-energy.com/contact
        address:
          $ref: '#/components/schemas/UKAddress'
        privacy-rights-url:
          type: string
          format: uri
          description: >
            URL of this Controller's data subject rights page. Required by GDPR
            Art. 13(2)(b)/(c). Required on `sole` and `lead` entries. Optional
            on `joint` entries (where each controller should supply their own).
            Omitted on `member` entries — customers are directed to the lead's
            URL.
          example: https://bright-energy.com/your-rights
        lia-reference:
          type: string
          maxLength: 255
          nullable: true
          description: >
            Reference to this Controller's Legitimate Interests Assessment.
            Expected on `sole` and `lead` entries when `legal-basis` is
            `uk-legitimate-interests`. Each joint controller should supply their
            own.
          example: LIA-2024-003
        statutory-reference:
          type: string
          maxLength: 500
          nullable: true
          description: >
            The statutory instrument, regulation, or licence condition
            authorising this Controller's access. Expected on `sole` and `lead`
            entries when `legal-basis` is `uk-public-task` or
            `uk-legal-obligation`.
          example: Energy Act 2023, s.147
        storage-conditions:
          nullable: true
          description: >
            Where and for how long this Controller stores the data. Required on
            `sole` and `lead` entries. Optional on `joint` entries where storage
            arrangements differ. Omitted on `member` entries.
          allOf:
            - $ref: '#/components/schemas/StorageConditions'
      required:
        - name
        - role
        - contact-url
    ConsentType:
      type: string
      description: >
        Legal type of consent expressed. Only applicable when `legal-basis` is a

        consent value.


        - `expressed-consent` — actively and unambiguously expressed (e.g.
        checkbox).
          Sufficient for standard personal data under Art. 6(1)(a).
        - `explicit-consent` — explicit and specific. Required for special
        category
          data under Art. 9(2)(a), or where the Controller's process mandates it.
      enum:
        - expressed-consent
        - explicit-consent
    ControllerRole:
      type: string
      description: >
        Role of this controller entry within the arrangement.


        - `sole` — the only controller. Only valid when `arrangement-type` is
        `sole`.

        - `lead` — the primary accountable controller. Required in `joint` and
        `group`
          arrangements; exactly one entry must carry this role.
        - `joint` — a co-controller sharing Art. 26 accountability. Only valid
        when
          `arrangement-type` is `joint`.
        - `member` — a trading name or subsidiary listed for customer
        transparency.
          Only valid when `arrangement-type` is `group`. Inherits accountability
          from the lead.
      enum:
        - sole
        - lead
        - joint
        - member
    UKAddress:
      type: object
      properties:
        addressLine1:
          type: string
          maxLength: 100
          example: 221B Baker Street
        addressLine2:
          type: string
          maxLength: 100
          nullable: true
          example: Marylebone
        townCity:
          type: string
          maxLength: 100
          example: London
        county:
          type: string
          maxLength: 100
          nullable: true
          example: Greater London
        postcode:
          type: string
          pattern: ^[A-Z]{1,2}[0-9][0-9A-Z]? ?[0-9][A-Z]{2}$
          example: NW1 6XE
      required:
        - addressLine1
        - townCity
        - postcode
    StorageConditions:
      type: object
      properties:
        location:
          type: string
          description: >-
            ISO 3166-1 alpha-2 country code where data is stored. Expected to be
            `GB` for UK-only deployments.
          example: GB
        retention-period:
          type: string
          description: ISO 8601 duration for data retention after expiry or revocation.
          example: P2Y
      required:
        - location
        - retention-period
  responses:
    NotFound:
      description: The requested resource does not exist.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    InternalServerError:
      description: An unexpected server-side error occurred.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'

````