openapi: 3.1.0
info:
  title: UPowr Retail Offer API
  version: 1.0.0
servers:
  - url: /api/v1/retail-offers
security:
  - session: []
paths:
  /:
    post:
      summary: Create a new retail offer
      operationId: createRetailOffer
      security:
        - session:
            - retail-offer:create
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateRetailOffer'
      responses:
        '201':
          $ref: '#/components/responses/CreateResponse'
        '400':
          $ref: '#/components/responses/BadRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '500':
          $ref: '#/components/responses/UnknownError'
  /{offerId}:
    patch:
      summary: Update an existing retail offer
      operationId: updateRetailOffer
      security:
        - session:
            - retail-offer:update
      parameters:
        - $ref: '#/components/parameters/offerId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateRetailOffer'
      responses:
        '200':
          $ref: '#/components/responses/SuccessResponse'
        '400':
          $ref: '#/components/responses/BadRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '500':
          $ref: '#/components/responses/UnknownError'
    delete:
      summary: Delete an existing retail offer
      operationId: deleteRetailOffer
      security:
        - session:
            - retail-offer:delete
      parameters:
        - $ref: '#/components/parameters/offerId'
      responses:
        '200':
          $ref: '#/components/responses/SuccessResponse'
        '400':
          $ref: '#/components/responses/BadRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '500':
          $ref: '#/components/responses/UnknownError'
components:
  parameters:
    offerId:
      name: offerId
      in: path
      description: The Retail Offer ID
      required: true
      schema:
        type: string
  schemas:
    CreateRetailOffer:
      type: object
      properties:
        name:
          type: string
          description: The name of the Retail Offer.
          maxLength: 40
        tags:
          type: array
          items:
            type: string
          description: A list of tags for filtering purposes
        customerId:
          type: string
          description: >-
            The unique identifier for the customer this Retail Offer is related
            to.
        data:
          $ref: '#/components/schemas/RetailOfferData'
      required:
        - name
        - data
    UpdateRetailOffer:
      type: object
      properties:
        name:
          type: string
          description: The name of the Retail Offer.
          maxLength: 40
        tags:
          type: array
          items:
            type: string
          description: A list of tags for filtering purposes
        customerId:
          type: string
          description: >-
            The unique identifier for the customer this Retail Offer is related
            to.
        data:
          $ref: '#/components/schemas/RetailOfferData'
      anyOf:
        - required:
            - name
        - required:
            - data
        - required:
            - tags
        - required:
            - customerId
    ErrorResponse:
      type: object
      properties:
        message:
          type: string
          description: A message describing the error that occurred.
      required:
        - message
    RetailOfferData:
      type: object
      description: >-
        This which will contain all charges and their related information
        (supply, usage, other, export)
      properties:
        seasons:
          description: Array of seasons with open/close dates and intervals
          type: array
          items:
            type: object
            properties:
              open:
                type: string
              close:
                type: string
              intervals:
                type: array
                items:
                  type: object
                  properties:
                    label:
                      type: string
                    end_time:
                      type: string
                    start_time:
                      type: string
                    block1_cpkwh:
                      type: number
                    block2_cpkwh:
                      type: number
                    days_of_week:
                      type: array
                      items:
                        type: number
                    demand_charge_cpkwpd:
                      type: number
                  required:
                    - label
                    - end_time
                    - start_time
                    - block2_cpkwh
                    - days_of_week
            required:
              - open
              - close
              - intervals
        controlled_load:
          type: array
          items:
            type: object
            properties:
              class:
                type: string
              rate_cpkwh:
                type: number
            required:
              - class
              - rate_cpkwh
          description: Optional array of controlled load details
        customer_cost_per_billing_period_cents:
          type: number
          description: Optional customer cost per billing period in cents
        eic_xref:
          type: string
          description: Optional EIC cross-reference
        public_display_name:
          type: string
          description: Optional public display name
        offer_id:
          type: string
          description: The offer ID
        dnsp_code:
          type: string
          description: Optional DNSP code
        plan_type:
          type: string
          description: The plan type
        effective_to:
          type: string
          description: The effective date to
        retailer_code:
          type: string
          description: The retailer code
        effective_from:
          type: string
          description: The effective date from
        billing_period_m:
          type: number
          description: Optional billing period in months
        blocking_period_m:
          type: number
          description: Optional blocking period in months
        block1_size_kwh:
          type: number
          description: Optional block 1 size in kWh
        feed_in_tariff_cpkwh:
          type: number
          description: The feed-in tariff in cents per kWh
        premium_feed_in_tariff_cpkwh:
          type: number
          description: The premium feed-in tariff in cents per kWh
        general_usage_supply_charge_cpday:
          type: number
          description: The general usage supply charge per day in cents
        billing_period_fixed_credits_cents:
          type: number
          description: Optional billing period fixed credits in cents
        is_gross_consumption:
          type: boolean
          description: >-
            Optional flag indicating if customer is charged based on gross
            consumption
        includes_gst:
          type: boolean
          description: Optional flag indicating if the retail offer includes GST
        gst_percentage:
          type: number
          description: Optional GST amount as a percentage
        charges:
          type: object
          description: Optional charges
          properties:
            ancillary_cpkwh:
              type: number
            ess_cpkwh:
              type: number
            veec_cpkwh:
              type: number
            lrec_cpkwh:
              type: number
            srec_cpkwh:
              type: number
        percentage_off_default_offer:
          type: object
          description: Optional percentage off the default offer
          properties:
            minimum:
              type: number
            ausgrid:
              type: number
            endeavour:
              type: number
            energex:
              type: number
            essential:
              type: number
            sapn:
              type: number
          required:
            - minimum
        gov_id:
          type: string
          description: Optional government ID
      required:
        - seasons
        - offer_id
        - plan_type
        - effective_to
        - retailer_code
        - effective_from
        - feed_in_tariff_cpkwh
        - premium_feed_in_tariff_cpkwh
        - general_usage_supply_charge_cpday
  responses:
    CreateResponse:
      description: Retail Offer created successfully.
      content:
        application/json:
          schema:
            type: object
            properties:
              id:
                type: string
                description: The unique identifier for the newly created Retail Offer.
            required:
              - id
          examples:
            actionCompleted:
              description: Retail Offer created
              value:
                id: ABC123456DE
    SuccessResponse:
      description: Retail Offer actioned successfully.
      content:
        application/json:
          schema:
            type: object
            properties:
              ok:
                type: boolean
                description: Indicates whether the action was successful.
            required:
              - ok
          examples:
            deleteSuccessful:
              description: Retail Offer actioned
              value:
                ok: true
    UnknownError:
      description: Unknown Error has occurred
      content:
        application/json:
          schema:
            type: object
            properties:
              message:
                type: string
                description: A message describing the error that occurred.
            required:
              - message
          examples:
            unknownError:
              summary: Unknown error occurred
              value:
                message: >-
                  Something's gone wrong, but we've been notified and we're
                  looking into it. If you have any questions, email
                  support@upowr.com.au with the error ID:
                  3fa85f64-5717-4562-b3fc-2c963f66afa7
    BadRequestError:
      description: Bad Request Error has occurred
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            badRequestError:
              summary: Bad Request error occurred
              value:
                message: Invalid Retailer
    UnauthorizedError:
      description: Unauthorized access. Valid authentication credentials are required.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            invalidCredentials:
              summary: Authentication failed due to invalid credentials
              value:
                message: Unauthorized
  securitySchemes:
    session:
      type: oauth2
      description: Machine-to-Machine Authorization
      flows:
        clientCredentials:
          tokenUrl: https://id.core.upowr.cloud/oauth/token
          scopes:
            retail-offer:create: Create a retail offer
            retail-offer:update: Update a retail offer
            retail-offer:delete: Delete a retail offer
