Green Button Alliance OpenESPI Authorization Server API
Green Button Alliance OpenESPI Authorization Server API from Green Button Alliance — 12 path(s) described in OpenAPI.
Green Button Alliance OpenESPI Authorization Server API from Green Button Alliance — 12 path(s) described in OpenAPI.
openapi: 3.0.3
info:
title: OpenESPI Authorization Server API
description: |
OAuth2/OIDC Authorization Server for Green Button Alliance ESPI 4.0 compliant applications.
This API provides:
- OAuth2 client management
- DataCustodian integration
- OIDC UserInfo endpoint with ESPI claims
- NAESB ESPI 4.0 compliance features
## Security
- **TLS 1.3 ONLY**: All communications must use TLS 1.3
- **Certificate Authentication**: Support for X.509 client certificates
- **Bearer Token**: Required for API access
- **Perfect Forward Secrecy**: All cipher suites support PFS
## ESPI Compliance
This server is certified for NAESB ESPI 4.0 compliance and supports:
- Green Button Connect My Data (CMD)
- Function Block 4.5.15+
- Certificate-based client authentication
- ESPI-specific scope validation
version: 1.0.0
contact:
name: Green Button Alliance
email: support@greenbuttonalliance.org
url: https://www.greenbuttonalliance.org
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0
termsOfService: https://www.greenbuttonalliance.org/terms
servers:
- url: https://authorization.greenbuttonalliance.org
description: Production server
- url: https://staging-authorization.greenbuttonalliance.org
description: Staging server
security:
- BearerAuth: []
- ClientCertificate: []
paths:
# OAuth2 Client Management API
/api/v1/oauth2/clients:
get:
tags:
- OAuth2 Client Management
summary: List OAuth2 clients
description: Retrieve a paginated list of registered OAuth2 clients
security:
- BearerAuth: []
parameters:
- name: page
in: query
description: Page number (zero-based)
schema:
type: integer
default: 0
minimum: 0
- name: size
in: query
description: Page size
schema:
type: integer
default: 20
minimum: 1
maximum: 100
- name: sort
in: query
description: Sort field
schema:
type: string
enum: [clientName, clientId, createdAt]
default: clientName
- name: direction
in: query
description: Sort direction
schema:
type: string
enum: [ASC, DESC]
default: ASC
- name: search
in: query
description: Search term for client name or ID
schema:
type: string
- name: espiCompliant
in: query
description: Filter by ESPI compliance
schema:
type: boolean
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/ClientListResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'429':
$ref: '#/components/responses/RateLimit'
post:
tags:
- OAuth2 Client Management
summary: Create new OAuth2 client
description: Register a new OAuth2 client
security:
- BearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateClientRequest'
responses:
'201':
description: Client created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/ClientResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'409':
$ref: '#/components/responses/Conflict'
'422':
$ref: '#/components/responses/ValidationError'
/api/v1/oauth2/clients/{clientId}:
get:
tags:
- OAuth2 Client Management
summary: Get client by ID
description: Retrieve a specific OAuth2 client by ID
security:
- BearerAuth: []
parameters:
- name: clientId
in: path
required: true
description: Client identifier
schema:
type: string
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/ClientResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
put:
tags:
- OAuth2 Client Management
summary: Update client
description: Update an existing OAuth2 client
security:
- BearerAuth: []
parameters:
- name: clientId
in: path
required: true
description: Client identifier
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateClientRequest'
responses:
'200':
description: Client updated successfully
content:
application/json:
schema:
$ref: '#/components/schemas/ClientResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/ValidationError'
delete:
tags:
- OAuth2 Client Management
summary: Delete client
description: Remove an OAuth2 client (soft delete)
security:
- BearerAuth: []
parameters:
- name: clientId
in: path
required: true
description: Client identifier
schema:
type: string
responses:
'200':
description: Client deleted successfully
content:
application/json:
schema:
$ref: '#/components/schemas/DeleteResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
/api/v1/oauth2/clients/{clientId}/metrics:
get:
tags:
- OAuth2 Client Management
summary: Get client metrics
description: Retrieve usage metrics for a specific client
security:
- BearerAuth: []
parameters:
- name: clientId
in: path
required: true
description: Client identifier
schema:
type: string
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/ClientMetricsResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
# DataCustodian Integration API
/api/v1/datacustodian/verify-user:
post:
tags:
- DataCustodian Integration
summary: Verify user credentials
description: Verify user credentials with DataCustodian
security:
- BearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/VerifyUserRequest'
responses:
'200':
description: User verification result
content:
application/json:
schema:
$ref: '#/components/schemas/VerifyUserResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'502':
$ref: '#/components/responses/DataCustodianError'
/api/v1/datacustodian/customers/{customerId}:
get:
tags:
- DataCustodian Integration
summary: Get retail customer info
description: Retrieve retail customer information from DataCustodian
security:
- BearerAuth: []
parameters:
- name: customerId
in: path
required: true
description: DataCustodian customer identifier
schema:
type: string
responses:
'200':
description: Customer information
content:
application/json:
schema:
$ref: '#/components/schemas/RetailCustomerResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'502':
$ref: '#/components/responses/DataCustodianError'
/api/v1/datacustodian/customers/{customerId}/usage-points:
get:
tags:
- DataCustodian Integration
summary: Get customer usage points
description: Retrieve usage points for a customer
security:
- BearerAuth: []
parameters:
- name: customerId
in: path
required: true
description: DataCustodian customer identifier
schema:
type: string
responses:
'200':
description: Usage points information
content:
application/json:
schema:
$ref: '#/components/schemas/UsagePointsResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'502':
$ref: '#/components/responses/DataCustodianError'
/api/v1/datacustodian/health:
get:
tags:
- DataCustodian Integration
summary: DataCustodian health check
description: Check DataCustodian integration health status
security:
- BearerAuth: []
responses:
'200':
description: Health status
content:
application/json:
schema:
$ref: '#/components/schemas/HealthResponse'
'401':
$ref: '#/components/responses/Unauthorized'
# OIDC UserInfo Endpoint
/userinfo:
get:
tags:
- OIDC
summary: Get user information
description: |
OpenID Connect UserInfo endpoint with ESPI-specific claims.
Returns user information based on the scopes granted to the access token.
**Standard OIDC Claims:**
- `openid` scope: sub
- `profile` scope: name, given_name, family_name, etc.
- `email` scope: email, email_verified
**ESPI-specific Claims:**
- FB scopes: customer_id, usage_point_details, data_rights
- Green Button Alliance extensions
security:
- BearerAuth: [openid]
responses:
'200':
description: User information
content:
application/json:
schema:
$ref: '#/components/schemas/UserInfoResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/InsufficientScope'
'500':
$ref: '#/components/responses/InternalServerError'
post:
tags:
- OIDC
summary: Get user information (POST)
description: Alternative POST method for UserInfo endpoint
security:
- BearerAuth: [openid]
requestBody:
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
access_token:
type: string
description: Access token (alternative to Authorization header)
responses:
'200':
description: User information
content:
application/json:
schema:
$ref: '#/components/schemas/UserInfoResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/InsufficientScope'
# OAuth2 Standard Endpoints
/oauth2/authorize:
get:
tags:
- OAuth2 Standard
summary: Authorization endpoint
description: |
OAuth2 authorization endpoint for initiating authorization code flow.
Supports PKCE (Proof Key for Code Exchange) for enhanced security.
parameters:
- name: response_type
in: query
required: true
description: Response type (must be 'code')
schema:
type: string
enum: [code]
- name: client_id
in: query
required: true
description: Client identifier
schema:
type: string
- name: redirect_uri
in: query
required: true
description: Callback URI
schema:
type: string
format: uri
- name: scope
in: query
required: true
description: Requested scopes (space-separated)
schema:
type: string
- name: state
in: query
required: true
description: CSRF protection parameter
schema:
type: string
- name: code_challenge
in: query
description: PKCE code challenge
schema:
type: string
- name: code_challenge_method
in: query
description: PKCE code challenge method
schema:
type: string
enum: [S256]
responses:
'302':
description: Redirect to callback URI with authorization code
'400':
description: Invalid request parameters
'401':
description: Authentication required
/oauth2/token:
post:
tags:
- OAuth2 Standard
summary: Token endpoint
description: OAuth2 token endpoint for exchanging authorization codes for access tokens
security:
- ClientCredentials: []
- ClientCertificate: []
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
oneOf:
- $ref: '#/components/schemas/AuthorizationCodeTokenRequest'
- $ref: '#/components/schemas/RefreshTokenRequest'
responses:
'200':
description: Access token response
content:
application/json:
schema:
$ref: '#/components/schemas/TokenResponse'
'400':
$ref: '#/components/responses/OAuth2Error'
'401':
$ref: '#/components/responses/OAuth2Error'
/oauth2/introspect:
post:
tags:
- OAuth2 Standard
summary: Token introspection
description: OAuth2 token introspection endpoint
security:
- ClientCredentials: []
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/IntrospectionRequest'
responses:
'200':
description: Token introspection response
content:
application/json:
schema:
$ref: '#/components/schemas/IntrospectionResponse'
'401':
$ref: '#/components/responses/Unauthorized'
/oauth2/revoke:
post:
tags:
- OAuth2 Standard
summary: Token revocation
description: OAuth2 token revocation endpoint
security:
- ClientCredentials: []
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/RevocationRequest'
responses:
'200':
description: Token revoked successfully
'401':
$ref: '#/components/responses/Unauthorized'
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
ClientCredentials:
type: http
scheme: basic
ClientCertificate:
type: mutualTLS
schemas:
# OAuth2 Client Management Schemas
ClientListResponse:
type: object
properties:
content:
type: array
items:
$ref: '#/components/schemas/ClientSummary'
pageable:
$ref: '#/components/schemas/Pageable'
totalElements:
type: integer
format: int64
totalPages:
type: integer
first:
type: boolean
last:
type: boolean
ClientSummary:
type: object
properties:
clientId:
type: string
clientName:
type: string
espiCompliant:
type: boolean
securityLevel:
type: string
enum: [LOW, MEDIUM, HIGH]
certificationStatus:
type: string
enum: [PENDING, CERTIFIED, EXPIRED, REVOKED]
createdAt:
type: string
format: date-time
lastUsed:
type: string
format: date-time
ClientResponse:
type: object
properties:
clientId:
type: string
clientName:
type: string
clientSecret:
type: string
description: "[PROTECTED] - Only returned on creation"
redirectUris:
type: array
items:
type: string
format: uri
scopes:
type: array
items:
type: string
authorizationGrantTypes:
type: array
items:
type: string
enum: [authorization_code, refresh_token, client_credentials]
clientAuthenticationMethods:
type: array
items:
type: string
enum: [client_secret_basic, client_secret_post, tls_client_auth]
espiCompliant:
type: boolean
securityLevel:
type: string
enum: [LOW, MEDIUM, HIGH]
certificationStatus:
type: string
enum: [PENDING, CERTIFIED, EXPIRED, REVOKED]
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
lastUsed:
type: string
format: date-time
usageMetrics:
$ref: '#/components/schemas/UsageMetrics'
CreateClientRequest:
type: object
required:
- clientName
- redirectUris
- scopes
properties:
clientName:
type: string
minLength: 1
maxLength: 100
redirectUris:
type: array
minItems: 1
items:
type: string
format: uri
scopes:
type: array
minItems: 1
items:
type: string
authorizationGrantTypes:
type: array
items:
type: string
enum: [authorization_code, refresh_token, client_credentials]
default: [authorization_code, refresh_token]
clientAuthenticationMethods:
type: array
items:
type: string
enum: [client_secret_basic, client_secret_post, tls_client_auth]
default: [client_secret_basic]
espiCompliant:
type: boolean
default: false
securityLevel:
type: string
enum: [LOW, MEDIUM, HIGH]
default: MEDIUM
clientSettings:
$ref: '#/components/schemas/ClientSettings'
tokenSettings:
$ref: '#/components/schemas/TokenSettings'
UpdateClientRequest:
type: object
properties:
clientName:
type: string
minLength: 1
maxLength: 100
redirectUris:
type: array
items:
type: string
format: uri
scopes:
type: array
items:
type: string
authorizationGrantTypes:
type: array
items:
type: string
enum: [authorization_code, refresh_token, client_credentials]
clientAuthenticationMethods:
type: array
items:
type: string
enum: [client_secret_basic, client_secret_post, tls_client_auth]
espiCompliant:
type: boolean
securityLevel:
type: string
enum: [LOW, MEDIUM, HIGH]
clientSettings:
$ref: '#/components/schemas/ClientSettings'
tokenSettings:
$ref: '#/components/schemas/TokenSettings'
ClientSettings:
type: object
properties:
requireAuthorizationConsent:
type: boolean
default: true
requireProofKey:
type: boolean
default: true
TokenSettings:
type: object
properties:
accessTokenTimeToLive:
type: string
description: ISO 8601 duration (e.g., PT1H)
default: PT1H
refreshTokenTimeToLive:
type: string
description: ISO 8601 duration (e.g., P30D)
default: P30D
reuseRefreshTokens:
type: boolean
default: false
ClientMetricsResponse:
type: object
properties:
clientId:
type: string
metrics:
$ref: '#/components/schemas/UsageMetrics'
UsageMetrics:
type: object
properties:
totalTokensIssued:
type: integer
format: int64
totalAuthorizationsGranted:
type: integer
format: int64
totalRefreshTokensUsed:
type: integer
format: int64
averageTokenLifetime:
type: integer
description: Average token lifetime in seconds
lastTokenIssuedAt:
type: string
format: date-time
peakUsageHour:
type: integer
minimum: 0
maximum: 23
weeklyStats:
$ref: '#/components/schemas/WeeklyStats'
WeeklyStats:
type: object
properties:
currentWeek:
$ref: '#/components/schemas/WeekStats'
previousWeek:
$ref: '#/components/schemas/WeekStats'
WeekStats:
type: object
properties:
authorizationsGranted:
type: integer
tokensIssued:
type: integer
# DataCustodian Integration Schemas
VerifyUserRequest:
type: object
required:
- username
- password
properties:
username:
type: string
password:
type: string
format: password
VerifyUserResponse:
type: object
properties:
verified:
type: boolean
customerId:
type: string
customerType:
type: string
enum: [RESIDENTIAL, COMMERCIAL, INDUSTRIAL]
message:
type: string
RetailCustomerResponse:
type: object
properties:
customerId:
type: string
username:
type: string
firstName:
type: string
lastName:
type: string
email:
type: string
format: email
customerType:
type: string
enum: [RESIDENTIAL, COMMERCIAL, INDUSTRIAL]
accountNumber:
type: string
serviceTerritory:
type: string
enrollmentDate:
type: string
format: date-time
status:
type: string
enum: [ACTIVE, INACTIVE, SUSPENDED]
UsagePointsResponse:
type: object
properties:
customerId:
type: string
usagePoints:
type: array
items:
$ref: '#/components/schemas/UsagePoint'
UsagePoint:
type: object
properties:
usagePointId:
type: string
usagePointUUID:
type: string
format: uuid
serviceCategory:
type: string
enum: [ELECTRICITY, GAS, WATER, TIME]
serviceKind:
type: string
enum: [ENERGY, DEMAND, VOLTAGE, CURRENT]
meterNumber:
type: string
serviceAddress:
type: string
status:
type: string
enum: [ACTIVE, INACTIVE]
installationDate:
type: string
format: date-time
HealthResponse:
type: object
properties:
status:
type: string
enum: [HEALTHY, DEGRADED, UNHEALTHY]
datacustodianVersion:
type: string
connectionStatus:
type: string
enum: [CONNECTED, DISCONNECTED, ERROR]
responseTime:
type: integer
description: Response time in milliseconds
lastSuccessfulCall:
type: string
format: date-time
metrics:
$ref: '#/components/schemas/HealthMetrics'
HealthMetrics:
type: object
properties:
totalRequests:
type: integer
format: int64
successfulRequests:
type: integer
format: int64
failedRequests:
type: integer
format: int64
averageResponseTime:
type: integer
description: Average response time in milliseconds
# OIDC Schemas
UserInfoResponse:
type: object
properties:
# Standard OIDC claims
sub:
type: string
description: Subject identifier
name:
type: string
description: Full name
given_name:
type: string
description: Given name
family_name:
type: string
description: Family name
preferred_username:
type: string
description: Preferred username
email:
type: string
format: email
description: Email address
email_verified:
type: boolean
description: Email verification status
locale:
type: string
description: Locale preference
zoneinfo:
type: string
description: Time zone
updated_at:
type: string
format: date-time
description: Last update time
# Authorization claims
aud:
type: string
description: Audience (client ID)
iss:
type: string
description: Issuer
iat:
type: string
format: date-time
description: Issued at time
exp:
type: string
format: date-time
description: Expiration time
auth_time:
type: string
format: date-time
description: Authentication time
scope:
type: string
description: Granted scopes
# ESPI-specific claims
customer_id:
type: string
description: DataCustodian customer identifier
customer_type:
type: string
enum: [RESIDENTIAL, COMMERCIAL, INDUSTRIAL]
description: Customer type
account_number:
type: string
description: Utility account number
service_territory:
type: string
description: Geographic service territory
espi_scopes:
type: array
items:
type: string
description: ESPI-specific scopes granted
datacustodian_grant_id:
type: string
description: DataCustodian grant identifier
authorized_usage_points:
type: array
items:
type: string
description: Authorized usage point IDs
usage_point_details:
type: array
items:
$ref: '#/components/schemas/UsagePointInfo'
description: Detailed usage point information
# Green Button Alliance extensions
gba_version:
type: string
description: Green Button Alliance version
espi_version:
type: string
description: NAESB ESPI version
data_rights:
type: array
items:
type: string
enum: [ENERGY_USAGE_DATA, 15_MINUTE_INTERVALS, HOURLY_INTERVALS, DAILY_USAGE_DATA, MONTHLY_BILLING_DATA, ADMIN_ACCESS, UPLOAD_ACCESS]
description: Granted data access rights
UsagePointInfo:
type: object
properties:
usage_point_id:
type: string
usage_point_uuid:
type: string
format: uuid
service_category:
type: string
enum: [ELECTRICITY, GAS, WATER, TIME]
service_kind:
type: string
enum: [ENERGY, DEMAND, VOLTAGE, CURRENT]
meter_number:
type: string
service_address:
type: string
status:
type: string
enum: [ACTIVE, INACTIVE]
# OAuth2 Standard Schemas
AuthorizationCodeTokenRequest:
type: object
required:
- grant_type
- code
- redirect_uri
properties:
grant_type:
type: string
enum: [authorization_code]
code:
type: string
redirect_uri:
type: string
format: uri
code_verifier:
type: string
description: PKCE code verifier
RefreshTokenRequest:
type: object
required:
- grant_type
- refresh_token
properties:
grant_type:
type: string
enum: [refresh_token]
refresh_token:
type: string
scope:
type: string
description: Optional scope limitation
TokenResponse:
type: object
properties:
access_token:
type: string
token_type:
type: string
enum: [Bearer]
expires_in:
type: integer
description: Token lifetime in seconds
refresh_token:
type: string
scope:
type: string
description: Granted scopes
id_token:
type: string
description: OpenID Connect ID token
IntrospectionRequest:
type: object
required:
- token
properties:
token:
type: string
token_type_hint:
type: string
enum: [access_token, refresh_token]
IntrospectionResponse:
type: object
properties:
active:
type: boolean
sub:
type: string
aud:
type: string
iss:
type: string
exp:
type: integer
iat:
type: integer
scope:
type: string
client_id:
type: string
token_type:
type: string
RevocationRequest:
type: object
required:
- token
properties:
token:
type: string
token_type_hint:
type: string
enum: [access_token, refresh_token]
# Common Schemas
Pageable:
type: object
properties:
sort:
type: object
properties:
sorted:
type: boolean
orderBy:
type: string
pageNumber:
type: integer
pageSize:
type: integer
DeleteResponse:
type: object
properties:
message:
type: string
clientId:
type: string
deletedAt:
type: string
format: date-time
ErrorResponse:
type: object
properties:
error:
type: string
error_description:
type: string
error_uri:
type: string
format: uri
timestamp:
type: string
format: date-time
path:
type: string
correlationId:
type: string
ValidationErrorResponse:
allOf:
- $ref: '#/components/schemas/ErrorResponse'
- type: object
properties:
details:
type: array
items:
type: object
properties:
field:
type: string
message:
type: string
responses:
BadRequest:
description: Bad request
content:
application/json:
# --- truncated at 32 KB (36 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/green-button-alliance/refs/heads/main/openapi/green-button-alliance-authorization-server-openapi.yml