ev.energy Regions API

Geographic regions and region groups used for program eligibility and tariffs.

Operations 7

GET /regions List regions #
POST /regions Create region #
GET /regions/{region_id} Retrieve region #
GET /region_groups List region groups #
POST /region_groups Create region group #
GET /region_groups/{region_group_id} Retrieve region group #
POST /region_groups:validate Validate a region group upload #

Documentation

Specifications

Other Resources

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/ev-energy-regions-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

ev-energy-regions-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: ev.energy v2 Regions API
  version: '2.0'
  contact:
    email: developers@ev.energy
    url: developers.ev.energy
    name: ev.energy developers
  description: The official API for ev.energy, version 2.
  license:
    name: Proprietary
    url: https://ev.energy
  termsOfService: ''
servers:
- url: https://api.ev.energy/v2
  description: Live API for both production and sandbox requests.
  x-internal: false
- description: Staging server for internal testing only.
  url: https://api-staging.ev.energy/v2
  x-internal: true
security:
- oauth2: []
tags:
- name: Regions
  description: Geographic regions and region groups used for program eligibility and tariffs.
paths:
  /regions:
    get:
      summary: List regions
      tags:
      - Regions
      operationId: get-regions
      description: List the regions created by your organisation (geometry omitted — retrieve a single region for its GeoJSON boundary).
      security:
      - oauth2:
        - region:read
      parameters:
      - $ref: '#/components/parameters/version-2'
      - $ref: '#/components/parameters/previous'
      - $ref: '#/components/parameters/next'
      - $ref: '#/components/parameters/page_size'
      - schema:
          type: string
        in: query
        name: name
        description: Exact region name.
      - schema:
          type: string
        in: query
        name: name__in
        description: Comma-separated list of exact region names.
      - schema:
          type: string
          pattern: rgrp[A-Z\d]{26}
        in: query
        name: region_group_id
        description: Only regions belonging to this region group (uid).
      - schema:
          type: string
          enum:
          - OTHER
          - ELECTRICITY
        in: query
        name: type
      - schema:
          type: string
          pattern: ^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$
          example: 42.2793,-71.1631
        in: query
        name: contains
        description: latitude,longitude — only regions strictly containing this point (a point exactly on a region's boundary does not match).
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Region'
          headers:
            Link:
              $ref: '#/components/headers/link'
            EvEnergy-Version:
              $ref: '#/components/headers/version-2'
            X-RateLimit-Limit:
              $ref: '#/components/headers/x-ratelimit-limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/x-ratelimit-remaining'
        '400':
          $ref: '#/components/responses/Problem400BadRequestList'
        '401':
          $ref: '#/components/responses/Problem401Unauthorized'
        '403':
          $ref: '#/components/responses/Problem403Forbidden'
        '406':
          $ref: '#/components/responses/Problem406NotAcceptable'
        '429':
          $ref: '#/components/responses/Problem429TooManyRequests'
    post:
      summary: Create region
      tags:
      - Regions
      operationId: post-regions
      description: 'Create a single region. The submitted geometries are unioned server-side into one MultiPolygon. Region names are unique across all organisations: a name clash returns 409 with the existing region''s URL — there is no upsert, and regions cannot be replaced via the API. The creating application must be linked to an organisation (creation is attributed to it, and only that organisation can read the region afterwards) — otherwise 403. Linked region_groups must belong to your organisation.'
      security:
      - oauth2:
        - region:write
      parameters:
      - $ref: '#/components/parameters/version-2'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RegionCreate'
      responses:
        '201':
          description: Region created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegionDetail'
          headers:
            EvEnergy-Version:
              $ref: '#/components/headers/version-2'
            X-RateLimit-Limit:
              $ref: '#/components/headers/x-ratelimit-limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/x-ratelimit-remaining'
        '400':
          $ref: '#/components/responses/Problem400BadRequestCreate'
        '401':
          $ref: '#/components/responses/Problem401Unauthorized'
        '403':
          $ref: '#/components/responses/Problem403Forbidden'
        '406':
          $ref: '#/components/responses/Problem406NotAcceptable'
        '409':
          description: A region with this name already exists (problem type region-name-conflict; extension member `conflicts` lists the clashing name and existing region URL). Nothing was written.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/RFC9457ProblemDetail'
        '413':
          description: Request body exceeds the 20 MB limit (problem type payload-too-large).
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/RFC9457ProblemDetail'
        '422':
          description: Validation failed — malformed GeoJSON, geometry not repairable by make_valid (problem type invalid-geometry, naming the region), or field validation errors (problem type validation-failed-regions).
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/RFC9457ProblemDetail'
        '429':
          $ref: '#/components/responses/Problem429TooManyRequests'
  /regions/{region_id}:
    parameters:
    - schema:
        type: string
        pattern: regn[A-Z\d]{26}
      name: region_id
      in: path
      required: true
    get:
      summary: Retrieve region
      tags:
      - Regions
      operationId: get-regions-region_id
      description: Retrieve a single region created by your organisation, including its full GeoJSON MultiPolygon geometry.
      security:
      - oauth2:
        - region:read
      parameters:
      - $ref: '#/components/parameters/version-2'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegionDetail'
          headers:
            EvEnergy-Version:
              $ref: '#/components/headers/version-2'
            X-RateLimit-Limit:
              $ref: '#/components/headers/x-ratelimit-limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/x-ratelimit-remaining'
        '400':
          $ref: '#/components/responses/Problem400BadRequestRetrieve'
        '401':
          $ref: '#/components/responses/Problem401Unauthorized'
        '403':
          $ref: '#/components/responses/Problem403Forbidden'
        '404':
          $ref: '#/components/responses/Problem404NotFound'
        '406':
          $ref: '#/components/responses/Problem406NotAcceptable'
        '429':
          $ref: '#/components/responses/Problem429TooManyRequests'
  /region_groups:
    get:
      summary: List region groups
      tags:
      - Regions
      operationId: get-region_groups
      description: List the region groups created by your organisation.
      security:
      - oauth2:
        - region:read
      parameters:
      - $ref: '#/components/parameters/version-2'
      - $ref: '#/components/parameters/previous'
      - $ref: '#/components/parameters/next'
      - $ref: '#/components/parameters/page_size'
      - schema:
          type: string
        in: query
        name: name
        description: Exact group name.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/RegionGroup'
          headers:
            Link:
              $ref: '#/components/headers/link'
            EvEnergy-Version:
              $ref: '#/components/headers/version-2'
            X-RateLimit-Limit:
              $ref: '#/components/headers/x-ratelimit-limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/x-ratelimit-remaining'
        '400':
          $ref: '#/components/responses/Problem400BadRequestList'
        '401':
          $ref: '#/components/responses/Problem401Unauthorized'
        '403':
          $ref: '#/components/responses/Problem403Forbidden'
        '406':
          $ref: '#/components/responses/Problem406NotAcceptable'
        '429':
          $ref: '#/components/responses/Problem429TooManyRequests'
    post:
      summary: Create region group
      tags:
      - Regions
      operationId: post-region_groups
      description: Atomically create a region group together with its member regions. Names are unique across all organisations, and every submitted region name must be fresh — a clash with an existing region always fails the whole request with 409; regions are never replaced or linked. Any failure rolls the whole request back — nothing is partially written. Send the identical body to POST /region_groups:validate first for a zero-write preview. The creating application must be linked to an organisation (creation is attributed to it, and only that organisation can read the group and regions afterwards) — otherwise 403.
      security:
      - oauth2:
        - region:write
      parameters:
      - $ref: '#/components/parameters/version-2'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RegionGroupCreate'
      responses:
        '201':
          description: Group and regions created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegionGroup'
          headers:
            EvEnergy-Version:
              $ref: '#/components/headers/version-2'
            X-RateLimit-Limit:
              $ref: '#/components/headers/x-ratelimit-limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/x-ratelimit-remaining'
        '400':
          $ref: '#/components/responses/Problem400BadRequestCreate'
        '401':
          $ref: '#/components/responses/Problem401Unauthorized'
        '403':
          $ref: '#/components/responses/Problem403Forbidden'
        '406':
          $ref: '#/components/responses/Problem406NotAcceptable'
        '409':
          description: Name conflict — either the group name is taken (problem type region-group-name-conflict, extension member `existing_region_group`) or one or more region entries clash with existing regions (problem type region-name-conflict, extension member `conflicts`). Includes clashes that appeared between :validate and this commit. Nothing was written.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/RFC9457ProblemDetail'
        '413':
          description: Request body exceeds the 20 MB limit (problem type payload-too-large).
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/RFC9457ProblemDetail'
        '422':
          description: Validation failed — unrepairable geometry (invalid-geometry, naming the region), duplicate/empty names, more than 500 regions, or an empty group (validation-failed-regions).
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/RFC9457ProblemDetail'
        '429':
          $ref: '#/components/responses/Problem429TooManyRequests'
  /region_groups/{region_group_id}:
    parameters:
    - schema:
        type: string
        pattern: rgrp[A-Z\d]{26}
      name: region_group_id
      in: path
      required: true
    get:
      summary: Retrieve region group
      tags:
      - Regions
      operationId: get-region_groups-region_group_id
      security:
      - oauth2:
        - region:read
      parameters:
      - $ref: '#/components/parameters/version-2'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegionGroup'
          headers:
            EvEnergy-Version:
              $ref: '#/components/headers/version-2'
            X-RateLimit-Limit:
              $ref: '#/components/headers/x-ratelimit-limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/x-ratelimit-remaining'
        '400':
          $ref: '#/components/responses/Problem400BadRequestRetrieve'
        '401':
          $ref: '#/components/responses/Problem401Unauthorized'
        '403':
          $ref: '#/components/responses/Problem403Forbidden'
        '404':
          $ref: '#/components/responses/Problem404NotFound'
        '406':
          $ref: '#/components/responses/Problem406NotAcceptable'
        '429':
          $ref: '#/components/responses/Problem429TooManyRequests'
  /region_groups:validate:
    post:
      summary: Validate a region group upload
      tags:
      - Regions
      operationId: post-region_groups:validate
      description: Zero-write dry-run of POST /region_groups with the identical body. Always returns 200 for content findings (name clashes, invalid geometry, duplicate names) — the findings ARE the response. Clashing entries include the existing region's URL; renaming the submitted region is the only resolution — regions are never replaced or linked.
      security:
      - oauth2:
        - region:write
      parameters:
      - $ref: '#/components/parameters/version-2'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RegionGroupCreate'
      responses:
        '200':
          description: Validation findings. Zero writes occurred.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegionGroupValidationResult'
          headers:
            EvEnergy-Version:
              $ref: '#/components/headers/version-2'
            X-RateLimit-Limit:
              $ref: '#/components/headers/x-ratelimit-limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/x-ratelimit-remaining'
        '400':
          $ref: '#/components/responses/Problem400BadRequestCreate'
        '401':
          $ref: '#/components/responses/Problem401Unauthorized'
        '403':
          $ref: '#/components/responses/Problem403Forbidden'
        '406':
          $ref: '#/components/responses/Problem406NotAcceptable'
        '413':
          description: Request body exceeds the 20 MB limit (problem type payload-too-large).
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/RFC9457ProblemDetail'
        '422':
          description: The body itself is malformed (missing name, wrong field types, more than 500 regions). Content-level findings return 200 instead.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/RFC9457ProblemDetail'
        '429':
          $ref: '#/components/responses/Problem429TooManyRequests'
components:
  responses:
    Problem404NotFound:
      description: This resource either does not exist or the client is not authorized to access it.
      content:
        application/problem+json:
          schema:
            type: object
            required:
            - title
            - detail
            properties:
              status:
                type: number
                example: 404
              title:
                type: string
                example: Not found
              detail:
                type: string
                example: Resource does not exist or cannot be accessed.
      headers:
        EvEnergy-Version:
          $ref: '#/components/headers/version-2'
        X-RateLimit-Limit:
          $ref: '#/components/headers/x-ratelimit-limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/x-ratelimit-remaining'
        RetryAfter:
          $ref: '#/components/headers/retry-after'
    Problem400BadRequestRetrieve:
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/RFC9457ProblemDetail'
          examples:
            Unsupported Version:
              $ref: '#/components/examples/ProblemUnsupportedVersion'
      description: A problem with the request's parameters prevented it being fulfilled.
      headers:
        EvEnergy-Version:
          $ref: '#/components/headers/version-2'
        X-RateLimit-Limit:
          $ref: '#/components/headers/x-ratelimit-limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/x-ratelimit-remaining'
    Problem400BadRequestCreate:
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/RFC9457ProblemDetail'
          examples:
            Request failed validation:
              $ref: '#/components/examples/ProblemValidationFailedVehicle'
      description: A problem with the request's parameters prevented it being fulfilled.
      headers:
        EvEnergy-Version:
          $ref: '#/components/headers/version-2'
        X-RateLimit-Limit:
          $ref: '#/components/headers/x-ratelimit-limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/x-ratelimit-remaining'
        RetryAfter:
          $ref: '#/components/headers/retry-after'
    Problem429TooManyRequests:
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/RFC9457ProblemDetail'
          examples:
            Example 1:
              value:
                type: https://api.ev.energy/v2/problems/rate-limit-exceeded/
                status: 429
                title: Too Many Requests
                detail: Request was rate limited. Try again in 42 seconds
      description: The client has exceeded its rate limit.
      headers:
        EvEnergy-Version:
          $ref: '#/components/headers/version-2'
        Retry-After:
          $ref: '#/components/headers/retry-after'
        X-RateLimit-Limit:
          $ref: '#/components/headers/x-ratelimit-limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/x-ratelimit-remaining'
    Problem401Unauthorized:
      description: You need to authorise requests to access this resource.
      content:
        application/problem+json:
          schema:
            type: object
            required:
            - title
            - detail
            properties:
              status:
                type: number
                example: 401
              title:
                type: string
                example: Unauthorized
              detail:
                type: string
                example: Authentication credentials were not provided.
      headers:
        EvEnergy-Version:
          $ref: '#/components/headers/version-2'
        X-RateLimit-Limit:
          $ref: '#/components/headers/x-ratelimit-limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/x-ratelimit-remaining'
        RetryAfter:
          $ref: '#/components/headers/retry-after'
    Problem400BadRequestList:
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/RFC9457ProblemDetail'
          examples:
            Invalid Pagination Parameter:
              $ref: '#/components/examples/ProblemInvalidPaginationParameter'
            Unsupported Version:
              $ref: '#/components/examples/ProblemUnsupportedVersion'
      description: A problem with the request's parameters prevented it being fulfilled.
      headers:
        EvEnergy-Version:
          $ref: '#/components/headers/version-2'
        X-RateLimit-Limit:
          $ref: '#/components/headers/x-ratelimit-limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/x-ratelimit-remaining'
        RetryAfter:
          $ref: '#/components/headers/retry-after'
    Problem403Forbidden:
      description: You do not have permission to perform this action.
      content:
        application/problem+json:
          schema:
            type: object
            required:
            - title
            - detail
            properties:
              status:
                type: number
                example: 403
              title:
                type: string
                example: Forbidden
              detail:
                type: string
                example: You do not have permission to perform this action.
      headers:
        EvEnergy-Version:
          $ref: '#/components/headers/version-2'
        X-RateLimit-Limit:
          $ref: '#/components/headers/x-ratelimit-limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/x-ratelimit-remaining'
        RetryAfter:
          $ref: '#/components/headers/retry-after'
    Problem406NotAcceptable:
      description: Could not satisfy the request Accept header.
      content:
        application/problem+json:
          schema:
            type: object
            required:
            - title
            - detail
            properties:
              status:
                type: number
                example: 406
              title:
                type: string
                example: Not Acceptable
              detail:
                type: string
                example: Could not satisfy the request Accept header.
      headers:
        EvEnergy-Version:
          $ref: '#/components/headers/version-2'
        X-RateLimit-Limit:
          $ref: '#/components/headers/x-ratelimit-limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/x-ratelimit-remaining'
        RetryAfter:
          $ref: '#/components/headers/retry-after'
  schemas:
    RFC9457ProblemDetail:
      title: RFC 9457 Problem Detail
      x-tags:
      - problems
      type: object
      required:
      - title
      - detail
      properties:
        type:
          type: string
          format: uri
          example: https://api.ev.energy/v2/problems/example-problem/
        status:
          type: number
          example: 400
        title:
          type: string
          example: Short description
        detail:
          type: string
          example: Long, more specific description.
        instance:
          type: string
          format: uri
          example: https://api.ev.energy/v2/users/user01HN2P75GBNFRJPCZJXEFVXH5E
        notification:
          $ref: '#/components/schemas/Notification'
      examples:
      - type: https://api.ev.energy/v2/problems/example-problem/
        status: 400
        title: Short description
        detail: Long, more specific description.
        instance: https://api.ev.energy/v2/users/user01HN2P75GBNFRJPCZJXEFVXH5E
        notification:
          id: notf01HTHKTXVB77901324BCQPF1RB
          url: https://api.ev.energy/notifications/notf01HTHKTXVB77901324BCQPF1RB
          message_id: ERR0123
          category: ACTIONABLE
          event_time: '2019-08-24T14:15:22Z'
          short_text_title: Your car is disconnected
          short_text_body: We need to reconnect to keep smart charging your car
          detail_page_title: Your car is disconnected
          detail_page_body: Your car has been disconnected. This happens when your password is reset. We need you to re-authorise ev.energy to access your account in order for us to keep managing your charging. Blah blah blah.
          external_link: http://example.com
          external_button_label: More info
          read_at: '2019-08-24T14:20:22Z'
          resolved_at: '2019-08-25T14:15:22Z'
    GeoJsonPolygon:
      title: GeoJsonPolygon
      type: object
      description: RFC 7946 GeoJSON Polygon in WGS 84. Positions are [longitude, latitude] (note the order — this is the GeoJSON interchange standard, not the {latitude, longitude} object used elsewhere in this API). The first ring is the exterior boundary; any further rings are holes.
      required:
      - type
      - coordinates
      properties:
        type:
          type: string
          enum:
          - Polygon
        coordinates:
          type: array
          description: Array of linear rings; each ring is a closed list of [longitude, latitude] positions (first position repeated last).
          minItems: 1
          maxItems: 100
          items:
            type: array
            minItems: 4
            maxItems: 25000
            items:
              type: array
              minItems: 2
              maxItems: 2
              items:
                type: number
    Notification:
      title: Notification
      description: Something that the user should be informed about.
      type: object
      examples:
      - id: notf67O36PLTFDB57M0E5L33JZLGM0
        url: https://api.ev.energy/notifications/notf67O36PLTFDB57M0E5L33JZLGM0
        message_id: ERR0123
        category: ACTIONABLE
        event_time: '2019-08-24T14:15:22Z'
        short_text_title: Your car is disconnected
        short_text_body: We need to reconnect to keep smart charging your car
        detail_page_title: Your car is disconnected
        detail_page_body: Your car has been disconnected. This happens when your password is reset. We need you to re-authorise ev.energy to access your account in order for us to keep managing your charging. Blah blah blah.
        external_link: http://example.com
        external_button_label: More info
        read_at: '2019-08-24T14:20:22Z'
        resolved_at: '2019-08-25T14:15:22Z'
      required:
      - id
      - url
      - message_id
      - category
      - event_time
      - short_text_title
      - short_text_body
      - detail_page_title
      - detail_page_body
      - external_link
      - external_button_label
      properties:
        id:
          type: string
          pattern: notf[A-Z\d]{26}
          example: notf67O36PLTFDB57M0E5L33JZLGM0
          description: Unique identifier for the Notification
        url:
          type: string
          format: uri
          example: https://api.ev.energy/notifications/notf67O36PLTFDB57M0E5L33JZLGM0
        message_id:
          type: string
          description: Internal identifier for this notification type. E.g. 'ERR0023'
        category:
          description: Category of this notification type
          enum:
          - ACTIONABLE
          - SERVICE
          - RETRY
          - MARKETING
          - INTERNAL
        event_time:
          type: string
          format: date-time
          description: The timestamp of the event described by this notification
        short_text_title:
          type: string
          description: Short title for the notification
          maxLength: 33
        short_text_body:
          type: string
          description: Short description of the event being notified
          maxLength: 49
        detail_page_title:
          type: string
          description: Title of a help page giving more information about this notification
        detail_page_body:
          type: string
          description: Text of a help page giving more information about this notification
        external_link:
          type:
          - string
          - 'null'
          description: URL of a web page giving further information about this notification
          format: uri
        external_button_label:
          type: string
          description: Text to be displayed on a button leading to the external_link location
        read_at:
          type: string
          format: date-time
          description: When the user examined the contents of this notification
        resolved_at:
          type: string
          format: date-time
          description: When the problem associated with this notification was resolved
    RegionGroupCreate:
      title: RegionGroupCreate
      type: object
      required:
      - name
      - regions
      properties:
        name:
          type: string
          example: Eversource MA Pilot 1A
          description: Unique name for the new group.
        regions:
          type: array
          minItems: 1
          maxItems: 500
          items:
            $ref: '#/components/schemas/RegionGroupEntry'
    Region:
      title: Region
      type: object
      description: A named geographic boundary (WGS 84) used to gate program tier eligibility, tariffs, carbon feeds and reward offers. Names are globally unique and immutable once created. The list representation omits the geometry; request a single region for the full GeoJSON MultiPolygon.
      properties:
        id:
          type: string
          example: regn01JCK1HPNAANB8WN253G27SFPC
          pattern: regn[A-Z\d]{26}
          readOnly: true
        url:
          type: string
          format: uri
          example: https://api.ev.energy/v2/regions/regn01JCK1HPNAANB8WN253G27SFPC
          readOnly: true
        name:
          type: string
          example: WEST ROXBURY
          description: Globally unique region name. Immutable after creation.
        type:
          type:
          - string
          - 'null'
          enum:
          - OTHER
          - ELECTRICITY
          - null
          description: Optional classification of the region.
        region_groups:
          type: array
          description: URLs of the region groups this region belongs to.
          readOnly: true
          items:
            type: string
            format: uri
        created_at:
          type: string
          format: date-time
          readOnly: true
        updated_at:
          type: string
          format: date-time
          readOnly: true
    RegionGroupValidationResult:
      title: RegionGroupValidationResult
      type: object
      properties:
        valid:
          type: boolean
          description: True when committing the identical body would succeed.
        group:
          type: object
          properties:
            name:
              type: string
            status:
              type: string
              enum:
              - AVAILABLE
              - NAME_EXISTS
            problems:
              type: array
              items:
                type: string
        regions:
          type: array
          items:
            $ref: '#/components/schemas/RegionValidationResult'
    RegionGroupEntry:
      title: RegionGroupEntry
      type: object
      required:
      - name
      - geometries
      properties:
        name:
          type: string
          example: MILTON
          description: Must not match any existing region — clashes fail the whole request with 409.
        type:
          type:
          - string
          - 'null'
          enum:
          - OTHER
          - ELECTRICITY
          - null
        geometries:
          type: array
          description: One or more GeoJSON Polygon/MultiPolygon geometries, unioned server-side into a single MultiPolygon.
          minItems: 1
          maxItems: 1000
          items:
            oneOf:
            - $ref: '#/components/schemas/GeoJsonPolygon'
            - $ref: '#/components/schemas/GeoJsonMultiPolygon'
    RegionGroup:
      title: RegionGroup
      type: object
      properties:
        id:
          type: string
          example: rgrp01JCK1HPNAANB8WN253G27SFPC
          pattern: rgrp[A-Z\d]{26}
          readOnly: true
        url:
          type: string
          format: uri
          readOnly: true
        name:
          type: string
          example: Eversource MA Pilot 1A
        regions:
          type: array
          description: URLs of the member regions.
          readOnly: true
          items:
            type: string
            format: uri
        regions_collection:
          type: string
          format: uri
          description: Pre-built link to the regions collection filtered to this group.
          readOnly: true
        created_at:
          type: string
          format: date-time
          readOnly: true
    RegionCreate:
      title: RegionCreate
      type: object
      required:
      - name
      - geometries
    

# --- truncated at 32 KB (40 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/ev-energy/refs/heads/main/openapi/ev-energy-regions-api-openapi.yml