openapi: 3.0.3
info:
  title: Portal API
  description: Backend for epilot portals - End Customer Portal & Installer Portal
  version: 1.0.0
tags:
- name: ECP
  description: APIs defined for a portal user
- name: ECP Admin
  description: APIs defined for a ECP Admin
- name: Public
  description: Public APIs
- name: portal_user_schema
  x-displayName: Portal User
  description: |
    <SchemaDefinition schemaRef="#/components/schemas/PortalUser" />
x-tagGroups:
- name: APIs
  tags:
  - ECP
  - ECP Admin
  - Public
- name: Schemas
  tags:
  - portal_user_schema
security:
- EpilotAuth: []
- PortalAuth: []
- EitherAuth: []
paths:
  /v2/portal/portal:
    post:
      operationId: upsertPortal
      summary: upsertPortal
      description: Upserts the settings for a portal of an organization.
      security:
      - EpilotAuth: []
      tags:
      - ECP Admin
      parameters:
      - in: query
        name: origin
        required: true
        schema:
          $ref: '#/components/schemas/Origin'
        description: Origin of the portal
      requestBody:
        description: Portal payload
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpsertPortalConfig'
      responses:
        '201':
          description: Portal upserted successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PortalConfig'
        '400':
          $ref: '#/components/responses/InvalidRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/public/user:
    post:
      operationId: createUser
      summary: createUser
      description: Registers a portal user
      security: []
      tags:
      - Public
      parameters:
      - in: query
        name: origin
        required: true
        schema:
          $ref: '#/components/schemas/Origin'
        description: Origin of the portal
      requestBody:
        description: Portal user payload
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateUserRequest'
      responses:
        '201':
          description: User created successfully.
          content:
            application/json:
              schema:
                type: object
                required:
                - message
                - response
                properties:
                  message:
                    type: string
                    enum:
                    - User created successfully
        '400':
          $ref: '#/components/responses/InvalidRequest'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/token/validate:
    post:
      operationId: validateToken
      summary: validateToken
      description: Validates Portal Token is valid. Pass the token via Authorization Header.
      tags:
      - ECP
      security:
      - PortalAuth: []
      responses:
        '204':
          description: Tokens is valid for the given organization.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/token/revoke:
    post:
      operationId: revokeToken
      summary: revokeToken
      description: Revokes all of the access tokens for the given Refresh Token.
      tags:
      - ECP
      security:
      - PortalAuth: []
      requestBody:
        description: Token payload
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - refresh_token
              properties:
                refresh_token:
                  type: string
                  description: Refresh Token to be revoked
                  example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
      responses:
        '200':
          description: Access Tokens revoked successfully for the given Refresh Token.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    enum:
                    - Token revoked successfully
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/public/config:
    get:
      operationId: getPortalConfigByDomain
      summary: getPortalConfigByDomain
      description: Retrieves the portal configuration by domain.
      tags:
      - Public
      security: []
      parameters:
      - in: query
        name: domain
        required: true
        schema:
          type: string
          example: example.com
          description: Domain of the portal
      responses:
        '200':
          description: Portal config retrieved successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PortalConfig'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/config:
    get:
      operationId: getPortalConfig
      summary: getPortalConfig
      description: Retrieves the portal configuration.
      tags:
      - ECP Admin
      - ECP
      parameters:
      - in: query
        name: origin
        required: false
        schema:
          $ref: '#/components/schemas/Origin'
        description: Origin of the portal
      security:
      - EitherAuth: []
      responses:
        '200':
          description: Portal config retrieved successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PortalConfig'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
    delete:
      operationId: deletePortal
      summary: deletePortal
      description: Deletes the portal.
      tags:
      - ECP Admin
      parameters:
      - in: query
        name: origin
        required: true
        schema:
          $ref: '#/components/schemas/Origin'
        description: Origin of the portal
      security:
      - EpilotAuth: []
      responses:
        '204':
          description: Portal deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/extensions:
    get:
      operationId: getPortalExtensions
      summary: getPortalExtensions
      description: Retrieves the installed portal extensions.
      tags:
      - ECP Admin
      parameters:
      - in: query
        name: origin
        required: false
        schema:
          $ref: '#/components/schemas/Origin'
        description: Origin of the portal
      security:
      - EpilotAuth: []
      responses:
        '200':
          description: Portal extensions retrieved successfully.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Extension'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/public/extensions:
    get:
      operationId: getPublicPortalExtensionDetails
      summary: getPublicPortalExtensionDetails
      description: Get public extension details shown to end customers and configuring users.
      tags:
      - Public
      security: []
      parameters:
      - in: query
        name: org_id
        required: true
        schema:
          type: string
          example: 12324
          description: Organization ID
      - in: query
        name: origin
        required: true
        schema:
          $ref: '#/components/schemas/Origin'
        description: Origin of the portal
      responses:
        '200':
          description: Public details of extensions.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicExtensionCapabilities'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/consumption:
    get:
      operationId: getConsumption
      summary: Get Consumption
      description: Get energy consumption data between a given time period.
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - in: query
        name: extensionId
        schema:
          type: string
        required: true
        description: Extension ID for consumption data.
      - in: query
        name: hookId
        schema:
          type: string
        required: true
        description: Hook ID for consumption data.
      - in: query
        name: meter_id
        schema:
          type: string
        required: true
        description: Meter ID for consumption data.
      - in: query
        name: from
        schema:
          type: string
          format: date-time
        required: true
        description: Start date for consumption data (ISO 8601 format).
      - in: query
        name: to
        schema:
          type: string
          format: date-time
        required: true
        description: End date for consumption data (ISO 8601 format).
      - in: query
        name: interval
        schema:
          type: string
          enum:
          - PT15M
          - PT1H
          - P1D
          - P1M
        required: true
        description: Interval between consumption data points (e.g., PT15M for 15 minutes, PT1H for hourly). Not all intervals have to be supported.
      responses:
        '200':
          description: Consumption data returned successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  consumptions:
                    type: array
                    items:
                      type: object
                      properties:
                        timestamp:
                          type: string
                          format: date-time
                          description: ISO 8601 timestamp of the consumption record.
                        value:
                          type: number
                          description: The consumption value.
                        type:
                          type: string
                          description: Optional type of the consumption, such as 'nt' (night time) or 'ht' (high time).
                      required:
                      - value
                      - unit
                      - timestamp
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/costs:
    get:
      operationId: getCosts
      summary: Get Costs
      description: Get energy cost data between a given time period.
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - in: query
        name: extensionId
        schema:
          type: string
        required: true
        description: Extension ID for cost data.
      - in: query
        name: hookId
        schema:
          type: string
        required: true
        description: Hook ID for cost data.
      - in: query
        name: meter_id
        schema:
          type: string
        required: true
        description: Meter ID for cost data.
      - in: query
        name: from
        schema:
          type: string
          format: date-time
        required: true
        description: Start date for cost data (ISO 8601 format).
      - in: query
        name: to
        schema:
          type: string
          format: date-time
        required: true
        description: End date for cost data (ISO 8601 format).
      - in: query
        name: interval
        schema:
          type: string
          enum:
          - PT15M
          - PT1H
          - P1D
          - P1M
        required: true
        description: Interval between cost data points (e.g., PT15M for 15 minutes, PT1H for hourly). Not all intervals have to be supported.
      responses:
        '200':
          description: Cost data returned successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  costs:
                    type: array
                    items:
                      type: object
                      properties:
                        timestamp:
                          type: string
                          format: date-time
                          description: ISO 8601 timestamp of the cost record.
                        unit_amount:
                          type: integer
                          description: Cost in cents, e.g. 1234 for 12,34 €.
                          example: 1234
                        unit_amount_currency:
                          type: string
                          description: ISO 4217:2015 currency.
                          example: EUR
                        unit_amount_decimal:
                          type: string
                          description: Cost in decimal format, e.g. "12.34".
                          example: '12.34'
                        tax_behavior:
                          type: string
                          description: Is the tax (typically Value Added Tax) included in the amounts. Typically should NOT be included - exclusive of tax.
                          enum:
                          - inclusive
                          - exclusive
                          example: exclusive
                        tax_rate:
                          type: integer
                          description: Tax rate in percent, e.g. 19 for 19%.
                          example: 19
                      required:
                      - timestamp
                      - unit_amount
                      - unit_amount_currency
                      - unit_amount_decimal
                      - tax_behavior
                      - tax_rate
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/prices:
    get:
      operationId: getPrices
      summary: Get Prices
      description: Get energy prices data between a given time period.
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - in: query
        name: extensionId
        schema:
          type: string
        required: true
        description: Extension ID for price data.
      - in: query
        name: hookId
        schema:
          type: string
        required: true
        description: Hook ID for price data.
      - in: query
        name: meter_id
        schema:
          type: string
        required: true
        description: Meter ID for price data.
      - in: query
        name: from
        schema:
          type: string
          format: date-time
        required: true
        description: Start date for price data (ISO 8601 format).
      - in: query
        name: to
        schema:
          type: string
          format: date-time
        required: true
        description: End date for price data (ISO 8601 format).
      - in: query
        name: interval
        schema:
          type: string
          enum:
          - PT15M
          - PT1H
          - P1D
          - P1M
        required: true
        description: Interval between price data points (e.g., PT15M for 15 minutes, PT1H for hourly). Not all intervals have to be supported.
      responses:
        '200':
          description: Price data returned successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  prices:
                    type: array
                    items:
                      type: object
                      properties:
                        timestamp:
                          type: string
                          format: date-time
                          description: ISO 8601 timestamp of the price record.
                        unit_amount:
                          type: integer
                          description: Cost in cents, e.g. 1234 for 12,34 €.
                          example: 1234
                        unit_amount_currency:
                          type: string
                          description: ISO 4217:2015 currency.
                          example: EUR
                        unit_amount_decimal:
                          type: string
                          description: Cost in decimal format, e.g. "12.34".
                          example: '12.34'
                        components:
                          type: object
                          description: Optional price components.
                          properties:
                            auction_price_amount:
                              type: integer
                              description: Market price in cents, e.g. 1000 for 10,00 €.
                              example: 1000
                            auction_price_amount_decimal:
                              type: string
                              description: Market price in decimal format, e.g. "10.00".
                              example: '10.00'
                            taxes_levies_amount:
                              type: integer
                              description: Taxes/Levies other than tax specified on the price level in cents, e.g. 50 for 00,50 €.
                              example: 50
                            taxes_levies_amount_decimal:
                              type: string
                              description: Taxes/Levies other than tax specified on the price level in decimal format, e.g. "0.50".
                              example: '0.50'
                            source_fee_amount:
                              type: integer
                              description: Fee associated with the source, e.g. Green Energy Certificate fee in cents, e.g. 50 for 00,50 €.
                              example: 50
                            source_fee_amount_decimal:
                              type: string
                              description: Fee associated with the source, e.g. Green Energy Certificate fee in decimal format, e.g. "0.50".
                              example: '0.50'
                            grid_fee_amount:
                              type: integer
                              description: Fee associated with the transmission/distribution in cents, e.g. 100 for 1,00 €.
                              example: 100
                            grid_fee_amount_decimal:
                              type: string
                              description: Fee associated with the transmission/distribution in decimal format, e.g. "1.00".
                              example: '1.00'
                            margin_amount:
                              type: integer
                              description: Margin in cents, e.g. 34 for 0,34 €.
                              example: 34
                            margin_amount_decimal:
                              type: string
                              description: Margin in decimal format, e.g. "0.34".
                              example: '0.34'
                        tax_behavior:
                          type: string
                          description: Is the tax (typically Value Added Tax) included in the amounts. Typically should NOT be included - exclusive of tax.
                          enum:
                          - inclusive
                          - exclusive
                          example: exclusive
                        tax_rate:
                          type: integer
                          description: Tax rate in percent, e.g. 19 for 19%.
                          example: 19
                      required:
                      - timestamp
                      - unit_amount
                      - unit_amount_currency
                      - unit_amount_decimal
                      - tax_behavior
                      - tax_rate
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/external-links:
    get:
      operationId: getExternalLinks
      summary: getExternalLinks
      description: Retrieves the portal configuration external links.
      tags:
      - ECP Admin
      - ECP
      parameters:
      - in: query
        name: origin
        required: false
        schema:
          $ref: '#/components/schemas/Origin'
        description: Origin of the portal
      - in: query
        name: contactId
        required: false
        schema:
          $ref: '#/components/schemas/EntityId'
        description: Contact ID of the user
      security:
      - EitherAuth: []
      responses:
        '200':
          description: Portal config links retrieved successfully.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ExternalLink'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/resolve:external-link/{id}:
    get:
      operationId: getResolvedExternalLink
      summary: getResolvedExternalLink
      description: Retrieves a resolved portal external link.
      tags:
      - ECP Admin
      - ECP
      parameters:
      - in: path
        name: id
        required: true
        schema:
          $ref: '#/components/schemas/EntityId'
        description: ID of the External Link
      - in: query
        name: origin
        required: false
        schema:
          $ref: '#/components/schemas/Origin'
        description: Origin of the portal
      - in: query
        name: contactId
        required: false
        schema:
          $ref: '#/components/schemas/EntityId'
        description: Contact ID of the user
      security:
      - EitherAuth: []
      responses:
        '200':
          description: Resolved portal config link retrieved successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExternalLink'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/public/portal/config:
    get:
      operationId: getPublicPortalConfig
      summary: getPublicPortalConfig
      description: Retrieves the public portal configuration.
      tags:
      - Public
      security: []
      parameters:
      - in: query
        name: org_id
        required: true
        schema:
          type: string
          example: 12324
          description: Organization ID
      - in: query
        name: origin
        required: true
        schema:
          $ref: '#/components/schemas/Origin'
        description: Origin of the portal
      responses:
        '200':
          description: Portal config retrieved successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PortalConfig'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/org/portal/config:
    get:
      operationId: getOrgPortalConfig
      summary: getOrgPortalConfig
      description: Retrieves the portal configuration for the organization.
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      parameters:
      - in: query
        name: origin
        required: true
        schema:
          $ref: '#/components/schemas/Origin'
        description: Origin of the portal
      responses:
        '200':
          description: Portal config retrieved successfully.
          content:
            application/json:
              schema:
                allOf:
                - $ref: '#/components/schemas/PortalConfig'
                - type: object
                  properties:
                    certificate_details:
                      type: object
                      properties:
                        status:
                          type: string
                          description: Status of the certificate
                          enum:
                          - PENDING_VALIDATION
                          - ISSUED
                          - INACTIVE
                          - EXPIRED
                          - VALIDATION_TIMED_OUT
                          - REVOKED
                          - FAILED
                          - PENDING_AUTO_RENEWAL
                        failed_reason:
                          type: string
                          description: Reason for failed certificate
                          example: CAA_ERROR
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/configs:
    get:
      operationId: getAllPortalConfigs
      summary: getAllPortalConfigs
      description: Retrieves all portal configurations.
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      responses:
        '200':
          description: All portal configs retrieved successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/PortalConfig'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/email-templates:
    post:
      operationId: upsertEmailTemplates
      summary: upsertEmailTemplates
      description: Upserts the email templates of a portal
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      parameters:
      - in: query
        name: origin
        required: true
        schema:
          $ref: '#/components/schemas/Origin'
        description: Origin of the portal
      requestBody:
        description: Email templates payload
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EmailTemplates'
      responses:
        '200':
          description: Upserted email templates of the portal successfully.
          content:
            application/json:
              schema:
                type: object
                required:
                - message
                - emailTemplates
                properties:
                  message:
                    type: string
                    enum:
                    - Email Templates upserted successfully
                  emailTemplates:
                    $ref: '#/components/schemas/EmailTemplates'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
    get:
      operationId: getEmailTemplates
      summary: getEmailTemplates
      description: Retrieves the email templates of a portal
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      parameters:
      - in: query
        name: origin
        required: true
        schema:
          $ref: '#/components/schemas/Origin'
        description: Origin of the portal
      responses:
        '200':
          description: Retrieved the email templates successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmailTemplates'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/public-widgets:
    get:
      operationId: getPublicPortalWidgets
      summary: getPublicPortalWidgets
      description: Retrieves the public widgets of a portal
      tags:
      - Public
      security: []
      parameters:
      - in: query
        name: org_id
        required: true
        schema:
          type: string
          description: Organization ID
          example: 123
      - in: query
        name: origin
        required: true
        schema:
          $ref: '#/components/schemas/Origin'
        description: Origin of the portal
      responses:
        '200':
          description: Retrieved the portal public widgets successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpsertPortalWidget'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/widgets:
    post:
      operationId: upsertPortalWidget
      summary: upsertPortalWidget
      description: Upsert widget for a portal of an organization.
      security:
      - EpilotAuth: []
      tags:
      - ECP Admin
      parameters:
      - in: query
        name: origin
        required: true
        schema:
          $ref: '#/components/schemas/Origin'
        description: Origin of the portal
      requestBody:
        description: Portal widgets payload
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpsertPortalWidget'
      responses:
        '201':
          description: Portal widget configuration upserted successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpsertPortalWidget'
        '400':
          $ref: '#/components/responses/InvalidRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
    get:
      operationId: getPortalWidgets
      summary: getPortalWidgets
      description: Retrieves the widgets of a portal
      tags:
      - ECP Admin
      - ECP
      security:
      - EitherAuth: []
      parameters:
      - in: query
        name: origin
        required: false
        schema:
          $ref: '#/components/schemas/Origin'
        description: Origin of the portal
      - in: query
        name: contract_id
        required: false
        schema:
          $ref: '#/components/schemas/EntityId'
        description: Contract context for widgets
      responses:
        '200':
          description: Retrieved the portal widgets successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpsertPortalWidget'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/replace-ecp-template-variables:
    post:
      operationId: replaceECPTemplateVariables
      summary: replaceECPTemplateVariables
      description: Replaces the template variables of a portal
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      requestBody:
        description: ECPVariables payload
        content:
          application/json:
            schema:
              type: object
              additionalProperties:
                type: object
                properties:
                  _id:
                    $ref: '#/components/schemas/EntityId'
                    description: ID of the entity
                  is_main_entity:
                    type: boolean
      responses:
        '200':
          description: Replaced portal template variables successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  customerPortal:
                    type: object
                    properties:
                      invitationLink:
                        type: string
                        example: https://end-customer-portal.ecp.dev.epilot.io/register?contactId=7aa44fb8-d60e-40cc-9a3a-ba09a1ff7f51&email=john@doe.com
                      newDocumentLink:
                        type: string
                        example: https://end-customer-portal.ecp.dev.epilot.io/requests/opportunities/b8fef220-abe0-4382-a704-26848f60977b
                      entityLink:
                        type: string
                        example: https://end-customer-portal.ecp.dev.epilot.io/requests/opportunities/b8fef220-abe0-4382-a704-26848f60977b
                      userEmailsOnEntity:
                        type: array
                        example:
                        - john@doe.com
                        - mary@doe.com
                        items:
                          type: string
                  installerPortal:
                    type: object
                    properties:
                      invitationLink:
                        type: string
                        example: https://installer-portal.ecp.dev.epilot.io/register?contactId=7aa44fb8-d60e-40cc-9a3a-ba09a1ff7f51&email=john@doe.com
                      newDocumentLink:
                        type: string
                        example: https://installer-portal.ecp.dev.epilot.io/requests/opportunities/b8fef220-abe0-4382-a704-26848f60977b
                      entityLink:
                        type: string
                        example: https://installer-portal.ecp.dev.epilot.io/requests/opportunities/b8fef220-abe0-4382-a704-26848f60977b
                      userEmailsOnEntity:
                        type: array
                        example:
                        - peter@doe.com
                        - jane@doe.com
                        items:
                          type: string
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/org/settings:
    get:
      operationId: getOrganizationSettings
      summary: getOrganizationSettings
      description: Retrieves the organization settings.
      tags:
      - ECP
      security:
      - PortalAuth: []
      responses:
        '200':
          description: Retrieved the settings for an organization successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/OrganizationSettings'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/schemas:
    get:
      operationId: getSchemas
      summary: getSchemas
      description: Retrieves the schemas.
      tags:
      - ECP
      security:
      - PortalAuth: []
      responses:
        '200':
          description: Retrieved schemas for an organization successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  schemas:
                    type: array
                    items:
                      $ref: '#/components/schemas/Schema'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/extra-permission-attributes:
    get:
      operationId: extraPermissionAttributes
      summary: extraPermissionAttributes
      description: Retrieves the extra permission attributes.
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      responses:
        '200':
          description: Retrieved extra permission attributes successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      contact:
                        $ref: '#/components/schemas/ExtraSchemaAttributes'
                      contract:
                        $ref: '#/components/schemas/ExtraSchemaAttributes'
                      order:
                        $ref: '#/components/schemas/ExtraSchemaAttributes'
                      opportunity:
                        $ref: '#/components/schemas/ExtraSchemaAttributes'
                      meter:
                        $ref: '#/components/schemas/ExtraSchemaAttributes'
                      meter_counter:
                        $ref: '#/components/schemas/ExtraSchemaAttributes'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/validate/caa-records:
    post:
      operationId: validateCaaRecords
      summary: validateCaaRecords
      description: Validates the CAA records of a portal
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      parameters:
      - in: query
        name: origin
        required: true
        schema:
          $ref: '#/components/schemas/Origin'
      responses:
        '200':
          description: Validated CAA records successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  retry:
                    type: boolean
                    description: Whether to retry the validation to continue the domain setup
                  message:
                    type: string
                    description: Message of the validation
                  isDNSConfigured:
                    type: boolean
                    description: Whether the DNS is configured from the customer side
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/contact:
    get:
      operationId: getContact
      summary: getContact
      description: Retrieves the contact of the logged in user.
      tags:
      - ECP
      security:
      - PortalAuth: []
      responses:
        '200':
          description: Retrieves the mapped contact of the logged in user successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  entity:
                    $ref: '#/components/schemas/Contact'
                  files:
                    type: array
                    items:
                      $ref: '#/components/schemas/File'
                  relations:
                    type: array
                    items:
                      $ref: '#/components/schemas/EntityItem'
                  journey_actions:
                    type: array
                    items:
                      $ref: '#/components/schemas/JourneyActions'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
    patch:
      operationId: updateContact
      summary: updateContact
      description: Updates the contact details.
      tags:
      - ECP
      security:
      - PortalAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Entity'
      responses:
        '200':
          description: Updated the contact details successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Contact'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/ForbiddenByRule'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/ecp/contact:
    get:
      operationId: getECPContact
      summary: getECPContact
      description: Get the Contact by id
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      parameters:
      - in: query
        name: id
        required: true
        schema:
          $ref: '#/components/schemas/EntityId'
      responses:
        '200':
          description: The contact returned successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Contact'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/public/contact/exists:
    post:
      operationId: checkContactExists
      summary: checkContactExists
      description: True if contact with given identifiers exists.
      security: []
      tags:
      - Public
      parameters:
      - in: query
        name: origin
        required: true
        schema:
          $ref: '#/components/schemas/Origin'
        description: Origin of the portal
      requestBody:
        description: Request payload
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContactExistsRequest'
      responses:
        '200':
          description: Return result true|false if the contact with given identifiers exists.
          content:
            application/json:
              schema:
                type: object
                properties:
                  exists:
                    type: boolean
                    description: Whether the contact exists with the given identifier values
                    example: true
                  contactId:
                    $ref: '#/components/schemas/EntityId'
                    description: ID of the contact if exists
        '400':
          $ref: '#/components/responses/InvalidRequest'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/contact/valid/secondary/attributes:
    get:
      operationId: getValidSecondaryAttributes
      summary: getValidSecondaryAttributes
      description: Get valid secondary attributes that are used while mapping a contact on registration
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      responses:
        '200':
          description: Valid secondary attributes for the contact entity are returned successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                          description: Name of the secondary attribute
                          example: first_name
                        type:
                          type: string
                          description: Type of the secondary attribute
                          example: string
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/user:
    get:
      operationId: getPortalUser
      summary: getPortalUser
      description: Get the portal user details
      tags:
      - ECP
      security:
      - PortalAuth: []
      responses:
        '200':
          description: Portal user returned successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/PortalUser'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
    patch:
      operationId: updatePortalUser
      summary: updatePortalUser
      description: Update the portal user details
      tags:
      - ECP
      security:
      - PortalAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Entity'
      responses:
        '200':
          description: The portal user updated successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/PortalUser'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
    delete:
      operationId: deletePortalUser
      summary: deletePortalUser
      description: Delete the portal user
      tags:
      - ECP
      security:
      - PortalAuth: []
      responses:
        '200':
          description: Portal user deleted successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    enum:
                    - User Succesfully Deleted
                  data:
                    $ref: '#/components/schemas/EntityId'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/user/update/email:
    put:
      operationId: updatePortalUserEmail
      summary: updatePortalUserEmail
      description: Update portal user email
      tags:
      - ECP
      security:
      - PortalAuth: []
      requestBody:
        description: Request payload
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - email
              - password
              properties:
                email:
                  type: string
                  description: New email address of the portal user
                  example: john@doe.com
                password:
                  type: string
                  description: Password of the portal user for confirmation
      responses:
        '200':
          description: Portal user email updated successfully and will receive a confirmation email soon.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    enum:
                    - You will receive a confirmation mail soon on your updated email address.
        '400':
          $ref: '#/components/responses/InvalidRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/user/resend/confirmation-email/{id}:
    post:
      operationId: resendConfirmationEmail
      summary: resendConfirmationEmail
      description: Resend confirmation email
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      parameters:
      - in: path
        name: id
        schema:
          $ref: '#/components/schemas/EntityId'
        required: true
        description: The ID of portal user id
      responses:
        '200':
          description: Confirmation email resent successfully for the portal user.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    enum:
                    - Confirmation email sent successfully.
        '400':
          $ref: '#/components/responses/InvalidRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/users/by-related-entity:
    get:
      operationId: fetchPortalUsersByRelatedEntity
      summary: fetchPortalUsersByRelatedEntity
      description: Get all users for a given entity
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      parameters:
      - in: query
        name: entity_id
        required: true
        schema:
          $ref: '#/components/schemas/EntityId'
      - in: query
        name: slug
        required: true
        schema:
          $ref: '#/components/schemas/EntitySlug'
      responses:
        '200':
          description: Returns the portal users under the given entity.
          content:
            application/json:
              schema:
                type: object
                properties:
                  portalUsers:
                    type: array
                    items:
                      $ref: '#/components/schemas/PortalUser'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/user/confirm:
    get:
      operationId: confirmUser
      summary: confirmUser
      description: Confirm a portal user
      tags:
      - Public
      security: []
      parameters:
      - in: query
        name: confirmation_link_token
        required: true
        schema:
          type: string
          description: Confirmation link token
      - in: query
        name: use_redirect
        required: false
        schema:
          type: boolean
          description: Should the operation result in a 301 redirect
          default: true
      responses:
        '200':
          description: Returned in case of successful user confirmation
          content:
            application/json:
              schema:
                type: object
                properties:
                  confirmed:
                    type: boolean
                    description: Is the user confirmed
                    example: true
                  user_already_confirmed:
                    type: boolean
                    description: Is the user previously confirmed
                    example: true
        '301':
          description: User is confirmed and redirected to the portal successfully.
        '400':
          $ref: '#/components/responses/ConfirmUserInvalidRequest'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/user/confirm/{id}:
    get:
      operationId: confirmUserWithUserId
      summary: confirmUserWithUserId
      description: Confirm a portal user
      tags:
      - Public
      security: []
      parameters:
      - in: query
        name: origin
        required: true
        schema:
          $ref: '#/components/schemas/Origin'
      - in: path
        name: id
        schema:
          $ref: '#/components/schemas/EntityId'
        required: true
        description: The ID of portal user id
      - in: query
        name: org_id
        required: true
        schema:
          type: string
          example: 123
        description: Organization ID
      responses:
        '301':
          description: User is confirmed and redirected to the portal successfully.
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/public/user/exists:
    get:
      operationId: userExists
      summary: userExists
      description: Checks whether a user exists in the portal
      tags:
      - Public
      security: []
      parameters:
      - in: query
        name: email
        required: true
        schema:
          type: string
          description: Email Address of the portal user
          example: user@example.com
      - in: query
        name: org_id
        required: true
        schema:
          type: string
          description: Organization ID
          example: 123
      - in: query
        name: origin
        required: false
        description: Checkes if user exists in the given portal origin. If not provided, checks in all origins.
        schema:
          $ref: '#/components/schemas/Origin'
      responses:
        '200':
          description: Returned whether the user exists in the portal or not successfully.
          content:
            application/json:
              schema:
                type: object
                required:
                - exists
                properties:
                  exists:
                    type: boolean
                    description: Whether the user exists in the portal
                    example: true
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/recipients-to-notify:
    post:
      operationId: getRecipientsToNotifyOnAutomation
      summary: getRecipientsToNotifyOnAutomation
      description: Get recipients to notify on automation
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
              - emails
              - template_id
              properties:
                emails:
                  type: array
                  example:
                  - john@doe.com
                  description: Emails array that are part of the automation
                  items:
                    type: string
                template_id:
                  $ref: '#/components/schemas/EntityId'
                  description: Email template ID that used on the automation
      responses:
        '200':
          description: Returns the valid recipients to notify successfully.
          content:
            application/json:
              schema:
                type: object
                required:
                - emails
                properties:
                  recipients:
                    type: array
                    description: Filtered recipients to notify
                    items:
                      type: object
                      required:
                      - email
                      - recipient_id
                      properties:
                        email:
                          type: string
                          description: Email of the recipient
                          example: john@doe.com
                        recipient_id:
                          $ref: '#/components/schemas/EntityId'
                          description: ID of the recipient
                  message:
                    type: string
                    description: Reason to not notify the user
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/configure-distribution:
    get:
      operationId: configureDistribution
      summary: configureDistribution
      description: Configure the distribution for the portal's custom domain
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      parameters:
      - in: query
        name: origin
        required: true
        schema:
          $ref: '#/components/schemas/Origin'
      responses:
        '200':
          description: The cloudfront distribution has been configure successfully for the custom domain.
          content:
            application/json:
              schema:
                type: object
                properties:
                  domainName:
                    type: string
                    description: The domain name of the configured distribution
                    example: dsj8op4ha01jha23.cloudfront.net
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/order:
    get:
      operationId: getAllOrders
      summary: getAllOrders
      description: Get all orders for the portal user
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - in: query
        name: from
        required: false
        schema:
          type: number
          description: Initial offset to set for the search results
          example: 0
          default: 0
      - in: query
        name: size
        required: false
        schema:
          type: number
          description: Size of the search results
          example: 100
          default: 100
      responses:
        '200':
          description: The orders for the portal user returned successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      allOf:
                      - $ref: '#/components/schemas/Order'
                      - type: object
                        properties:
                          journey_actions:
                            $ref: '#/components/schemas/JourneyActions'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/order/{id}/acceptance:
    post:
      operationId: postOrderAcceptance
      summary: postOrderAcceptance
      description: Accept/decline an offer by id
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - in: path
        name: id
        schema:
          $ref: '#/components/schemas/EntityId'
        required: true
        description: The ID of order
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AcceptanceDecision'
      responses:
        '200':
          description: Order was accepted/declined successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Order'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/order/{id}:
    get:
      operationId: getOrder
      summary: getOrder
      description: Get an order by id
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - in: path
        name: id
        schema:
          $ref: '#/components/schemas/EntityId'
        required: true
        description: The ID of order
      responses:
        '200':
          description: The requested order has been retrieved successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  entity:
                    $ref: '#/components/schemas/Order'
                  files:
                    type: array
                    description: The related files of the requested order
                    items:
                      $ref: '#/components/schemas/File'
                  relations:
                    type: array
                    description: The related entities of the requested order
                    items:
                      $ref: '#/components/schemas/EntityItem'
                  products:
                    type: array
                    description: The related products of the requested order
                    items:
                      $ref: '#/components/schemas/Product'
                  crossSellableProducts:
                    type: array
                    description: The related cross sellable products of the requested order
                    items:
                      $ref: '#/components/schemas/Product'
                  workflow:
                    type: array
                    description: The related workflows of the requested order
                    items:
                      $ref: '#/components/schemas/WorkflowExecution'
                  journey_actions:
                    type: array
                    items:
                      $ref: '#/components/schemas/JourneyActions'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
    patch:
      operationId: updateOrder
      summary: updateOrder
      description: Update an order by id
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - in: path
        name: id
        schema:
          $ref: '#/components/schemas/EntityId'
        required: true
        description: The ID of order
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Entity'
      responses:
        '200':
          description: Updated the order details successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Order'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/opportunity:
    get:
      operationId: getAllOpportunities
      summary: getAllOpportunities
      description: Get all opportunities of a portal user
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - in: query
        name: from
        required: false
        schema:
          type: number
          description: Initial offset to set for the search results
          example: 0
          default: 0
      - in: query
        name: size
        required: false
        schema:
          type: number
          description: Size of the search results
          example: 100
          default: 100
      responses:
        '200':
          description: The opportunities is retrieved successfully for the portal user.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      allOf:
                      - $ref: '#/components/schemas/Opportunity'
                      - type: object
                        properties:
                          journey_actions:
                            $ref: '#/components/schemas/JourneyActions'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/opportunities/searchable-attributes:
    get:
      operationId: getSearchableAttributesForOpportunities
      summary: getSearchableAttributesForOpportunities
      description: Get all opportunity searchable attributes for a portal user
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - in: query
        name: from
        required: false
        schema:
          type: number
          description: Initial offset to set for the search results
          example: 0
          default: 0
      - in: query
        name: size
        required: false
        schema:
          type: number
          description: Size of the search results
          example: 1000
          default: 1000
      responses:
        '200':
          description: The opportunities is retrieved successfully for the portal user.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Opportunity'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/opportunities/search:
    post:
      operationId: getSearchResultsForOpportunities
      summary: getSearchResultsForOpportunities
      description: Get all opportunity with the given serached attributes
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - in: query
        name: from
        required: false
        schema:
          type: number
          description: Initial offset to set for the search results
          example: 0
          default: 0
      - in: query
        name: size
        required: false
        schema:
          type: number
          description: Size of the search results
          example: 1000
          default: 1000
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                addresses:
                  type: array
                  items:
                    type: string
                customers:
                  type: array
                  items:
                    type: string
                purposes:
                  type: array
                  items:
                    $ref: '#/components/schemas/EntityId'
                workflows:
                  type: array
                  items:
                    items:
                      $ref: '#/components/schemas/WorfklowIdentifier'
      responses:
        '200':
          description: The opportunities is retrieved successfully for the portal user.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Opportunity'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/opportunities/{id}:
    get:
      operationId: getOpportunity
      summary: getOpportunity
      description: Get an opportunity by id
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - in: path
        name: id
        schema:
          $ref: '#/components/schemas/EntityId'
        required: true
        description: The ID of opportunity
      responses:
        '200':
          description: The returned opportunities
          content:
            application/json:
              schema:
                type: object
                properties:
                  entity:
                    $ref: '#/components/schemas/Opportunity'
                  orders:
                    type: array
                    description: The related orders of the requested opportunity
                    items:
                      $ref: '#/components/schemas/Order'
                  files:
                    type: array
                    description: The related files of the requested opportunity
                    items:
                      $ref: '#/components/schemas/File'
                  relations:
                    type: array
                    description: The related entities of the requested opportunity
                    items:
                      $ref: '#/components/schemas/EntityItem'
                  workflow:
                    type: array
                    description: The related workflows of the requested opportunity
                    items:
                      $ref: '#/components/schemas/WorkflowExecution'
                  journey_actions:
                    type: array
                    items:
                      $ref: '#/components/schemas/JourneyActions'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
    patch:
      operationId: updateOpportunity
      summary: updateOpportunity
      description: Update an opportunity by id
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - in: path
        name: id
        schema:
          $ref: '#/components/schemas/EntityId'
        required: true
        description: The ID of opportunity
      requestBody:
        description: Requested opportunity body to update
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Entity'
      responses:
        '200':
          description: Updated the opportunity successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Opportunity'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/request:
    get:
      operationId: getAllRequests
      summary: getAllRequests
      description: Get all opportunities & orders of a portal user
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - in: query
        name: from
        required: false
        schema:
          type: number
          description: Initial offset to set for the search results
          example: 0
          default: 0
      - in: query
        name: size
        required: false
        schema:
          type: number
          description: Size of the search results
          example: 100
          default: 200
      responses:
        '200':
          description: The opportunities is retrieved successfully for the portal user.
          content:
            application/json:
              schema:
                type: object
                properties:
                  hits:
                    type: number
                    description: Total number of hits
                    example: 1
                  results:
                    type: array
                    items:
                      allOf:
                      - type: object
                        oneOf:
                        - $ref: '#/components/schemas/Opportunity'
                        - $ref: '#/components/schemas/Order'
                      - type: object
                        properties:
                          journey_actions:
                            $ref: '#/components/schemas/JourneyActions'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/contract:
    get:
      operationId: getAllContracts
      summary: getAllContracts
      description: Get all contracts for a portal user
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - in: query
        name: from
        required: false
        schema:
          type: number
          description: Initial offset to set for the search results
          example: 0
          default: 0
      - in: query
        name: size
        required: false
        schema:
          type: number
          description: Size of the search results
          example: 100
          default: 100
      responses:
        '200':
          description: Contracts have been retrieved successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      allOf:
                      - $ref: '#/components/schemas/Contract'
                      - type: object
                        properties:
                          journey_actions:
                            $ref: '#/components/schemas/JourneyActions'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/contract/{id}:
    get:
      operationId: getContract
      summary: getContract
      description: Get a contract by id
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - in: path
        name: id
        schema:
          $ref: '#/components/schemas/EntityId'
        required: true
        description: The ID of the contract
      responses:
        '200':
          description: The requested contract returned successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  entity:
                    $ref: '#/components/schemas/Contract'
                  orders:
                    type: array
                    description: The related orders of the requested contract
                    items:
                      $ref: '#/components/schemas/Order'
                  meters:
                    type: array
                    description: The related meters of the requested contract
                    items:
                      $ref: '#/components/schemas/Meter'
                  files:
                    type: array
                    description: The related files of the requested contract
                    items:
                      $ref: '#/components/schemas/File'
                  relations:
                    type: array
                    description: The related entities of the requested contract
                    items:
                      $ref: '#/components/schemas/EntityItem'
                  workflow:
                    type: array
                    items:
                      $ref: '#/components/schemas/WorkflowExecution'
                  journey_actions:
                    type: array
                    items:
                      $ref: '#/components/schemas/JourneyActions'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
    patch:
      operationId: updateContract
      summary: updateContract
      description: Update a contract by id
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - in: path
        name: id
        schema:
          $ref: '#/components/schemas/EntityId'
        required: true
        description: The ID of the contract
      requestBody:
        description: Requested contract body to update
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Entity'
      responses:
        '200':
          description: Updated the contract successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Contract'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/ForbiddenByRule'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/contract/by-identifiers:
    post:
      operationId: addContractByIdentifiers
      summary: addContractByIdentifiers
      description: Self-assign contract(s) by pre-configured identifiers.
      tags:
      - ECP
      security:
      - PortalAuth: []
      requestBody:
        description: Identifiers to search by. Have to be pre-configured in Portal Configuration Permissions.
        required: true
        content:
          application/json:
            schema:
              type: object
              description: Identifier-value pairs per schema to identify the contract
              additionalProperties:
                type: object
                additionalProperties:
                  type: string
              example:
                contract:
                  contract_number: '123456'
                meter:
                  meter_number: '123456'
      responses:
        '200':
          description: Contract(s) assigned successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/EntityItem'
                  hits:
                    type: number
                    minimum: 0
                required:
                - hits
        '400':
          $ref: '#/components/responses/InvalidRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '409':
          $ref: '#/components/responses/ContractAssignmentConflict'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/entity/identifiers/{slug}:
    get:
      operationId: getEntityIdentifiers
      summary: getEntityIdentifiers
      description: Retrieve a list of entity identifiers used for entity search by portal users.
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      parameters:
      - in: path
        name: slug
        schema:
          $ref: '#/components/schemas/EntitySlug'
        required: true
        description: The slug of an entity
      responses:
        '200':
          description: The identifiers of the requested entity returned successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                          description: The name of the identifier
                          example: contract_number
                        type:
                          type: string
                          description: The type of the identifier
                          example: string
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/entity/{slug}/{id}/activity:
    get:
      operationId: getEntityActivityFeed
      summary: getEntityActivityFeed
      description: |
        Get activity feed for an entity
      tags:
      - Activity
      parameters:
      - in: path
        name: slug
        description: Entity Type
        required: true
        schema:
          $ref: '#/components/schemas/EntitySlug'
      - in: path
        name: id
        description: Entity id
        required: true
        schema:
          $ref: '#/components/schemas/EntityId'
      - in: query
        name: after
        description: Get activities after this timestamp
        schema:
          type: string
          format: date-time
      - in: query
        name: before
        description: get activities before this timestamp
        schema:
          type: string
          format: date-time
      - in: query
        name: from
        description: start from page
        schema:
          type: integer
          minimum: 0
          default: 0
      - in: query
        name: size
        description: max number of results to return
        schema:
          type: integer
          minimum: 1
          default: 25
      - in: query
        name: type
        description: Filter by activity type
        schema:
          type: string
          example: SyncActivity
      - in: query
        name: include_relations
        description: Include activities from related entities
        schema:
          type: boolean
          default: false
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  total:
                    type: integer
                    example: 1
                  results:
                    type: array
                    items:
                      $ref: '#/components/schemas/ActivityItem'
  /v2/portal/{slug}/{id}:validateRule:
    get:
      operationId: validateCadenceEntityEditRules
      summary: validateCadenceEntityEditRules
      description: |
        Validate if cadence rule is valid for an entity
      tags:
      - ECP
      parameters:
      - in: path
        name: slug
        description: Entity Type
        required: true
        schema:
          $ref: '#/components/schemas/EntitySlug'
      - in: path
        name: id
        description: Entity id
        required: true
        schema:
          $ref: '#/components/schemas/EntityId'
      - in: query
        name: attribute
        description: Get activities after this timestamp
        schema:
          type: string
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  isBlockedByRules:
                    type: boolean
                    example: false
                  failedRule:
                    $ref: '#/components/schemas/EntityEditRule'
  /v2/portal/entities-by-payment/{id}:
    get:
      operationId: searchPaymentRelationsInEntities
      summary: searchPaymentRelationsInEntities
      description: |
        Search for entities that have the payment relation with the given payment id
      tags:
      - ECP
      parameters:
      - in: path
        name: id
        description: Entity id
        required: true
        schema:
          $ref: '#/components/schemas/EntityId'
      responses:
        '200':
          description: Entities that have the payment relation.
          content:
            application/json:
              schema:
                type: object
                properties:
                  results:
                    type: array
                    items:
                      $ref: '#/components/schemas/EntityItem'
                  hits:
                    type: number
                    description: Total number of files for entities found
                    example: 50
  /v2/portal/entity/activity:
    put:
      operationId: createCustomEntityActivity
      summary: createCustomEntityActivity
      description: Create a custom activity that can be displayed in activity feed of an entity.
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - in: query
        name: entities
        description: Comma-separated list of entities which the activity primarily concerns. Deprecated - ignored as the list of entities is automatically determined now.
        deprecated: true
        style: form
        explode: false
        schema:
          type: array
          items:
            $ref: '#/components/schemas/EntityId'
          minItems: 1
          uniqueItems: true
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                type:
                  type: string
                  enum:
                  - PortalUserResetPassword
                  description: One of supported activity types
              required:
              - type
      responses:
        '201':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActivityItem'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/entity/file:
    post:
      operationId: saveEntityFile
      summary: saveEntityFile
      description: Add files to an entity
      tags:
      - ECP
      security:
      - PortalAuth: []
      requestBody:
        description: The request of an file entity
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SaveEntityFile'
      responses:
        '201':
          description: The files have been saved to the entitiy successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  createdFiles:
                    type: array
                    items:
                      $ref: '#/components/schemas/File'
        '400':
          $ref: '#/components/responses/InvalidRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
    delete:
      operationId: deleteEntityFile
      summary: deleteEntityFile
      description: Delete files from an entity
      tags:
      - ECP
      security:
      - PortalAuth: []
      requestBody:
        description: Delete file
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DeleteEntityFile'
      responses:
        '202':
          description: The files are removed from the requested entity successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  deletedFiles:
                    type: array
                    items:
                      $ref: '#/components/schemas/EntityId'
                      description: File ID
        '400':
          $ref: '#/components/responses/InvalidRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/portal/files:
    post:
      operationId: savePortalFiles
      summary: savePortalFiles
      description: Add files to portal
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      requestBody:
        description: portal files request
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SavePortalFile'
      responses:
        '201':
          description: The files have been saved to the portal successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  createdFiles:
                    type: array
                    items:
                      $ref: '#/components/schemas/File'
        '400':
          $ref: '#/components/responses/InvalidRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/registration/identifiers:
    get:
      operationId: getRegistrationIdentifiers
      summary: getRegistrationIdentifiers
      description: Get valid attributes from entities that can be used as identifier to map contact to user on registration
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      responses:
        '200':
          description: A dictionary of identifier attributes per entity schema are returned successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    additionalProperties:
                      type: array
                      items:
                        $ref: '#/components/schemas/IdentifierAttribute'
                    example:
                      contact:
                      - label: First name
                        name: first_name
                        type: string
                      contract:
                      - label: Contract number
                        name: contract_number
                        type: string
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/user/files:
    get:
      operationId: getAllFiles
      summary: getAllFiles
      description: Fetch all documents under the related entities of a contact
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - in: query
        name: from
        schema:
          type: number
          description: Initial offset to set for the search results
          example: 0
        required: true
      - in: query
        name: size
        schema:
          type: number
          description: Size of the search results
          example: 0
        required: true
      - in: query
        name: entity_ids
        description: List of entity ids to filter the results
        schema:
          type: array
          items:
            $ref: '#/components/schemas/EntityId'
          minItems: 1
          uniqueItems: true
          example:
          - 4910096f-000a-4504-bf5a-d3774ec3032a
          - 7c9f8536-6266-42e8-a0de-c60b61aa81a7
      responses:
        '200':
          description: The files have been fetched successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  results:
                    type: array
                    items:
                      $ref: '#/components/schemas/FileItem'
                  hits:
                    type: number
                    description: Total number of files for pagination
                    example: 50
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/user/file/{id}:
    get:
      operationId: getFileById
      summary: getFileById
      description: Fetch a document with ID
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - in: path
        name: id
        schema:
          $ref: '#/components/schemas/EntityId'
        required: true
        description: The Id of a file
      responses:
        '200':
          description: The files have been fetched successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  file:
                    $ref: '#/components/schemas/FileItem'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/user/file/{id}/downloaded:
    post:
      operationId: trackFileDownloaded
      summary: trackFileDownloaded
      description: Track that user has downloaded a file
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - in: path
        name: id
        schema:
          $ref: '#/components/schemas/EntityId'
        required: true
        description: The Id of a file
      responses:
        '200':
          description: File download tracked successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  file:
                    $ref: '#/components/schemas/FileItem'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/user/files/count-by-entity:
    get:
      operationId: getFilesCountByEntity
      summary: getFileCountByEntity
      description: Fetch file counts for all ECP user related entities
      tags:
      - ECP
      security:
      - PortalAuth: []
      responses:
        '200':
          description: The file counts have been fetched successfully.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/EntityFileCount'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/billing/events:
    get:
      operationId: getBillingEvents
      summary: getBillingEvents
      description: Fetch billing events for a portal user
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - in: query
        name: from
        required: false
        schema:
          type: number
          description: Initial offset to set for the search results
          default: 0
          minimum: 0
          example: 0
      - in: query
        name: size
        required: false
        schema:
          type: number
          description: Size of the search results.
          default: 100
          minimum: 0
          maximum: 1000
          example: 100
      - name: entity_id
        in: query
        description: Entity ID to filter billing events by
        required: false
        schema:
          type: array
          items:
            $ref: '#/components/schemas/EntityId'
          minItems: 1
          uniqueItems: true
      - name: event_type
        in: query
        schema:
          type: string
          enum:
          - installment
          - reimbursement
          description: Type of billing event to filter by
      - name: paid
        in: query
        schema:
          type: boolean
          description: Filter billing events by paid status
      - name: date_after
        in: query
        schema:
          type: string
          format: date-time
          description: List billing events after this date
      - name: date_before
        in: query
        schema:
          type: string
          format: date-time
          description: List billing events before this date
      - name: sort
        in: query
        schema:
          type: string
          description: Key to sort by
          example: due_date:asc
      responses:
        '200':
          description: List billing events for all contracts/orders of specific customer
          content:
            application/json:
              schema:
                type: object
                properties:
                  results:
                    type: array
                    items:
                      $ref: '#/components/schemas/BillingEvent'
                  hits:
                    type: number
                    description: Total number of billing events for pagination
                    example: 50
  /v2/portal/billing/customers/balance:
    get:
      operationId: getCustomerBalance
      summary: getCustomerBalance
      description: Get total balance across all contracts and orders of a customer entity.
      security:
      - PortalAuth: []
      tags:
      - Balance
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Balance'
  /v2/portal/admin:login-as-user:
    post:
      operationId: loginToPortalAsUser
      summary: loginToPortalAsUser
      description: |
        Generate a token to log in to a portal impersonating a users.

        Token is valid for 5 minutes.
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      requestBody:
        description: The request body to log in to a portal impersonating a user
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                  description: The email address of the user to log in as
                  example: portal-customer@email.com
                origin:
                  $ref: '#/components/schemas/Origin'
      responses:
        '200':
          description: The token has been generated successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  login_as_token:
                    type: string
                    description: A generated login_as_token to log in to a portal impersonating a user.
  /v2/portal/entity/{schema}/access:
    post:
      operationId: triggerEntityAccessEvent
      summary: triggerEntityAccessEvent
      description: Trigger entity access event for a portal user
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - name: schema
        in: path
        required: true
        description: Entity schema
        schema:
          type: string
          example: contract
      - name: entity_id
        in: query
        required: false
        description: Entity ID
        schema:
          $ref: '#/components/schemas/EntityId'
      - name: origin
        in: query
        required: true
        description: Portal origin
        schema:
          $ref: '#/components/schemas/Origin'
          description: Origin of the portal
      responses:
        '200':
          description: The event has been triggered successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  eventId:
                    type: string
                    description: Event ID
  /v2/portal/entity:search:
    post:
      operationId: searchPortalUserEntities
      summary: searchPortalUserEntities
      description: Search all entities of a portal user
      tags:
      - ECP
      security:
      - PortalAuth: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EntitySearchParams'
      responses:
        '200':
          description: The entities is retrieved successfully for the portal user.
          content:
            application/json:
              schema:
                type: object
                properties:
                  results:
                    type: array
                    items:
                      $ref: '#/components/schemas/EntityItem'
                  hits:
                    type: number
                    description: Total number of entities for pagination
                    example: 50
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/can-trigger-portal-flow:
    post:
      operationId: canTriggerPortalFlow
      summary: canTriggerPortalFlow
      description: Returns whether the user can trigger a portal flow
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      parameters:
      - in: query
        name: origin
        required: true
        schema:
          $ref: '#/components/schemas/Origin'
        description: Origin of the portal
      requestBody:
        description: Request of trigger portal flow
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TriggerPortalFlow'
      responses:
        '200':
          description: Can Trigger Portal Flow
          content:
            application/json:
              schema:
                type: object
                properties:
                  can_trigger:
                    type: boolean
                    description: Whether the flow can be triggered
                    example: true
  /v2/portal/workflow/{workflow_id}/{step_id}:markDone:
    put:
      operationId: updateWorkflowStepAsDone
      summary: updateWorkflowStepAsDone
      description: Update a workflow step as done
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - in: path
        name: workflow_id
        required: true
        schema:
          type: string
          description: ID of a workflow
          example: 0bjwcxc827t
      - in: path
        name: step_id
        required: true
        schema:
          type: string
          description: ID of a step
          example: q1d6vcbsqvn
      responses:
        '200':
          description: Updated workflow step successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowStep'
  /v2/portal/metering/reading/photo:
    post:
      operationId: uploadMeterReadingPhoto
      summary: Upload Meter Reading Photo
      description: Uploads a Meter Reading photo and - if enabled - gives back data extracted from the photo.
      tags:
      - ECP
      security:
      - PortalAuth: []
      requestBody:
        description: Upload Meter reading photo payload.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MeterReadingPhoto'
      responses:
        '200':
          description: Meter reading photo saved successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/MeterReadingPhotoData'
        '400':
          $ref: '#/components/responses/InvalidRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/metering/reading:
    post:
      operationId: createMeterReading
      summary: Create Meter Reading
      description: Inserts a new meter reading.
      tags:
      - ECP
      security:
      - PortalAuth: []
      parameters:
      - name: override_plausibility
        in: query
        required: false
        description: Override plausibility check
        schema:
          type: boolean
          default: false
      requestBody:
        description: Meter reading payload.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MeterReading'
      responses:
        '200':
          description: Meter reading created successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/MeterReading'
        '400':
          $ref: '#/components/responses/InvalidRequestCreateMeterReading'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/public/sso/login:
    post:
      operationId: ssoLogin
      summary: ssoLogin
      description: |
        Initiate login using external SSO identity.

        Verifies the user with the issuer and matches the identity to an epilot user (or creates a new user).

        Returns parameters to be used with CUSTOM_AUTH flow against Cognito
      security:
      - ExternalOIDCAuth: []
      parameters:
      - in: query
        name: origin
        required: true
        description: Origin of the Portal
        schema:
          $ref: '#/components/schemas/Origin'
      - in: query
        name: org_id
        description: epilot organization id
        required: true
        schema:
          type: string
          example: 123
      - in: query
        name: contact_id
        description: contact id in the epilot system
        required: false
        schema:
          type: string
          format: uuid
          example: 5da0a718-c822-403d-9f5d-20d4584e0528
      tags:
      - Login
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                provider_slug:
                  $ref: '#/components/schemas/ProviderSlug'
      responses:
        '200':
          description: Cognito login parameters to use with the CUSTOM_AUTH_FLOW
          content:
            application/json:
              schema:
                type: object
                properties:
                  token:
                    $ref: '#/components/schemas/SSOLoginToken'
  /v2/portal/public/sso/redirect:
    post:
      operationId: ssoRedirect
      summary: ssoRedirect
      description: |
        Handles the redirect from the external SSO provider. Validates the authorization `code` and `state` received from the provider.
        Redirects the user to the provided `web_uri` with the validated credentials.
      security: []
      tags:
      - Public
      parameters:
      - in: query
        name: web_uri
        required: true
        description: The URI to redirect to after the SSO login
        schema:
          type: string
          example: https://customer-portal.com
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                code:
                  type: string
                  description: The code received from the external SSO provider
                  example: '123456'
                state:
                  type: string
                  description: The state received from the external SSO provider
                  example: '123456'
      responses:
        '301':
          description: Redirect to the login page with the code
          headers:
            Location:
              schema:
                type: string
                example: https://customer-portal.com/login?code=123456&state=123456
        '400':
          $ref: '#/components/responses/InvalidRequest'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/public/sso/callback:
    post:
      operationId: ssoCallback
      summary: ssoCallback
      description: |
        Handles the callback from the external SSO provider, validates the authorization `code`
        and generates a external provider token to be used with the CUSTOM_AUTH flow against Cognito.
      security: []
      tags:
      - Public
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SSOCallbackRequest'
      responses:
        '200':
          description: The token to be used with the CUSTOM_AUTH flow against Cognito
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SSOCallbackResponse'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/pages/{id}:
    parameters:
    - in: path
      name: id
      required: true
      schema:
        type: string
        format: uuid
        example: 5da0a718-c822-403d-9f5d-20d4584e0528
    get:
      operationId: getPortalPage
      summary: getPortalPage
      description: Fetch a portal page by id
      tags:
      - ECP
      - ECP Admin
      security:
      - EitherAuth: []
      responses:
        '200':
          description: The portal page has been fetched successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Page'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
    put:
      operationId: updatePortalPage
      summary: updatePortalPage
      description: Update a portal page by id
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      requestBody:
        description: The portal page to update
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PageRequest'
      responses:
        '200':
          description: The portal page has been fetched successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Page'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
    delete:
      operationId: deletePortalPage
      summary: deletePortalPage
      description: Delete a portal page by id
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      responses:
        '204':
          description: The portal page has been fetched successfully.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/pages:
    parameters:
    - in: query
      name: domain
      required: true
      schema:
        type: string
        example: customer-portal.epilot.io
        description: The domain of the portal
    get:
      operationId: getPortalPages
      summary: getPortalPages
      description: Fetch all portal pages
      tags:
      - ECP
      - ECP Admin
      security:
      - EitherAuth: []
      parameters:
      - in: query
        name: fields
        required: false
        description: The fields to include in the response
        schema:
          type: string
          example: id,slug,description
      - in: query
        name: filter
        required: false
        description: The filter to apply to the response
        schema:
          type: string
          example: schema=contract,slug=contracts
      responses:
        '200':
          description: The portal pages have been fetched successfully.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Page'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
    post:
      operationId: createPortalPage
      summary: createPortalPage
      description: Create a new portal page
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      requestBody:
        description: The portal page to create
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PageRequest'
      responses:
        '200':
          description: The portal page has been created successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Page'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/pages/{id}/blocks:
    parameters:
    - in: path
      name: id
      required: true
      schema:
        type: string
        format: uuid
        example: 5da0a718-c822-403d-9f5d-20d4584e0528
    post:
      operationId: createPortalPageBlock
      summary: createPortalPageBlock
      description: Create a new portal page block
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      requestBody:
        description: The portal page block to create
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BlockRequest'
      responses:
        '200':
          description: The portal page block has been created successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Block'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
    get:
      operationId: getPortalPageBlocks
      summary: getPortalPageBlocks
      description: Fetch all portal page blocks
      tags:
      - ECP
      - ECP Admin
      security:
      - EitherAuth: []
      responses:
        '200':
          description: The portal page blocks have been fetched successfully.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Block'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/pages/{id}/blocks/{block_id}:
    parameters:
    - in: path
      name: id
      required: true
      schema:
        type: string
        format: uuid
        example: 5da0a718-c822-403d-9f5d-20d4584e0528
    - in: path
      name: block_id
      required: true
      schema:
        type: string
        format: uuid
        example: 5da0a718-c822-403d-9f5d-20d4584e0528
    get:
      operationId: getPortalPageBlock
      summary: getPortalPageBlock
      description: Fetch a portal page block by id
      tags:
      - ECP
      - ECP Admin
      security:
      - EitherAuth: []
      responses:
        '200':
          description: The portal page block has been fetched successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Block'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
    put:
      operationId: updatePortalPageBlock
      summary: updatePortalPageBlock
      description: Update a portal page block by id
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      requestBody:
        description: The portal page block to update
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BlockRequest'
      responses:
        '200':
          description: The portal page block has been fetched successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Block'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
    delete:
      operationId: deletePortalPageBlock
      summary: deletePortalPageBlock
      description: Delete a portal page block by id
      tags:
      - ECP Admin
      security:
      - EpilotAuth: []
      responses:
        '204':
          description: The portal page block has been fetched successfully.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v2/portal/public/user/entry-point:
    get:
      operationId: getUserEntryPoint
      summary: getUserEntryPoint
      description: Get the entry point for the user
      tags:
      - Public
      security: []
      parameters:
      - in: query
        name: email
        required: true
        schema:
          type: string
          description: Email Address of the portal user
          example: user@example.com
      - in: query
        name: domain
        required: true
        schema:
          type: string
          description: Domain of the portal
          example: customer-portal.epilot.io
      responses:
        '200':
          description: Returned the entry point for the user
          content:
            application/json:
              schema:
                type: object
                required:
                - entry_point
                - user_exists
                properties:
                  user_exists:
                    type: boolean
                    description: Whether the user exists in the portal
                    example: true
                  entry_point:
                    type: string
                    description: The entry point for the user
                    enum:
                    - PASSWORD
                    - SSO
                  preferred_sso_providers:
                    type: array
                    description: The SSO providers for the user
                    items:
                      $ref: '#/components/schemas/ProviderSlug'
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  responses:
    InvalidRequest:
      description: The request could not be validated
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResp'
    Unauthorized:
      description: Could not authenticate the user
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResp'
    Forbidden:
      description: The user is not allowed to access this resource
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResp'
    ForbiddenByRule:
      description: The user is not allowed to access this resource
      content:
        application/json:
          schema:
            oneOf:
            - $ref: '#/components/schemas/ErrorResp'
            - $ref: '#/components/schemas/FailedRuleErrorResp'
    Conflict:
      description: The request conflicts with the current state of the target resource.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResp'
    ContractAssignmentConflict:
      description: Contract was found but is not assignable in its current state.
      content:
        application/json:
          schema:
            allOf:
            - $ref: '#/components/schemas/ErrorResp'
            - properties:
                reason:
                  type: string
                  description: Reason why the contract is not assignable. If the reason is "MULTIPLE", the contract is not assignable because multiple contracts were found and the business logic does not allow it.
                  enum:
                  - DRAFT
                  - MULTIPLE
              required:
              - reason
    NotFound:
      description: The specified resource was not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResp'
    InternalServerError:
      description: Internal Server Error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResp'
    ConfirmUserInvalidRequest:
      description: The request could not be validated
      content:
        application/json:
          schema:
            allOf:
            - $ref: '#/components/schemas/ErrorResp'
            - properties:
                reason:
                  type: string
                  enum:
                  - invalid_token
              required:
              - reason
    InvalidRequestCreateMeterReading:
      description: The request could not be validated
      content:
        application/json:
          schema:
            allOf:
            - $ref: '#/components/schemas/ErrorResp'
            - properties:
                reason:
                  type: string
                  enum:
                  - contract_period
                  - no_counter
                  - no_direction
                  - timestamp_future
                  - less_than_previous
                  - greater_than_subsequent
                  - meter_decommissioned
                  - plausibility_check_failed
            - oneOf:
              - properties:
                  reason:
                    enum:
                    - plausibility_check_failed
                  upper_limit:
                    type: number
                  lower_limit:
                    type: number
                required:
                - upper_limit
                - lower_limit
              - not:
                  properties:
                    reason:
                      enum:
                      - plausibility_check_failed
  securitySchemes:
    PortalAuth:
      type: http
      scheme: bearer
      description: Portal Cognito Token
    EpilotAuth:
      type: http
      scheme: bearer
      description: Epilot Bearer Token
    EitherAuth:
      type: http
      scheme: bearer
      description: Portal or Epilot Bearer Token
    AsOrganization:
      type: apiKey
      in: header
      name: x-ivy-org-id
      description: Set organization id as internal user
    ExternalOIDCAuth:
      type: http
      scheme: bearer
      description: Authorization header with id token from external OIDC provider
      bearerFormat: JWT
  schemas:
    ErrorResp:
      type: object
      properties:
        message:
          type: string
          description: Error message
    FailedRuleErrorResp:
      type: object
      properties:
        message:
          type: string
          description: Error message
        failed_rule:
          type: object
          description: Failed validation rule
    EmailTemplates:
      type: object
      description: Email templates used for authentication and internal processes
      properties:
        confirmAccount:
          $ref: '#/components/schemas/EntityId'
          description: ID of the confirmation email template upon registration
        advancedMFA:
          $ref: '#/components/schemas/EntityId'
          nullable: true
          description: ID of the advanced MFA with login link and login code
        journeySignUp:
          $ref: '#/components/schemas/EntityId'
          nullable: true
          description: ID of the email template for signing up from Journeys
        journeySignInOneTimePassword:
          $ref: '#/components/schemas/EntityId'
          nullable: true
          description: ID of the email template for OTP to sign in from Journeys
        journeyLoginOTP:
          $ref: '#/components/schemas/EntityId'
          nullable: true
          description: ID of the email template for OTP to sign in from Journeys
          deprecated: true
        forgotPassword:
          $ref: '#/components/schemas/EntityId'
          description: ID of the email template for forgot password
        invitation:
          $ref: '#/components/schemas/EntityId'
          description: ID of the email template for invitation
        onNewQuote:
          $ref: '#/components/schemas/EntityId'
          description: ID of the email template for new quote
        onMapAPendingUser:
          $ref: '#/components/schemas/EntityId'
          description: ID of the email template for mapping a pending portal user with a contact
        onDocUpload:
          $ref: '#/components/schemas/EntityId'
          description: ID of the email template for document upload
        onWorkflowStepAssigned:
          $ref: '#/components/schemas/EntityId'
          description: ID of the email template for workflow step assignment
        confirmEmailUpdate:
          $ref: '#/components/schemas/EntityId'
          description: ID of the email template for setting password while updating email
        verifyCodeToSetPassword:
          $ref: '#/components/schemas/EntityId'
          description: ID of the email template for setting password while verifying code
    DeleteEntityFile:
      type: object
      required:
      - file_entity_ids
      - entity_type
      - entity_id
      properties:
        entity_id:
          $ref: '#/components/schemas/EntityId'
        entity_type:
          type: string
          example: order
          description: Entity type
        file_entity_ids:
          type: array
          items:
            $ref: '#/components/schemas/EntityId'
          minItems: 1
          uniqueItems: true
          description: Array of file entity IDs
    SaveEntityFile:
      type: object
      required:
      - entity_id
      - entity_type
      - files
      properties:
        entity_id:
          $ref: '#/components/schemas/EntityId'
        entity_type:
          type: string
          example: order
          description: Entity type
        files:
          type: array
          items:
            type: object
            required:
            - filename
            - s3ref
            properties:
              filename:
                type: string
                example: document.pdf
                description: File name
              access_control:
                type: string
                default: private
                enum:
                - private
                - public-read
                description: Access control level for the file. Deprecated - all files are private.
                deprecated: true
              s3ref:
                type: object
                required:
                - bucket
                - key
                properties:
                  bucket:
                    type: string
                    example: 12345
                    description: S3 bucket name
                  key:
                    type: string
                    example: 12345
                    description: S3 key
    SavePortalFile:
      type: object
      required:
      - files
      - origin
      properties:
        origin:
          $ref: '#/components/schemas/Origin'
          description: Origin of the portal
        files:
          type: array
          items:
            type: object
            required:
            - file_type
            properties:
              filename:
                type: string
                example: 12345
                description: File name
              file_type:
                type: string
                example: orderRightTeaser
                description: File type
              _tags:
                type: array
                items:
                  type: string
                example: 12345
                description: Array of file tags
              s3ref:
                type: object
                required:
                - bucket
                - key
                properties:
                  bucket:
                    type: string
                    example: 12345
                    description: S3 bucket name
                  key:
                    type: string
                    example: 12345
                    description: S3 key
    ExtraSchemaAttributes:
      type: array
      items:
        type: object
        required:
        - name
        - label
        - group
        properties:
          name:
            type: string
            description: Attribute name
          label:
            type: string
            description: Attribute label
          group:
            type: string
            description: Attribute group
    Origin:
      type: string
      description: Origin of the portal
      enum:
      - END_CUSTOMER_PORTAL
      - INSTALLER_PORTAL
    AllowedFileExtensions:
      type: object
      description: Allowed file extensions for upload
      properties:
        document:
          type: array
          items:
            type: string
            example: pdf
        image:
          type: array
          items:
            type: string
            example: jpg
        spreadsheet:
          type: array
          items:
            type: string
            example: xls
        presentation:
          type: array
          items:
            type: string
            example: ppt
        audioVideo:
          type: array
          items:
            type: string
            example: mp4
        email:
          type: array
          items:
            type: string
            example: eml
        archive:
          type: array
          items:
            type: string
            example: zip
        cad:
          type: array
          items:
            type: string
            example: cad
        calendar:
          type: array
          items:
            type: string
            example: ics
        other:
          type: array
          items:
            type: string
            example: txt
      additionalProperties: false
    UpdateOnlyPortalConfigAttributes:
      type: object
      properties:
        entity_actions:
          type: array
          description: Journey actions allowed on an entity by a portal user
          items:
            type: object
            properties:
              journey_id:
                $ref: '#/components/schemas/EntityId'
              slug:
                $ref: '#/components/schemas/EntitySlug'
              action_Label:
                type: object
                properties:
                  en:
                    type: string
                  de:
                    type: string
        extensions:
          type: array
          description: Configured Portal extensions
          items:
            $ref: '#/components/schemas/ExtensionConfig'
        extension_hooks:
          type: object
          description: Configured Portal extensions hooks
          additionalProperties:
            $ref: '#/components/schemas/ExtensionHookConfig'
        default_user_to_notify:
          type: object
          description: Default 360 user to notify upon an internal notification
          properties:
            onPendingUser:
              type: array
              items:
                $ref: '#/components/schemas/AdminUser'
              description: Default admin users for pending user notification to notify
    CommonConfigAttributes:
      type: object
      required:
      - design_id
      properties:
        enabled:
          type: boolean
          description: Enable/Disable the portal access
        name:
          type: string
          description: A short name to identify your portal
          example: Installer Portal
        domain:
          type: string
          description: The URL on which the portal is accessible
          example: abc.com
        is_epilot_domain:
          type: boolean
          description: Mark true if the domain is an Epilot domain
        design_id:
          $ref: '#/components/schemas/EntityId'
          description: ID of the design used to build the portal
        self_registration_setting:
          type: string
          enum:
          - ALLOW_WITH_CONTACT_CREATION
          - ALLOW_WITHOUT_CONTACT_CREATION
          - DENY
        feature_settings:
          type: object
          description: Feature settings for the portal
          properties:
            start_page:
              type: boolean
              description: Start page feature flag
            billing:
              type: boolean
              description: Billing feature flag
            change_due_date:
              type: boolean
              description: Change due date feature flag
            new_design:
              type: boolean
              description: Enable or disable the new design for the portal
        accessToken:
          type: string
          description: Access token for the portal
        advanced_mfa:
          type: object
          properties:
            enabled:
              type: boolean
              description: Advanced MFA feature flag
        auth_settings:
          type: object
          description: Authentication settings for the portal
          properties:
            entry_point:
              type: string
              enum:
              - PASSWORD
              - SSO
            preferred_sso_providers:
              type: array
              items:
                $ref: '#/components/schemas/ProviderSlug'
        cognito_details:
          type: object
          description: AWS Cognito Pool details for the portal
          properties:
            cognito_user_pool_client_id:
              type: string
              example: 6bsd0jkgoie74k2i8mrhc1vest
              description: Cognito user pool client ID
            cognito_user_pool_arn:
              type: string
              example: arn:aws:cognito-idp:us-east-1:123412341234:userpool/us-east-1_123412341
              description: Cognito user pool ARN
            cognito_user_pool_id:
              type: string
              example: eu-central-1_CUEQRNbUb
              description: Cognito user pool ID
            password_policy:
              type: object
              description: Password policy for the portal
              properties:
                minimum_length:
                  type: integer
                  example: 8
                  description: Minimum password length
                require_lowercase:
                  type: boolean
                  example: true
                  description: Require lowercase characters
                require_uppercase:
                  type: boolean
                  example: true
                  description: Require uppercase characters
                require_numbers:
                  type: boolean
                  example: true
                  description: Require numbers
                require_symbols:
                  type: boolean
                  example: true
                  description: Require symbols
        config:
          type: string
          description: Stringified object with configuration details
        contact_identifiers:
          type: array
          description: Deprecated. Use registration_identifiers instead.
          deprecated: true
          items:
            type: string
          example:
          - email
          - last_name
        approval_state_attributes:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
          example:
            contact:
            - name
            - address
            contract:
            - installment_amount
        email_templates:
          $ref: '#/components/schemas/EmailTemplates'
        images:
          type: object
          description: Teaser & Banner Image web links
          properties:
            orderLeftTeaser:
              type: string
              nullable: true
              example: https://epilot-bucket.s3.eu-central-1.amazonaws.com/12344/6538fddb-f0e9-4f0f-af51-6e57891ff20a/order-left-teaser.jpeg
              description: URL of the order left teaser image
            orderRightTeaser:
              type: string
              nullable: true
              example: https://epilot-bucket.s3.eu-central-1.amazonaws.com/12344/6538fddb-f0e9-4f0f-af51-6e57891ff20a/order-right-teaser.jpeg
              description: URL of the order right teaser image
            welcomeBanner:
              type: string
              nullable: true
              example: https://epilot-bucket.s3.eu-central-1.amazonaws.com/12344/6538fddb-f0e9-4f0f-af51-6e57891ff20a/welcome-banner.jpeg
              description: URL of the welcome banner image
        entity_identifiers:
          type: object
          description: Identifiers used to identify an entity by a portal user. Deprecated. Use contract_identifiers instead.
          deprecated: true
          properties:
            type:
              type: object
              properties:
                isEnabled:
                  type: boolean
                  description: Enable/Disable the entity identifier
                attributes:
                  type: array
                  description: Attributes used to identify an entity
                  items:
                    type: string
                    example: contract_number
        contract_identifiers:
          type: array
          description: Identifiers to identify a contract by a portal user.
          items:
            $ref: '#/components/schemas/ContractIdentifier'
          example:
          - name: email
            schema: contact
          - name: last_name
            schema: contact
          - name: contract_number
            schema: contract
        contract_selector_config:
          type: object
          description: Configuration for contract selector in the portal
          properties:
            show_inactive:
              type: boolean
              description: Whether to show inactive contracts in the selector
            title_path:
              type: string
              description: Path to the property to use as the contract title
        registration_identifiers:
          type: array
          description: Identifiers to identify a contact of a portal user during the registration.
          items:
            $ref: '#/components/schemas/ContractIdentifier'
          example:
          - name: last_name
            schema: contact
          - name: contract_number
            schema: contract
        triggered_journeys:
          type: array
          description: Journeys automatically opened on a portal user action
          items:
            type: object
            properties:
              trigger_name:
                type: string
                enum:
                - FIRST_LOGIN
                - ACCEPT_ORDER
                - DECLINE_ORDER
              journey_id:
                $ref: '#/components/schemas/EntityId'
        entity_edit_rules:
          type: array
          description: Rules for editing an entity by a portal user
          items:
            type: object
            properties:
              slug:
                $ref: '#/components/schemas/EntitySlug'
              attribute:
                type: string
                example: first_name
              rule_type:
                type: string
                enum:
                - cadence
                - relative_to_current_value
                - days_before_date
                - overdue_payments
              cadence_period_type:
                type: string
                enum:
                - days
                - weeks
                - months
              cadence_period:
                type: number
                example: 1
              changes_allowed:
                type: integer
                example: 1
              grace_period:
                type: integer
                example: 1
              allowed_increment:
                type: string
                example: 10%
              allowed_decrement:
                type: string
                example: 10%
              number_of_days_before_restriction:
                type: integer
                example: 10
        allowed_file_extensions:
          $ref: '#/components/schemas/AllowedFileExtensions'
        prevent_search_engine_indexing:
          type: boolean
          description: Prevent indexing by search engines
        meter_reading_grace_period:
          type: number
          description: Grace period in days for meter readings
        inactive_contract_cutoff_years:
          type: number
          description: Number of years to look back for showing inactive contracts in the portal
        pages:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/Page'
    UpsertPortalConfig:
      allOf:
      - $ref: '#/components/schemas/UpdateOnlyPortalConfigAttributes'
      - $ref: '#/components/schemas/CommonConfigAttributes'
      required:
      - config
      - design_id
      - feature_settings
    PortalConfig:
      allOf:
      - $ref: '#/components/schemas/CommonConfigAttributes'
      - properties:
          id:
            type: string
            example: 12345
            description: ID of the organization
            deprecated: true
          organization_id:
            type: string
            example: 12345
            description: ID of the organization
          origin:
            $ref: '#/components/schemas/Origin'
          org_settings:
            type: object
            description: Organization settings
            properties:
              canary:
                type: object
                description: Canary feature flag
                properties:
                  enabled:
                    type: boolean
                    description: Enable/Disable the canary feature
              notracking:
                type: object
                description: Disable Advanced Usage Metrics
                properties:
                  enabled:
                    type: boolean
                    description: Disable browser-side scripts that track advanced usage metrics
          feature_flags:
            type: object
            description: Feature flags for the portal
            additionalProperties:
              type: boolean
          grants:
            type: array
            description: Permissions granted to a portal user while accessing entities
            items:
              $ref: '#/components/schemas/Grant'
          identity_providers:
            type: array
            items:
              $ref: '#/components/schemas/ProviderPublicConfig'
    UpsertPortalWidget:
      type: object
      required:
      - widgets
      properties:
        widgets:
          type: array
          items:
            $ref: '#/components/schemas/PortalWidget'
    WidgetBase:
      type: object
      required:
      - id
      - type
      - listIndex
      properties:
        id:
          type: string
        type:
          type: string
          enum:
          - ACTION_WIDGET
          - CONTENT_WIDGET
          - ENTITY_WIDGET
          - TEASER_WIDGET
          - DOCUMENT_WIDGET
          - PAYMENT_WIDGET
          - METER_READING_WIDGET
          - METER_CHART_WIDGET
          - CAMPAIGN_WIDGET
        listIndex:
          type: integer
          description: Index of the widget in the list, used for ordering (left or right)
        headline:
          type: object
          properties:
            en:
              type: string
            de:
              type: string
        subHeadline:
          type: object
          properties:
            en:
              type: string
            de:
              type: string
    EntityWidget:
      allOf:
      - $ref: '#/components/schemas/WidgetBase'
      - type: object
        properties:
          schema:
            type: string
    MeterReadingWidget:
      allOf:
      - $ref: '#/components/schemas/WidgetBase'
      - type: object
        properties:
          schema:
            type: string
    MeterChartWidget:
      allOf:
      - $ref: '#/components/schemas/WidgetBase'
      - type: object
        properties:
          schema:
            type: string
    WidgetAction:
      type: object
      properties:
        _id:
          type: string
        type:
          type: string
          enum:
          - link
          - journey
        label:
          type: object
          properties:
            en:
              type: string
            de:
              type: string
        url:
          type: string
        rules:
          type: array
          items:
            type: object
            properties:
              attribute:
                type: string
              attribute_value:
                type: string
              entity:
                type: string
            required:
            - attribute
            - attribute_value
            - entity
      required:
      - type
      - label
      - url
      - _id
    ActionWidget:
      allOf:
      - $ref: '#/components/schemas/WidgetBase'
      - type: object
        properties:
          actions:
            type: array
            items:
              $ref: '#/components/schemas/WidgetAction'
    TeaserWidget:
      allOf:
      - $ref: '#/components/schemas/WidgetBase'
      - type: object
        properties:
          imageUrl:
            type: string
          button:
            type: object
            properties:
              label:
                type: object
                properties:
                  en:
                    type: string
                  de:
                    type: string
              url:
                type: string
    ContentWidget:
      allOf:
      - $ref: '#/components/schemas/WidgetBase'
      - type: object
        properties:
          content:
            type: string
    DocumentWidget:
      allOf:
      - $ref: '#/components/schemas/WidgetBase'
    PaymentWidget:
      allOf:
      - $ref: '#/components/schemas/WidgetBase'
    CampaignWidget:
      allOf:
      - $ref: '#/components/schemas/TeaserWidget'
      - type: object
        properties:
          campaign_id:
            type: string
            description: ID of the campaign
    PortalWidget:
      anyOf:
      - $ref: '#/components/schemas/EntityWidget'
      - $ref: '#/components/schemas/ContentWidget'
      - $ref: '#/components/schemas/ActionWidget'
      - $ref: '#/components/schemas/TeaserWidget'
      - $ref: '#/components/schemas/DocumentWidget'
      - $ref: '#/components/schemas/PaymentWidget'
      - $ref: '#/components/schemas/MeterReadingWidget'
      - $ref: '#/components/schemas/MeterChartWidget'
      - $ref: '#/components/schemas/CampaignWidget'
    ContactCountRequest:
      type: object
      required:
      - contactIdentifiers
      - orgId
      properties:
        orgId:
          type: string
          example: 728
          description: ID of the organization
        contactIdentifiers:
          type: object
          description: Identifiers to identify a contact
          additionalProperties:
            type: string
    ContactExistsRequest:
      type: object
      required:
      - registration_identifiers
      - org_id
      properties:
        org_id:
          type: string
          example: 728
          description: ID of the organization
        registration_identifiers:
          type: object
          description: Identifier-value pairs per schema to identify a contact of a portal user during the resgistration
          additionalProperties:
            type: object
            additionalProperties:
              type: string
          example:
            contact:
              email: john.doe@example.com
            contract:
              contract_number: '123456'
    UserRequest:
      type: object
      properties:
        email:
          type: string
          example: testemail921@yopmail.com
          description: User's email address
        first_name:
          type: string
          example: John
          description: First Name of the portal user
        last_name:
          type: string
          example: Doe
          description: Last Name of the portal user
        contactId:
          $ref: '#/components/schemas/EntityId'
          description: ID of the contact
    CreateUserRequest:
      required:
      - email
      - orgId
      - password
      allOf:
      - $ref: '#/components/schemas/UserRequest'
      - properties:
          orgId:
            type: string
            example: 728
            description: ID of the organization
          password:
            type: string
            example: 124n$aAJs*d41h4
            description: User's password
          contactIdentifiers:
            type: object
            description: Deprecated. Use registration_identifiers instead.
            deprecated: true
            additionalProperties:
              type: string
          registration_identifiers:
            type: object
            description: Identifier-value pairs per schema to identify a contact of a portal user during the resgistration
            additionalProperties:
              type: object
              additionalProperties:
                type: string
            example:
              contact:
                email: john.doe@example.com
              contract:
                contract_number: '123456'
    OrganizationSettings:
      type: object
      properties:
        automation_entity_mapping:
          type: object
          properties:
            enabled:
              type: boolean
              description: Enable/Disable automation entity mapping
        automation_preview:
          type: object
          properties:
            enabled:
              type: boolean
              description: Enable/Disable automation preview
        central_inbox_preview_setting:
          type: object
          properties:
            enabled:
              type: boolean
              description: Enable/Disable central inbox preview setting
        contracts_preview_setting:
          type: object
          properties:
            enabled:
              type: boolean
              description: Enable/Disable contracts preview setting
        disable_ivy:
          type: object
          properties:
            enabled:
              type: boolean
              description: Enable/Disable Ivy
        double_opt_in:
          type: object
          properties:
            enabled:
              type: boolean
              description: Enable/Disable double opt-in
        ecommerce_catalog_preview:
          type: object
          properties:
            enabled:
              type: boolean
              description: Enable/Disable ecommerce catalog preview
        ecommerce_opportunities_preview:
          type: object
          properties:
            enabled:
              type: boolean
              description: Enable/Disable ecommerce opportunities preview
        ecommerce_preview:
          type: object
          properties:
            enabled:
              type: boolean
              description: Enable/Disable ecommerce preview
        end_customer_portal:
          type: object
          properties:
            enabled:
              type: boolean
              description: Enable/Disable end customer portal
        installer_portal:
          type: object
          properties:
            enabled:
              type: boolean
              description: Enable/Disable installer portal
        entity_schema_builder:
          type: object
          properties:
            enabled:
              type: boolean
              description: Enable/Disable entity schema builder
        logic_editor_preview:
          type: object
          properties:
            enabled:
              type: boolean
              description: Enable/Disable logic editor preview
        new_navigation:
          type: object
          properties:
            enabled:
              type: boolean
              description: Enable/Disable new navigation
        partnering:
          type: object
          properties:
            enabled:
              type: boolean
              description: Enable/Disable partnering
        product-availability:
          type: object
          properties:
            enabled:
              type: boolean
              description: Enable/Disable product availability
        sso:
          type: object
          properties:
            enabled:
              type: boolean
              description: Enable/Disable single sign-on (SSO)
        submission_preview:
          type: object
          properties:
            enabled:
              type: boolean
              description: Enable/Disable submission preview
        user_roles_preview:
          type: object
          properties:
            enabled:
              type: boolean
              description: Enable/Disable user roles preview
    AuthConfig:
      type: object
      properties:
        user_pool_id:
          type: string
          example: eu-central-1_CUEQRNbUb
          description: AWS Cognito User Pool ID
        user_pool_client_id:
          type: string
          example: 6bsd0jkgoie74k2i8mrhc1vest
          description: AWS Cognito User Pool Client ID
        user_pool_identity_pool_id:
          type: string
          example: eu-central-1:a63af1f7-ab86-4ab5-a0eb-f461cb37c2b1
          description: AWS Cognito User Pool Identity Pool ID
        portal_id:
          type: string
          example: 7h2hwdj7hhjsdcjkq03eidna3ep
          description: Portal ID
      required:
      - user_pool_id
      - user_pool_client_id
      - portal_id
    Exists:
      type: object
      required:
      - exists
      properties:
        exists:
          type: boolean
          description: Indicate whether the item exists
        active:
          type: boolean
          description: Indicate whether the item is active
      example:
        exists: true
        active: false
    EntitySlug:
      description: URL-friendly identifier for the entity schema
      type: string
      enum:
      - contact
      - contract
      - file
      - order
      - opportunity
      - product
      - price
      - meter
      - meter_counter
      example: contact
    EntityId:
      type: string
      format: uuid
      description: Entity ID
      example: 5da0a718-c822-403d-9f5d-20d4584e0528
    BaseEntity:
      type: object
      properties:
        _id:
          $ref: '#/components/schemas/EntityId'
          description: Entity ID
          example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
        _title:
          type: string
          description: Title of the entity
          example: Example Entity
        _org:
          type: string
          description: Organization ID the entity belongs to
          example: '123'
        _tags:
          type: array
          items:
            type: string
          description: Array of entity tags
          example:
          - example
          - mock
        _created_at:
          type: string
          format: date-time
          description: Creation timestamp of the entity
          example: '2021-02-09T12:41:43.662Z'
        _updated_at:
          type: string
          format: date-time
          description: Last update timestamp of the entity
          example: '2021-02-09T12:41:43.662Z'
      required:
      - _id
      - _title
      - _org
      - _created_at
      - _updated_at
    Schema:
      type: object
      properties:
        slug:
          type: string
          description: Slug of the schema
          example: contact
      additionalProperties: true
    Entity:
      type: object
      properties: {}
      additionalProperties: true
    EntityItem:
      allOf:
      - $ref: '#/components/schemas/BaseEntity'
      - $ref: '#/components/schemas/Entity'
      - type: object
        required:
        - _schema
        properties:
          _schema:
            $ref: '#/components/schemas/EntitySlug'
            description: Entity schema identifier
    PortalUser:
      description: The portal user entity
      allOf:
      - $ref: '#/components/schemas/BaseEntity'
      - $ref: '#/components/schemas/Entity'
      - type: object
        required:
        - _schema
        properties:
          _schema:
            type: string
            enum:
            - portal_user
    Contact:
      description: The mapped contact of the portal user
      allOf:
      - $ref: '#/components/schemas/BaseEntity'
      - $ref: '#/components/schemas/Entity'
      - type: object
        required:
        - _schema
        properties:
          _schema:
            type: string
            enum:
            - contact
    WorfklowIdentifier:
      description: Workflow identifier object
      allOf:
      - type: object
        properties:
          defition_id:
            type: string
          name:
            type: string
    Meter:
      description: The meter entity
      allOf:
      - $ref: '#/components/schemas/BaseEntity'
      - $ref: '#/components/schemas/Entity'
      - type: object
        required:
        - _schema
        properties:
          _schema:
            type: string
            enum:
            - meter
    Order:
      description: The order entity
      allOf:
      - $ref: '#/components/schemas/BaseEntity'
      - $ref: '#/components/schemas/Entity'
      - type: object
        required:
        - _schema
        properties:
          _schema:
            type: string
            enum:
            - order
    Opportunity:
      description: The opportunity entity
      allOf:
      - $ref: '#/components/schemas/BaseEntity'
      - $ref: '#/components/schemas/Entity'
      - type: object
        required:
        - _schema
        properties:
          _schema:
            type: string
            enum:
            - opportunity
    Contract:
      description: The contract entity
      allOf:
      - $ref: '#/components/schemas/BaseEntity'
      - $ref: '#/components/schemas/Entity'
      - type: object
        properties:
          contract_name:
            type: string
            description: The name of the contract.
            example: Grid Contract
          contract_number:
            type: string
            description: The unique identifier of the contract.
            example: '12345'
          status:
            type: string
            enum:
            - draft
            - in_approval_process
            - approved
            - active
            - deactivated
            - revoked
            - terminated
            - expired
            default: draft
            description: The status of the contract.
            example: approved
          description:
            type: string
            description: A brief description of the contract.
            example: This contract is for the supply of widgets.
          account_number:
            type: string
            description: The account number associated with the contract.
            example: '67890'
          branch:
            type: string
            enum:
            - power
            - gas
            - water
            - waste_water
            - district_heating
            description: The branch associated with the contract.
            example: power
          billing_address:
            type: string
            description: The billing address associated with the contract.
            example: 123 Main St, Anytown
          delivery_address:
            type: string
            description: The delivery address associated with the contract.
            example: 456 Elm St, Anytown
          additional_addresses:
            type: string
            description: Any additional addresses associated with the contract.
            example: 789 Oak St, Anytown
          termination_date:
            type: string
            description: The date on which the contract was terminated.
            example: '2022-01-01'
          termination_reason:
            type: string
            description: The reason for the termination of the contract.
            example: Non-payment
          billing_period:
            type: string
            enum:
            - weekly
            - monthly
            - every_quarter
            - every_6_months
            - yearly
            default: weekly
            description: The billing period associated with the contract.
            example: monthly
          billing_duration_amount:
            type: number
            minimum: 0
            description: The duration of the billing period.
            example: 30
          renewal_duration_amount:
            type: number
            minimum: 0
            description: The duration of the renewal period.
            example: 365
          renewal_duration_unit:
            type: string
            enum:
            - weeks
            - months
            - years
            default: months
            description: The unit of time for the renewal period.
            example: years
          notice_time_amount:
            type: number
            minimum: 0
            description: The amount of notice required for termination of the contract.
            example: 30
          notice_time_unit:
            type: string
            enum:
            - weeks
            - months
            - years
            default: months
            description: The unit of time for the notice period.
            example: months
          start_date:
            type: string
            description: The start date of the contract.
            example: '2021-01-01'
          billing_due_day:
            type: integer
            description: Defines the day of the month in which the installments are due.
            minimum: 1
            maximum: 31
            example: 2
          installment_amount:
            type: integer
            description: Set amount for installments in cents. (precision 2)
            example: 10050
          balance:
            type: integer
            description: Current balance of the contract in cents. (precision 2)
            example: 8990
          balance_currency:
            $ref: '#/components/schemas/Currency'
    File:
      description: The file entity
      allOf:
      - $ref: '#/components/schemas/BaseEntity'
      - $ref: '#/components/schemas/Entity'
      - type: object
        required:
        - _schema
        properties:
          _schema:
            type: string
            enum:
            - file
    Product:
      description: The product entity
      allOf:
      - $ref: '#/components/schemas/BaseEntity'
      - $ref: '#/components/schemas/Entity'
      - type: object
        required:
        - _schema
        properties:
          _schema:
            type: string
            enum:
            - product
    ActivityId:
      type: string
      format: ulid
      description: See https://github.com/ulid/spec
      example: 01F130Q52Q6MWSNS8N2AVXV4JN
    ActivityCallerContext:
      type: object
      additionalProperties: true
      properties:
        PortalAuth:
          type: object
          properties:
            token:
              type: object
              properties:
                sub:
                  type: string
                  example: 8cc73157-3dc4-47f3-b163-d3a5039bba72
                email:
                  type: string
                  example: john@doe.com
                cognito:username:
                  type: string
                  example: john@doe.com
                custom:portal_user_id:
                  $ref: '#/components/schemas/EntityId'
                custom:contact_entity_id:
                  $ref: '#/components/schemas/EntityId'
              example:
                cognito:username: john@doe.com
                custom:contact_entity_id: 7579d22f-9400-41d1-b460-04730239ee91
                custom:org_id: '123456'
                custom:origin: END_CUSTOMER_PORTAL
                custom:portal_user_id: 06c78f9d-af75-4483-893d-a3fad524400f
                email: john@doe.com
                email_verified: true
                exp: 1694693219
                iat: 1694689619
                sub: 8cc73157-3dc4-47f3-b163-d3a5039bba72
    Activity:
      type: object
      properties:
        type:
          type: string
          example: MyCustomActivity
        title:
          type: string
          description: Title for activity. Supports handlebars syntax.
          example: My custom activity
        message:
          type: string
          description: Message for activity. Supports handlebars syntax.
          example: '{{caller}} did something with {{entity payload.entity.id}}.'
        payload:
          type: object
          properties: {}
          additionalProperties: true
          example:
            entity:
              id: 3fa85f64-5717-4562-b3fc-2c963f66afa6
              schema: contact
      required:
      - type
      - title
      - message
    EntityEditRule:
      type: object
      properties:
        slug:
          $ref: '#/components/schemas/EntitySlug'
        attribute:
          type: string
        rule_type:
          type: string
        cadence_period_type:
          type: string
        changes_allowed:
          type: number
        cadence_period:
          type: number
        allowed_decrement:
          type: string
        allowed_increment:
          type: string
        number_of_days_before_restriction:
          type: number
        grace_period:
          type: number
    ActivityItem:
      allOf:
      - type: object
        properties:
          _id:
            $ref: '#/components/schemas/ActivityId'
          timestamp:
            type: string
            format: date-time
      - $ref: '#/components/schemas/Activity'
      - type: object
        properties:
          payload:
            type: object
            properties:
              entity:
                type: object
                properties:
                  id:
                    $ref: '#/components/schemas/EntityId'
                  schema:
                    type: string
              caller:
                $ref: '#/components/schemas/ActivityCallerContext'
    FileItem:
      allOf:
      - $ref: '#/components/schemas/File'
      - type: object
        properties:
          filename:
            type: string
            example: document.pdf
          access_control:
            type: string
            default: private
            enum:
            - private
            - public-read
          file_date:
            type: string
            format: date-time
            description: The date used for sorting the file
            example: '2021-02-09T12:41:43.662Z'
          public_url:
            description: Direct URL for file (public only if file access control is public-read)
            type: string
            format: url
            example: https://epilot-files-prod.s3.eu-central-1.amazonaws.com/123/4d689aeb-1497-4410-a9fe-b36ca9ac4389/document.pdf
          type:
            description: Human readable type for file
            type: string
            enum:
            - document
            - document_template
            - text
            - image
            - video
            - audio
            - spreadsheet
            - presentation
            - font
            - archive
            - application
            - unknown
          mime_type:
            type: string
            description: MIME type of the file
            example: application/pdf
          _relations:
            type: array
            items:
              type: object
              properties:
                entity_id:
                  $ref: '#/components/schemas/EntityId'
                  description: The ID of the parent entity
                _schema:
                  $ref: '#/components/schemas/EntitySlug'
                _title:
                  type: string
                  description: The title of the parent entity
                  example: Opportunity ABC
          is_new:
            type: boolean
            description: Indicate whether the user has not seen/downloaded the file before
    EntityFileCount:
      type: object
      required:
      - entity_id
      - file_count
      - _schema
      properties:
        entity_id:
          $ref: '#/components/schemas/EntityId'
          description: The ID of the parent entity
        _schema:
          $ref: '#/components/schemas/EntitySlug'
        _title:
          type: string
          description: The title of the parent entity
          example: Opportunity ABC
        file_count:
          type: integer
          description: Number of files associated with the entity and shared with portal user
          example: 2
    AdminUser:
      type: object
      additionalProperties: true
      properties:
        type:
          type: string
          example: user
          nullable: true
        user_id:
          type: string
          example: '123456'
        display_name:
          type: string
          example: John
          nullable: true
        image_uri:
          type: object
          nullable: true
          properties:
            original:
              type: string
              example: https://fuafjvoHKsu.cloudimg.io/v7/e-mage-sam-bucket-dev.s3.eu-central-1.amazonaws.com/files/fuafjvoHKsudhfagweucjasdvga/original
              nullable: true
            thumbnail_32:
              type: string
              example: https://fuafjvoHKsu.cloudimg.io/v7/e-mage-sam-bucket-dev.s3.eu-central-1.amazonaws.com/files/fuafjvoHKsudhfagweucjasdvga/original?w=32&h=32
              nullable: true
            thumbnail_64:
              type: string
              example: https://fuafjvoHKsu.cloudimg.io/v7/e-mage-sam-bucket-dev.s3.eu-central-1.amazonaws.com/files/fuafjvoHKsudhfagweucjasdvga/original?w=64&h=64
              nullable: true
            key:
              type: string
              example: fuafjvoHKsudhfagweucjasdvga
              nullable: true
        org_id:
          type: string
          example: '123'
        email:
          type: string
          example: j.doe@epilot.cloud
          nullable: true
        phone:
          type: string
          example: 12345 67890
          nullable: true
    Grant:
      type: object
      properties:
        action:
          type: string
          example: entity-read
          description: Action for granting permission
        resource:
          type: string
          example: entity:123:contact:f7c22299-ca72-4bca-8538-0a88eeefc947
          description: Resource for granting permission
        effect:
          type: string
          default: allow
          enum:
          - allow
          - deny
          description: Effect of the permission
      required:
      - action
    ActionLabel:
      type: object
      properties:
        en:
          type: string
          nullable: true
        de:
          type: string
          nullable: true
    Rule:
      type: object
      properties:
        entity:
          type: string
          nullable: true
        attribute:
          type: string
          nullable: true
        attribute_value:
          type: string
          nullable: true
    JourneyActions:
      type: object
      properties:
        journey_id:
          type: string
          nullable: true
        action_label:
          type: object
          $ref: '#/components/schemas/ActionLabel'
          nullable: true
        slug:
          type: string
          nullable: true
        rules:
          type: array
          items:
            $ref: '#/components/schemas/Rule'
          nullable: true
    ExternalLink:
      type: object
      properties:
        id:
          type: string
          description: Unique identifier for the external link
        label:
          type: object
          additionalProperties:
            type: string
        type:
          type: string
          enum:
          - link
          - journey
          - seamless
        link:
          type: string
          description: The URL of the external link
        rules:
          type: array
          items:
            type: object
        attribute:
          type: string
          description: Attribute associated with the link
        entity:
          type: string
          description: Entity associated with the link
        attribute_value:
          type: string
          description: Attribute value for the link
        icon:
          type: object
          description: Configuration of the icon for the external link
          properties:
            name:
              type: string
              description: The name of the icon
            color:
              type: string
              description: The color of the icon
            size:
              type: integer
              description: Size of the icon in pixels
        extension_link_id:
          type: array
          items:
            type: string
          description: Seamless link identifier in a form of [extensionId, linkId]
      required:
      - id
      - label
      - type
      - link
    WorkflowExecution:
      type: object
      properties: {}
      additionalProperties: true
      example:
        id: 8gja72h6kas6h
        name: Lead Qualification
        trigger: MANUAL
        status: STARTED
        creationTime: '2021-04-27T12:01:13.000Z'
        lastUpdateTime: '2021-04-27T12:01:13.000Z'
        dueDate: '2021-04-27T12:01:13.000Z'
        assignedTo:
        - '252'
        - '29052'
        flow:
        - id: sectionId1
          name: Initial Information Gathering
          steps:
          - id: sada5641f3a21
            name: Call client and confirm address and product
            status: ASSIGNED
            assignedTo:
            - '11'
          - id: sada5641f3a22
            name: Check product availability
            status: UNASSIGNED
          - id: sada5641f3a23
            name: Send email confirming contact with the client
            status: SKIPPED
        - id: firstLevelStepId1
          name: Print and send catalog
          status: SKIPPED
          dueDate: '2023-01-15T20:00:00'
    WorkflowStep:
      type: object
      properties: {}
      additionalProperties: true
      example:
        startedTime: '2024-01-12T13:29:55.942Z'
        requirements: []
        created: '2023-10-20T17:41:10.256Z'
        executionType: MANUAL
        assignedToInProgress: '-'
        sectionId: lzxsw2sblj7
        type: STEP
        entityRefId: q1d6vcbsqvn
        assignedTo:
        - '10014532'
        lastUpdated: '2024-01-13T05:18:43.838Z'
        ecp: {}
        userIds: []
        name: Hinterlege den vereinbarten LIC Termin
        id: q1d6vcbsqvn
        definitionId: 9UjHKq
        status: COMPLETED
        manuallyCreated: false
        enabled: true
        completedTime: '2024-01-13T05:18:43.827Z'
    BaseBillingEvent:
      allOf:
      - $ref: '#/components/schemas/BaseEntity'
      - $ref: '#/components/schemas/Entity'
      description: A base billing event to be inherited by all billing events.
      type: object
      required:
      - type
      - contract
      additionalProperties: true
      properties:
        billing_amount:
          type: integer
          description: Amount to be paid in cents i.e. precision 2
          example: 10050
        billing_amount_decimal:
          type: string
          description: Amount to be paid in cents in decimal string representation
          example: '100.50'
        billing_currency:
          $ref: '#/components/schemas/Currency'
        external_id:
          type: string
          description: Unique identifier for event, used to reference the event to a 3rd party resource such as a SAP Installment.
          example: d4fb2a4e-3f74-4fc4-8fba-6fdaaaa3b08e
        contract:
          type: object
          properties:
            $relation:
              type: array
              items:
                type: object
                properties:
                  entity_id:
                    type: string
                    description: Entity ID for the related contract.
                    example: f589786b-3024-43cd-9cb3-5a3c953f2896
    InstallmentEvent:
      description: An entity that describes an installment billing event.
      allOf:
      - $ref: '#/components/schemas/BaseBillingEvent'
      - type: object
        properties:
          type:
            type: string
            enum:
            - installment
            description: Type of the billing event.
            example: installment
          due_date:
            type: string
            format: date
            description: Date on which the installment is due.
          paid_date:
            type: string
            format: date
            description: Date on which the installment is paid by the customer.
        required:
        - due_date
      properties:
        billing_amount_decimal:
          type: string
          description: Amount to be paid in cents in decimal string representation
          example: '100.50'
    ReimbursementEvent:
      description: An entity that describes a reimbursement billing event.
      allOf:
      - $ref: '#/components/schemas/BaseBillingEvent'
      - type: object
        properties:
          type:
            type: string
            enum:
            - reimbursement
            description: Type of the billing event.
            example: reimbursement
          due_date:
            type: string
            format: date
            description: Date on which the installment is due.
          paid_date:
            type: string
            format: date
            description: Date on which the customer is reimbursed.
    BillingEvent:
      description: An entity that describes a billing event such as a future installment or a reimbursement back to the customer.
      oneOf:
      - $ref: '#/components/schemas/InstallmentEvent'
      - $ref: '#/components/schemas/ReimbursementEvent'
      properties:
        billing_amount_decimal:
          type: string
          description: Amount to be paid in cents in decimal string representation
          example: '100.50'
    Balance:
      type: object
      properties:
        balance:
          type: integer
          description: Current balance of the customer in cents. (precision 2)
          example: 8990
        balance_decimal:
          type: number
          description: Current balance of the customer in decimal string representation.
          example: '89.90'
        balance_currency:
          $ref: '#/components/schemas/Currency'
    Currency:
      type: string
      description: Currency code in ISO 4217 format
      example: EUR
    EntitySearchParams:
      type: object
      properties:
        slug:
          $ref: '#/components/schemas/EntitySlug'
        sort:
          type: string
          example: _created_at:desc
        from:
          type: integer
          minimum: 0
          default: 0
        size:
          type: integer
          minimum: 0
          default: 10
          description: Max search size is 1000 with higher values defaulting to 1000
        hydrate:
          type: boolean
          description: When true, enables entity hydration to resolve nested $relation & $relation_ref references in-place.
          default: false
        fields:
          type: array
          description: List of entity fields to include in search results
          items:
            type: string
          example:
          - _id
          - _title
          - first_name
      required:
      - slug
    IdentifierAttribute:
      type: object
      properties:
        label:
          type: string
          description: Label attribute
        name:
          type: string
          description: Name of the attribute
        type:
          type: string
          description: Type of the secondary attribute
    RegistrationIdentifier:
      type: object
      properties:
        name:
          type: string
          description: Name of the identifier/attribute
        schema:
          $ref: '#/components/schemas/EntitySlug'
    ContractIdentifier:
      type: object
      properties:
        name:
          type: string
          description: Name of the identifier/attribute
        schema:
          $ref: '#/components/schemas/EntitySlug'
    AcceptanceDecision:
      type: object
      properties:
        decision:
          type: string
          enum:
          - accept
          - decline
          description: Acceptance decision
      required:
      - decision
      additionalProperties: false
    TriggerPortalFlow:
      type: object
      properties:
        activity_id:
          type: string
          description: Id of the activity
          example: 01F130Q52Q6MWSNS8N2AVXV4JN
        ecp_config:
          type: object
          properties:
            file_config:
              type: object
              properties:
                shared_with_end_customer:
                  type: boolean
                  description: Indicate whether the file is shared with the end customer
                _tags:
                  type: array
                  items:
                    type: string
                  description: Array of entity tags
                  example:
                  - example
                  - mock
    ExtensionConfig:
      type: object
      properties:
        id:
          type: string
          description: Name of the extension
        status:
          type: string
          enum:
          - installed
          - enabled
          description: Status of the extension
          default: installed
        options:
          type: object
          description: Extension option values.
          additionalProperties:
            type: string
          default: {}
      required:
      - id
      - status
    ExtensionHookConfig:
      type: object
      nullable: true
      properties:
        hook_id:
          type: string
          description: The ID of the hook that is being configured.
        app_id:
          type: string
          description: The ID of the app that is being hooked into.
    PublicExtensionCapabilities:
      type: object
      properties:
        consumptionDataRetrieval:
          type: array
          items:
            $ref: '#/components/schemas/DataRetrievalItem'
        priceDataRetrieval:
          type: array
          items:
            $ref: '#/components/schemas/DataRetrievalItem'
        costDataRetrieval:
          type: array
          items:
            $ref: '#/components/schemas/DataRetrievalItem'
        contractIdentification:
          type: object
          properties:
            extension:
              $ref: '#/components/schemas/PublicExtensionDetails'
            hook:
              $ref: '#/components/schemas/PublicContractIdentificationDetails'
    DataRetrievalItem:
      type: object
      properties:
        extension:
          $ref: '#/components/schemas/PublicExtensionDetails'
        hook:
          $ref: '#/components/schemas/PublicDataRetrievalHookDetails'
    PublicExtensionDetails:
      type: object
      properties:
        id:
          type: string
          description: Identifier of the extension.
        name:
          type: object
          properties:
            en:
              type: string
              description: Name of the extension in English.
          additionalProperties:
            type: string
            description: Name of the extension in some other language denoted by ISO 3166-1 alpha-2 code.
          required:
          - en
    PublicDataRetrievalHookDetails:
      type: object
      properties:
        id:
          type: string
          description: Identifier of the hook.
        name:
          type: object
          properties:
            en:
              type: string
              description: Name of the extension in English.
          additionalProperties:
            type: string
            description: Name of the extension in some other language denoted by ISO 3166-1 alpha-2 code.
          required:
          - en
        intervals:
          type: array
          items:
            type: string
          description: The intervals associated with the hook.
    PublicContractIdentificationDetails:
      type: object
      properties:
        explanation:
          type: object
          properties:
            en:
              type: string
              description: Explanation of the functionality shown to the end user.
              example: This process will give you access to all Contracts kept
          additionalProperties:
            type: string
            description: Explanation of the functionality in language denoted by ISO 3166-1 alpha-2 code.
          required:
          - en
          description: Explanation of the hook.
    Extension:
      type: object
      properties:
        id:
          type: string
          description: Identifier of the extension. Should not change between updates.
        app_id:
          type: string
          description: Identifier of the app from which the extension was installed. Should not change between updates.
        name:
          type: object
          properties:
            en:
              type: string
              description: Name of the extension in English.
          additionalProperties:
            type: string
            description: Name of the extension in some other language denoted by ISO 3166-1 alpha-2 code.
          required:
          - en
          description: Name of the extension.
        description:
          type: object
          properties:
            en:
              type: string
              description: Name of the extension in English.
          additionalProperties:
            type: string
            description: Name of the extension in some other language denoted by ISO 3166-1 alpha-2 code.
          required:
          - en
          description: Name of the extension.
        version:
          type: string
          description: Version of the extension.
        options:
          type: array
          description: Options available to the extension configurable by the portal administrator.
          items:
            type: object
            properties:
              id:
                type: string
                description: Identifier of the option. Should not change between updates.
              name:
                type: object
                properties:
                  en:
                    type: string
                    description: Name of the option in English.
                additionalProperties:
                  type: string
                  description: Name of the option in some other language denoted by ISO 3166-1 alpha-2 code.
                required:
                - en
                description: Name of the option.
              type:
                type: string
                enum:
                - text
                - secret
                description: Type of the option.
              description:
                type: object
                properties:
                  en:
                    type: string
                    description: Description of the option in English.
                additionalProperties:
                  type: string
                  description: Description of the option in some other language denoted by ISO 3166-1 alpha-2 code.
                required:
                - en
                description: Description of the option.
              default:
                type: string
                description: Default value of the option.
              required:
                type: boolean
                description: Indicate whether the option is required.
                default: false
            required:
            - id
            - name
            - type
        links:
          type: array
          description: External links added to the portal.
          items:
            allOf:
            - $ref: '#/components/schemas/ExtensionSeamlessLink'
        hooks:
          type: array
          description: Hooks that influence the behavior of Portal.
          items:
            allOf:
            - $ref: '#/components/schemas/ExtensionHook'
            - oneOf:
              - $ref: '#/components/schemas/ExtensionHookRegistrationIdentifiersCheck'
              - $ref: '#/components/schemas/ExtensionHookContractIdentification'
              - $ref: '#/components/schemas/ExtensionHookPriceDataRetrieval'
              - $ref: '#/components/schemas/ExtensionHookConsumptionDataRetrieval'
              - $ref: '#/components/schemas/ExtensionHookCostDataRetrieval'
              - $ref: '#/components/schemas/ExtensionHookMeterReadingPlausibilityCheck'
      required:
      - id
      - name
    ExtensionSeamlessLink:
      type: object
      properties:
        id:
          type: string
          description: Identifier of the link. Should not change between updates.
        name:
          type: object
          properties:
            en:
              type: string
              description: Name of the extension in English.
          additionalProperties:
            type: string
            description: Name of the extension in some other language denoted by ISO 3166-1 alpha-2 code.
          required:
          - en
          description: Name of the extension.
        description:
          type: object
          properties:
            en:
              type: string
              description: Name of the extension in English.
          additionalProperties:
            type: string
            description: Name of the extension in some other language denoted by ISO 3166-1 alpha-2 code.
          required:
          - en
          description: Name of the extension.
        type:
          type: string
          enum:
          - seamless
        condition:
          type: string
          description: Controls whether the link should be shown. Supports variable interpolation.
          example: '{{Contact.customer_number | is_not_empty}}'
        auth:
          $ref: '#/components/schemas/ExtensionAuthBlock'
        redirect:
          type: object
          properties:
            url:
              type: string
              description: URL to redirect to. Supports variable interpolation.
            params:
              type: object
              description: Parameters to append to the URL. Supports variable interpolation.
              additionalProperties:
                type: string
              default: {}
      required:
      - id
      - name
      - type
      - redirect
    ExtensionHook:
      type: object
      properties:
        id:
          type: string
          description: Identifier of the hook. Should not change between updates.
    ExtensionHookRegistrationIdentifiersCheck:
      description: |
        Hook that replaces the built-in registration identifiers check. This hook makes a POST call whenever a user is trying to register to find the corresponding contact. The expected response to the call is:
          - 200 with contact id if exactly one contact is found
          - 404 if no contact is found or more than contact is found
      type: object
      properties:
        type:
          type: string
          enum:
          - registrationIdentifiersCheck
        auth:
          $ref: '#/components/schemas/ExtensionAuthBlock'
        call:
          type: object
          properties:
            url:
              type: string
              description: URL to call. Supports variable interpolation.
            params:
              type: object
              description: Parameters to append to the URL. Supports variable interpolation.
              additionalProperties:
                type: string
              default: {}
            headers:
              type: object
              description: Headers to use. Supports variable interpolation.
              additionalProperties:
                type: string
              default: {}
            result:
              type: string
              description: Contact ID usually retrieved from the response body, e.g. `{{CallResponse.data.contact_id}}`. Supports variable interpolation.
          required:
          - url
          - headers
          - result
      required:
      - type
      - call
    ExtensionHookContractIdentification:
      description: >
        Hook that replaces the built-in contract identification for self-assignment. This hook makes a POST call whenever a user is trying to self-assign a contract to find the corresponding contract(s). The expected response to the call
        is:
          - 200 if found with either:
            - contract_id array
            - contact_id string
          - 404 if no contract is found
        If `contact_id` is provided in the response, Contracts are retrieved from this Contact. In that case, optionally, if you also specify `contact_relation_attribute`, the specified Contact attribute of the user performing the action
        will be modified to add the matched Contact.
      type: object
      properties:
        type:
          type: string
          enum:
          - contractIdentification
        auth:
          $ref: '#/components/schemas/ExtensionAuthBlock'
        call:
          type: object
          properties:
            url:
              type: string
              description: URL to call. Supports variable interpolation.
            params:
              type: object
              description: Parameters to append to the URL. Supports variable interpolation.
              additionalProperties:
                type: string
              default: {}
            headers:
              type: object
              description: Headers to use. Supports variable interpolation.
              additionalProperties:
                type: string
              default: {}
          required:
          - url
          - headers
          - result
        contact_relation_attribute:
          type: string
          description: Name of the Contact attribute to update with the matched Contact ID. Must be a Contact relation attribute supporting multiple entities.
          example: represents_contact
        explanation:
          type: object
          properties:
            en:
              type: string
              description: Explanation of the functionality shown to the end user.
              example: This process will give you access to all Contracts kept
          additionalProperties:
            type: string
            description: Explanation of the functionality in language denoted by ISO 3166-1 alpha-2 code.
          required:
          - en
          description: Explanation of the hook.
      required:
      - type
      - call
    ExtensionHookMeterReadingPlausibilityCheck:
      description: |
        Hook that checks the plausibility of meter readings before they are saved. This hook makes a POST call whenever a user is trying to save a meter reading. The expected response to the call is:
          - 200:
            If meter reading is plausible, the response should contain:
              - valid: true
            If meter reading is not plausible, the response should contain:
              - valid: false
      type: object
      properties:
        type:
          type: string
          enum:
          - meterReadingPlausibilityCheck
        auth:
          $ref: '#/components/schemas/ExtensionAuthBlock'
        call:
          type: object
          properties:
            url:
              type: string
              description: URL to call. Supports variable interpolation.
            body:
              type: object
              description: JSON body to use for authentication. Supports variable interpolation.
              additionalProperties:
                type: string
              default: {}
            headers:
              type: object
              description: Headers to use. Supports variable interpolation.
              additionalProperties:
                type: string
              default: {}
          required:
          - url
          - headers
          - body
          - result
        resolved:
          type: object
          description: Response to the call
          properties:
            valid:
              type: string
              description: Indicate whether the meter reading is plausible
              example: '{{CallResponse.data.valid}}'
            upper_limit:
              type: string
              description: Upper allowed limit of the meter reading
              example: '{{CallResponse.data.upper_limit}}'
            lower_limit:
              type: string
              description: Lower allowed limit of the meter reading
              example: '{{CallResponse.data.lower_limit}}'
      required:
      - type
      - call
      - resolved
    ExtensionHookPriceDataRetrieval:
      description: >
        Hook that will allow using the specified source as data for price visualizations. This hook is triggered to fetch the data. Format of the request and response has to follow the following specification: TBD. The expected response to
        the call is:
          - 200 with the time series data
      type: object
      properties:
        type:
          type: string
          enum:
          - priceDataRetrieval
        auth:
          $ref: '#/components/schemas/ExtensionAuthBlock'
        call:
          type: object
          properties:
            method:
              type: string
              description: HTTP method to use for the call
              default: GET
            url:
              type: string
              description: URL to call. Supports variable interpolation.
            params:
              type: object
              description: Parameters to append to the URL. Supports variable interpolation.
              additionalProperties:
                type: string
              default: {}
            headers:
              type: object
              description: Headers to use. Supports variable interpolation.
              additionalProperties:
                type: string
              default: {}
          required:
          - url
        resolved:
          type: object
          properties:
            dataPath:
              type: string
              description: Optional path to the data (array) in the response. If omitted, the data is assumed to be on the top level.
      required:
      - type
      - call
    ExtensionHookConsumptionDataRetrieval:
      description: >
        Hook that will allow using the specified source as data for consumption visualizations. This hook is triggered to fetch the data. Format of the request and response has to follow the following specification: TBD. The expected
        response to the call is:
          - 200 with the time series data
      type: object
      properties:
        type:
          type: string
          enum:
          - consumptionDataRetrieval
        auth:
          $ref: '#/components/schemas/ExtensionAuthBlock'
        call:
          type: object
          properties:
            method:
              type: string
              description: HTTP method to use for the call
              default: GET
            url:
              type: string
              description: URL to call. Supports variable interpolation.
            params:
              type: object
              description: Parameters to append to the URL. Supports variable interpolation.
              additionalProperties:
                type: string
              default: {}
            headers:
              type: object
              description: Headers to use. Supports variable interpolation.
              additionalProperties:
                type: string
              default: {}
          required:
          - url
        resolved:
          type: object
          properties:
            dataPath:
              type: string
              description: Optional path to the data (array) in the response. If omitted, the data is assumed to be on the top level.
      required:
      - type
      - call
    ExtensionHookCostDataRetrieval:
      description: >
        Hook that will allow using the specified source as data for consumption visualizations. This hook is triggered to fetch the data. Format of the request and response has to follow the following specification: TBD. The expected
        response to the call is:
          - 200 with the time series data
      type: object
      properties:
        type:
          type: string
          enum:
          - costDataRetrieval
        auth:
          $ref: '#/components/schemas/ExtensionAuthBlock'
        call:
          type: object
          properties:
            method:
              type: string
              description: HTTP method to use for the call
              default: GET
            url:
              type: string
              description: URL to call. Supports variable interpolation.
            params:
              type: object
              description: Parameters to append to the URL. Supports variable interpolation.
              additionalProperties:
                type: string
              default: {}
            headers:
              type: object
              description: Headers to use. Supports variable interpolation.
              additionalProperties:
                type: string
              default: {}
          required:
          - url
        resolved:
          type: object
          properties:
            dataPath:
              type: string
              description: Optional path to the data (array) in the response. If omitted, the data is assumed to be on the top level.
      required:
      - type
      - call
    ExtensionAuthBlock:
      type: object
      properties:
        method:
          type: string
          description: HTTP method to use for authentication
          default: GET
        url:
          type: string
          description: URL to use for authentication. Supports variable interpolation.
        params:
          type: object
          description: Parameters to append to the URL. Supports variable interpolation.
          additionalProperties:
            type: string
          default: {}
        headers:
          type: object
          description: Headers to use for authentication. Supports variable interpolation.
          additionalProperties:
            type: string
          default: {}
        body:
          type: object
          description: JSON body to use for authentication. Supports variable interpolation.
          additionalProperties:
            type: string
          default: {}
        cache:
          type: object
          properties:
            key:
              type: string
              description: Key to use to identify the auth response. Supports interpolation.
              example: '{{Options.api_key}}'
            ttl:
              type: string
              description: Time to live in seconds for the cache. Supports interpolation.
              example: '{{AuthResponse.data.expires_in}}'
          required:
          - key
          - ttl
      required:
      - url
    Direction:
      type: string
      enum:
      - feed-in
      - feed-out
    TariffType:
      type: string
      enum:
      - ht
      - nt
    Source:
      type: string
      enum:
      - ECP
      - ERP
      - '360'
      - journey-submission
    Reason:
      type: string
      nullable: true
      example: Storing the feed-in record
      description: The reason for recording the reading
    ReadBy:
      type: string
      nullable: true
      example: John Doe
      description: The person who recorded the reading
    ReadingStatus:
      type: string
      nullable: true
      enum:
      - valid
      - in-validation
      - implausible
      - null
      - ''
    MeterReading:
      type: object
      required:
      - value
      - meter_id
      - source
      properties:
        value:
          type: number
          example: 240
          description: The reading value of the meter
        read_by:
          $ref: '#/components/schemas/ReadBy'
        reason:
          $ref: '#/components/schemas/Reason'
        meter_id:
          $ref: '#/components/schemas/EntityId'
          description: The ID of the associated meter
        counter_id:
          $ref: '#/components/schemas/EntityId'
          description: The ID of the associated meter counter
        direction:
          $ref: '#/components/schemas/Direction'
          description: The direction of the reading (feed-in or feed-out)
        timestamp:
          type: string
          description: If the value is not provided, the system will be set with the time the request is processed.
          example: '2022-10-10'
        source:
          $ref: '#/components/schemas/Source'
          description: The source of the reading
        status:
          $ref: '#/components/schemas/ReadingStatus'
          description: The status of the reading
    MeterReadingPhoto:
      type: object
      required:
      - filename
      - mime_type
      - contents
      - meter_id
      properties:
        filename:
          type: string
          example: Reading 10.01.2025.jpg
        mime_type:
          type: string
          example: image/jpeg
        contents:
          type: string
          description: Base64 encoded image
          example: data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxMTEhUTExMWFhUXGBgYGBgYGBgYGBgYGBgYFxgYFxgYHSggGBolHRgXITEhJSkrLi4uFx8zODMtNygtLisBCgoKDg0OGhAQGy0lHyUt
        meter_id:
          $ref: '#/components/schemas/EntityId'
          description: The ID of the associated Meter
    MeterReadingPhotoData:
      type: object
      required:
      - filename
      - s3ref
      properties:
        filename:
          type: string
          example: Reading 10.01.2025.jpg
        s3ref:
          type: object
          required:
          - bucket
          - key
          properties:
            bucket:
              type: string
              example: meter-readings
              description: S3 bucket name
            key:
              type: string
              example: uuid/reading-10.01.2025.jpg
              description: S3 key
        reading:
          type: string
          example: '000123.45'
        sector:
          type: string
          example: water
        meter_number:
          type: string
          example: '00123456'
    SSOLoginToken:
      type: string
    ProviderSlug:
      type: string
      example: office-365-login
      description: URL-friendly slug to use as organization-unique identifier for Provider
      pattern: '[0-9a-z-]+'
    ProviderDisplayName:
      type: string
      example: Office 365 Login
      description: Human-readable display name for identity provider shown in login
    ProviderConfig:
      type: object
      properties:
        slug:
          $ref: '#/components/schemas/ProviderSlug'
        display_name:
          $ref: '#/components/schemas/ProviderDisplayName'
        provider_type:
          type: string
          enum:
          - OIDC
        attribute_mappings:
          $ref: '#/components/schemas/AttributeMappingConfig'
        oidc_config:
          $ref: '#/components/schemas/OIDCProviderConfig'
        mobile_oidc_config:
          $ref: '#/components/schemas/MoblieOIDCConfig'
      required:
      - display_name
      - provider_type
    ProviderPublicConfig:
      type: object
      properties:
        slug:
          $ref: '#/components/schemas/ProviderSlug'
        display_name:
          $ref: '#/components/schemas/ProviderDisplayName'
        oidc_config:
          $ref: '#/components/schemas/OIDCProviderConfig'
        mobile_oidc_config:
          $ref: '#/components/schemas/MoblieOIDCConfig'
      required:
      - slug
      - display_name
    AttributeMappingConfig:
      type: object
      description: Dictionary of epilot user attributes to claims
      properties:
        contact:
          additionalProperties: true
          type: object
          required:
          - email
          properties:
            email:
              type: string
              example: email
            first_name:
              type: string
              example: first_name
            last_name:
              type: string
              example: last_name
            phone:
              type: string
              example: tel
            preferred_language:
              type: string
              example: language
            concession:
              type: string
              example: GPE
              description: 'The concession of the user. For eg: GPE, EPE, WPE'
            installer_number:
              type: string
              example: 123456
              description: The installer number of the user
        account:
          additionalProperties: true
          type: object
          properties:
            name:
              type: string
              example: company_name
            street:
              type: string
              example: street_name
            house_number:
              type: string
              example: house_number
            postal_code:
              type: string
              example: postal_code
            city:
              type: string
              example: city
        portal_user:
          additionalProperties: true
          type: object
          properties:
            access_status:
              type: string
              example: access_status
            expires_at:
              type: string
              example: expires_at
        concession_attributes:
          type: object
          properties:
            water:
              type: string
              example: water
            energy:
              type: string
              example: energy
            gas:
              type: string
              example: gas
      required:
      - contact
    OIDCProviderConfig:
      type: object
      properties:
        oidc_issuer:
          type: string
          description: Issuing Authority URL
          example: https://login.microsoftonline.com/33d4f3e5-3df2-421e-b92e-a63cfa680a88/v2.0
        redirect_uri:
          type: string
          description: Redirect URI for the OIDC flow
          example: https://customer-portal.com/login
        client_id:
          type: string
          example: ab81daf8-8b1f-42d6-94ca-c51621054c75
        client_secret:
          type: string
          example: 7BIUnn~6shh.7fNtXb..3k1Mp3s6k6WK3B
        scope:
          type: string
          description: Space-separated list of OAuth 2.0 scopes to request from OpenID Connect
          example: openid email
        metadata:
          $ref: '#/components/schemas/OIDCProviderMetadata'
      required:
      - oidc_issuer
      - client_id
      - scope
    MoblieOIDCConfig:
      type: object
      properties:
        client_id:
          type: string
          description: Client ID for the mobile app
          example: 123456
        client_secret:
          type: string
          description: Client Secret for the mobile app
          example: 123456
    OIDCProviderMetadata:
      type: object
      properties:
        authorization_endpoint:
          type: string
          description: URL of the authorization endpoint
          example: https://www.facebook.com/v12.0/dialog/oauth
        token_endpoint:
          type: string
          description: URL of the token endpoint
          example: https://graph.facebook.com/v12.0/oauth/access_token
        userinfo_endpoint:
          type: string
          description: URL of the userinfo endpoint
          example: https://graph.facebook.com/me
        mobile_redirect_uri:
          type: string
          description: URL of the mobile redirect URI
          example: msauth.io.epilot.ecp://auth
    SAMLProviderConfig:
      type: object
    SSOCallbackRequest:
      type: object
      required:
      - token_endpoint
      - grant_type
      - code
      - redirect_uri
      - client_id
      - client_secret
      - code_verifier
      properties:
        token_endpoint:
          type: string
          description: URL of the authorization endpoint
          example: https://www.facebook.com/v12.0/dialog/oauth
        grant_type:
          type: string
          description: The grant type
          example: authorization_code
        code:
          type: string
          description: The code received from the external SSO provider
          example: '123456'
        redirect_uri:
          type: string
          description: The redirect uri
          example: https://customer-portal.com/login
        client_id:
          type: string
          description: The client id
          example: '123456'
        client_secret:
          type: string
          description: The client secret
          example: '123456'
        code_verifier:
          type: string
          description: The code verifier
          example: '123456'
    SSOCallbackResponse:
      type: object
      required:
      - access_token
      - token_type
      - expires_in
      - refresh_token
      - id_token
      properties:
        access_token:
          type: string
          description: The access token
          example: '123456'
        token_type:
          type: string
          description: The token type
          example: Bearer
        expires_in:
          type: number
          description: The expires in
          example: 3600
        refresh_token:
          type: string
          description: The refresh token
          example: '123456'
        id_token:
          type: string
          description: The id token
          example: '123456'
    BlockProps:
      type: object
      additionalProperties: true
      properties:
        visibility:
          type: object
          description: The conditions that need to be met for the block to be shown
        content:
          type: object
          description: The content of the block
        design:
          type: object
          description: The design of the block
    BlockType:
      type: string
      description: The type of the block. eg; tabs, tab, group, attribute
      example: tab
    BlockRequest:
      type: object
      additionalProperties: true
      required:
      - type
      - order
      properties:
        props:
          $ref: '#/components/schemas/BlockProps'
        parent_id:
          type: string
          description: The id of the parent block
          example: c495fef9-eeca-4019-a989-8390dcd9825b
        type:
          $ref: '#/components/schemas/BlockType'
        order:
          type: number
          description: The order of the block
          example: 1
    BlockId:
      type: string
      description: The id of the block
      format: uuid
      example: c495fef9-eeca-4019-a989-8390dcd9825b
    Block:
      type: object
      required:
      - id
      allOf:
      - $ref: '#/components/schemas/BlockRequest'
      - type: object
        additionalProperties: true
        properties:
          id:
            type: string
            description: The id of the block
            format: uuid
            example: c495fef9-eeca-4019-a989-8390dcd9825b
    PageRequest:
      type: object
      additionalProperties: true
      required:
      - slug
      - path
      - order
      properties:
        slug:
          type: string
          description: The slug of the page
          example: dashboard
        path:
          type: string
          description: The path of the page
          example: /dashboard
        schema:
          type: string
          description: The schema of the page
          enum:
          - contact
          - contract
          - meter
          - order
          - opportunity
        visibility:
          type: object
          description: The conditions that need to be met for the page to be shown
          additionalProperties: true
        content:
          type: object
          description: The content of the page
          additionalProperties: true
        design:
          type: object
          description: The design of the page
          additionalProperties: true
        blocks:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/Block'
        order:
          type: number
          description: The order of the block
          example: 1
        is_system:
          type: boolean
          description: Whether the page is a system page
          example: false
        is_public:
          type: boolean
          description: Whether the page is public
          example: true
    Page:
      type: object
      required:
      - id
      allOf:
      - $ref: '#/components/schemas/PageRequest'
      - type: object
        additionalProperties: true
        properties:
          id:
            type: string
            description: The id of the page
            format: uuid
            example: c495fef9-eeca-4019-a989-8390dcd9825b
servers:
- url: https://customer-portal-api.sls.epilot.io

