openapi: 3.1.0
info:
  title: Roof-Calc Management REST API
  version: 1
  summary: Roof-Calc quote, product and stock management REST API.
  contact:
    name: Roof-Calc Support
    email: admin@roof-calc.co.uk
  x-logo:
    url: https://app.roof-calc.co.uk/roof-calc-default.15305bd5.webp
    altText: Roof-Calc logo
  description: |
    ## Introduction    
    Welcome to the Roof-Calc quote, product and stock management REST API. This API is intended **SOLELY** for automatically updating merchant product details (including pricing and stock/availability) and managing merchant quotes.

    ## Access
      ### Base URL
      The base URL for this API is `https://api.roof-calc.co.uk/${version}` where `version` is some sequential **MAJOR** version string such as `v1`, `v2`, `v3`. The latest/current version path will be used across the API reference within each endpoint URL.
      ### Authentication
      Access to this API is authenticated **ONLY** by means of a JWT Bearer token in the request headers tied to a specific merchant account with `api` scope set.
      
      Your merchant's JWT API Key can be found and regenerated in the Roof-Calc Dashboard using an account with `manager` privileges by clicking on "Integrations Details" in the bottom part of the left nav and looking for the "JWT API Key" field.

      Please store your JWT API Key securely for example using environment variables. Either periodically, or in the event that you suspect the JWT API key has been compromised in any way, you **MUST** regenerate it through the Roof-Calc Dashboard. **REGENERATING THE JWT API KEY WILL INVALIDATE THE EXISTING KEY.**

      Further details are available in the OpenAPI security schemes for this API (see [here](/docs/api-reference/roof-calc-management-rest-api#authentication)).
      ### Rate Limiting
      This API uses various rate limits to ensure fair service availability for all users and to protect against abuse. We do not disclose the exact details of our rate limiting policy, however making not more than 4 requests per second over a sustained period should prevent your requests from being refused. Some additional allowance is available for burst requests, however the API is **NOT** intended for sustained frequent use.

      Any request may be rejected by returning an HTTP 429 response (Too Many Requests). In this event we recommend waiting for a period of time not less than 60 seconds before attempting to make any additional requests. Continued requests in excess of the imposed rate limits following an HTTP 429 response will be deemed as abuse of the API and may result in permanent request throttling or termination of your account subject to Section 11.2 of our Terms of Use (see [here](/docs/terms-of-use#112---by-provider)).
    ## Legal
      ### Terms of Use
        By using this API, you agree to be bound by our Terms of Use policy (see [here](/docs/terms-of-use)). Subject to Section 11.2 of these Terms of Use (see [here](/docs/terms-of-use#112---by-provider)), if you are found to be in contravention of these Terms of Use, your access to this API and its associated software may be terminated immediately.
      ### License
        Copyright (C) FlexiProof Limited. All rights reserved.

        This API is provided as a part of proprietary software built and maintained by FlexiProof Limited (company number [09132601](https://find-and-update.company-information.service.gov.uk/company/09132601). Under Section 2.3 of our Terms of Use policy (see [here](/docs/terms-of-use#22---restrictions)), it is **NOT** permitted to resell or redistribute any parts of this software.
servers:
  - url: https://api.roof-calc.co.uk/{version}
    description: Primary server Base URL for accessing API with MAJOR path versioning.  
    variables:
      version:
        default: v1
        description: API version using SemVer MAJOR path versioning prefixed with `v` (i.e. `v1`, `v2` etc.).
paths:
  "":
    get:
      tags:
        - API Info
      summary: API information
      description: Get basic API information including base URL, OpenAPI specification file download link and support email.
      responses:
        200:
          description: OK - Fetching API information successful.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ServerInfo"
        5xx:
          description: Internal Server Error - Your request was correctly formed, however an internal server error was encountered, please try again later or contact support if the issue persists.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InternalServerError"
  /spec:
    get:
      tags:
        - API Info
      summary: OpenAPI spec
      description: Download OpenAPI YAML specification file for API (must be authorized to access this resource).
      responses:
        200:
          description: OK - Download of OpenAPI specification file successful.
          content:
            application/yaml:
              schema:
                type: string
                example: "OpenAPI YAML file..."
        5xx:
          description: Internal Server Error - Your request was correctly formed, however an internal server error was encountered, please try again later or contact support if the issue persists.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InternalServerError"
  /merchants:
    get:
      tags:
        - Merchants
      summary: Read merchant details
      description: Read merchant details for all merchants associated with subject claim in API token.
      responses:
        200:
          description: OK - Merchant details fetched successfully.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/MerchantIdentifiers"
        4xx:
          description: Bad Request - There was a problem with your request, please refer to the specific HTTP response code, check your request against all available documentation and try again. Problems may include missing or disallowed keys or unexpected data types in request body, missing or invalid authentication in request headers, attempting to access a record which does not exist or for which you are not authorized or rate limiting.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RequestError"
        5xx:
          description: Internal Server Error - Your request was correctly formed, however an internal server error was encountered, please try again later or contact support if the issue persists.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InternalServerError"
      security:
        - JWTBearerAuth: []
  /:merchantId/quotes:
    get:
      tags:
        - Quotes
      summary: Read multiple quotes
      description: Read paginated quotes associated with merchant specified by UUID in path.
      parameters:
        - name: merchantId
          in: path
          description: Merchant UUID.
          example: eed31b32-bdc8-4e76-8939-952a707455f3
          required: true
          schema:
            type: uuid
        - name: limit
          in: query
          description: Number of results to return.
          default: 10
          schema:
            type: integer
            minimum: 0
            maximum: 100
        - name: page
          in: query
          description: Page to return based on specified limit.
          default: 0
          schema:
            type: integer
            minimum: 0
      responses:
        200:
          description: OK - Quotes associated with specified merchant fetched successfully.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Product"
        4xx:
          description: Bad Request - There was a problem with your request, please refer to the specific HTTP response code, check your request against all available documentation and try again. Problems may include missing or disallowed keys or unexpected data types in request body, missing or invalid authentication in request headers, attempting to access a record which does not exist or for which you are not authorized or rate limiting.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RequestError"
        5xx:
          description: Internal Server Error - Your request was correctly formed, however an internal server error was encountered, please try again later or contact support if the issue persists.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InternalServerError"
      security:
        - JWTBearerAuth: []
    patch:
      tags:
        - Quotes
      summary: Update multiple quotes
      description: Update multiple quotes associated with merchant specified by UUID in path.
      parameters:
        - name: merchantId
          in: path
          description: Merchant UUID.
          example: 58ad9a15-111f-451d-a69d-844d9e9d0eef
          required: true
          schema:
            type: uuid
      requestBody:
        description: Array of *up to* 100 update objects referencing target quotes by UUID.
        required: true
        content:
          application/json:
            schema:
              type: array
              items:
                $ref: "#/components/schemas/QuoteUpdate"
              maxItems: 100
      responses:
        200:
          description: OK - Quotes associated with specified merchant updated successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: Human-readable string containing number of updated quotes.
                    example: Updated 50 quotes
        4xx:
          description: Bad Request - There was a problem with your request, please refer to the specific HTTP response code, check your request against all available documentation and try again. Problems may include missing or disallowed keys or unexpected data types in request body, missing or invalid authentication in request headers, attempting to access a record which does not exist or for which you are not authorized or rate limiting.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RequestError"
        5xx:
          description: Internal Server Error - Your request was correctly formed, however an internal server error was encountered, please try again later or contact support if the issue persists.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InternalServerError"
      security:
        - JWTBearerAuth: []
  /:merchantId/quotes/:quoteId:
    get:
      tags:
        - Quotes
      summary: Read single quote
      description: Read single quote associated with merchant specified by UUIDs in path.
      parameters:
        - name: merchantId
          in: path
          description: Merchant UUID.
          example: eed31b32-bdc8-4e76-8939-952a707455f3
          required: true
          schema:
            type: uuid
        - name: quoteId
          in: path
          description: Quote UUID.
          example: bffe73dd-cd6e-4590-b75f-0a5a7c0dd7bc
          required: true
          schema:
            type: uuid
      responses:
        200:
          description: OK - Specified quote fetched successfully.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Quote"
        4xx:
          description: Bad Request - There was a problem with your request, please refer to the specific HTTP response code, check your request against all available documentation and try again. Problems may include missing or disallowed keys or unexpected data types in request body, missing or invalid authentication in request headers, attempting to access a record which does not exist or for which you are not authorized or rate limiting.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RequestError"
        5xx:
          description: Internal Server Error - Your request was correctly formed, however an internal server error was encountered, please try again later or contact support if the issue persists.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InternalServerError"
      security:
        - JWTBearerAuth: []
    patch:
      tags:
        - Quotes
      summary: Update single quote
      description: Update single quote associated with merchant specified by UUIDs in path.
      parameters:
        - name: merchantId
          in: path
          description: Merchant UUID.
          example: a6d2f16d-dc4c-414b-9d63-da5f0ac6deff
          required: true
          schema:
            type: uuid
        - name: quoteId
          in: path
          description: Quote UUID.
          example: b9a5a798-6505-492d-8ef3-9fa6968ab57d
          required: true
          schema:
            type: uuid
      requestBody:
        description: Update object for quote referenced by UUID in path.
        required: true
        content:
          application/json:
            schema:
                $ref: "#/components/schemas/QuoteUpdate"
      responses:
        200:
          description: OK - Specified quote updated successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: Human-readable string containing UUID of updated quote.
                    example: Updated quote b9a5a798-6505-492d-8ef3-9fa6968ab57d
        4xx:
          description: Bad Request - There was a problem with your request, please refer to the specific HTTP response code, check your request against all available documentation and try again. Problems may include missing or disallowed keys or unexpected data types in request body, missing or invalid authentication in request headers, attempting to access a record which does not exist or for which you are not authorized or rate limiting.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RequestError"
        5xx:
          description: Internal Server Error - Your request was correctly formed, however an internal server error was encountered, please try again later or contact support if the issue persists.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InternalServerError"
      security:
        - JWTBearerAuth: []
  /:merchantId/products:
    get:
      tags:
        - Products
      summary: Read multiple products
      description: Read paginated products associated with merchant specified by UUID in path.
      parameters:
        - name: merchantId
          in: path
          description: Merchant UUID.
          example: 56783305-d8ef-495b-a62c-2347ff5b54a1
          required: true
          schema:
            type: uuid
        - name: limit
          in: query
          description: Number of results to return.
          default: 10
          schema:
            type: integer
            minimum: 0
            maximum: 100
        - name: page
          in: query
          description: Page to return based on specified limit.
          default: 0
          schema:
            type: integer
            minimum: 0
      responses:
        200:
          description: OK - Products associated with specified merchant fetched successfully.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Product"
        4xx:
          description: Bad Request - There was a problem with your request, please refer to the specific HTTP response code, check your request against all available documentation and try again. Problems may include missing or disallowed keys or unexpected data types in request body, missing or invalid authentication in request headers, attempting to access a record which does not exist or for which you are not authorized or rate limiting.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RequestError"
        5xx:
          description: Internal Server Error - Your request was correctly formed, however an internal server error was encountered, please try again later or contact support if the issue persists.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InternalServerError"
      security:
        - JWTBearerAuth: []
    patch:
      tags:
        - Products
      summary: Update multiple products
      description: Update multiple products associated with merchant specified by UUID in path.
      parameters:
        - name: merchantId
          in: path
          description: Merchant UUID.
          example: 3ea63431-cec2-415f-baa8-bc453b5be80a
          required: true
          schema:
            type: uuid
      requestBody:
        description: Array of *up to* 100 update objects referencing target products by UUID.
        required: true
        content:
          application/json:
            schema:
              type: array
              items:
                $ref: "#/components/schemas/ProductUpdate"
              maxItems: 100
      responses:
        200:
          description: OK - Products associated with specified merchant updated successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: Human-readable string containing number of updated products.
                    example: Updated 50 products
        4xx:
          description: Bad Request - There was a problem with your request, please refer to the specific HTTP response code, check your request against all available documentation and try again. Problems may include missing or disallowed keys or unexpected data types in request body, missing or invalid authentication in request headers, attempting to access a record which does not exist or for which you are not authorized or rate limiting.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RequestError"
        5xx:
          description: Internal Server Error - Your request was correctly formed, however an internal server error was encountered, please try again later or contact support if the issue persists.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InternalServerError"
      security:
        - JWTBearerAuth: []
  /:merchantId/products/:productId:
    get:
      tags:
        - Products
      summary: Read single product
      description: Read single product associated with merchant specified by UUIDs in path.
      parameters:
        - name: merchantId
          in: path
          description: Merchant UUID.
          example: 113c3cc2-1bd0-4450-975e-dc9afab81659
          required: true
          schema:
            type: uuid
        - name: productId
          in: path
          description: Product UUID.
          example: 716f8fab-24d0-4da8-b94b-ee18f293c5e1
          required: true
          schema:
            type: uuid
      responses:
        200:
          description: OK - Specified product fetched successfully.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Product"
        4xx:
          description: Bad Request - There was a problem with your request, please refer to the specific HTTP response code, check your request against all available documentation and try again. Problems may include missing or disallowed keys or unexpected data types in request body, missing or invalid authentication in request headers, attempting to access a record which does not exist or for which you are not authorized or rate limiting.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RequestError"
        5xx:
          description: Internal Server Error - Your request was correctly formed, however an internal server error was encountered, please try again later or contact support if the issue persists.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InternalServerError"
      security:
        - JWTBearerAuth: []
    patch:
      tags:
        - Products
      summary: Update single product
      description: Update single product associated with merchant specified by UUIDs in path.
      parameters:
        - name: merchantId
          in: path
          description: Merchant UUID.
          example: bbe748f1-34bc-4ff1-9e63-bda3edcdee06
          required: true
          schema:
            type: uuid
        - name: productId
          in: path
          description: Product UUID.
          example: 5132780d-6a83-48c2-bc1d-0cace89335a8
          required: true
          schema:
            type: uuid
      requestBody:
        description: Update object for product referenced by UUID in path.
        required: true
        content:
          application/json:
            schema:
                $ref: "#/components/schemas/ProductUpdate"
      responses:
        200:
          description: OK - Specified product updated successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: Human-readable string containing UUID of updated product.
                    example: Updated product 5132780d-6a83-48c2-bc1d-0cace89335a8
        4xx:
          description: Bad Request - There was a problem with your request, please refer to the specific HTTP response code, check your request against all available documentation and try again. Problems may include missing or disallowed keys or unexpected data types in request body, missing or invalid authentication in request headers, attempting to access a record which does not exist or for which you are not authorized or rate limiting.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RequestError"
        5xx:
          description: Internal Server Error - Your request was correctly formed, however an internal server error was encountered, please try again later or contact support if the issue persists.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InternalServerError"
      security:
        - JWTBearerAuth: []
components:
  securitySchemes:
    JWTBearerAuth:
      description: JWT Bearer token tied to a specific merchant account with `api` scope set.
      type: http
      scheme: Bearer
      bearerFormat: JWT
  schemas:
    RequestError:
      type: object
      properties:
        message:
          type: string
          description: Human-readable error message corresponding to HTTP status code.
          default: Bad request made
          enum:
            - Bad request made
            - You are unauthenticated
            - You are unauthorized for this resource
            - Resource you requested was not found
            - Method you requested is not allowed
            - Your request timed out
            - Your request conflicts with existing data
            - Your content is too large
            - Your URI is too large
            - Your media type is unsupported
            - I'm a teapot and won't process your request
            - Upgraded protocol required
            - You have made too many requests
            - HTTP method not implemented by server
            - Service is currently unavailable
            - Server does not support HTTP version
      required:
        - message
    InternalServerError:
      type: object
      properties:
        message:
          type: string
          description: Human-readable error message corresponding to HTTP status code.
          default: Internal server error encountered
          enum:
            - Internal server error encountered
      required:
        - message
    ServerInfo:
      type: object
      properties:
        name:
          type: string
          description: Full API name.
          default: Roof-Calc Management REST API
        docs:
          type: string
          format: url
          description: API reference documentation URL.
          default: https://docs.roof-calc.co.uk/docs/api-reference/roof-calc-management-rest-api
        spec:
          type: string
          format: url
          description: OpenAPI spec download URL.
          default: https://api.roof-calc.co.uk/v1/spec
        support:
          type: string
          format: email
          description: Preferred API Support email.
          default: admin@roof-calc.co.uk
      required:
        - name
        - docs
        - spec
        - support
    Quote:
      type: object
      properties:
        uuid:
          type: string
          format: uuid
          description: Quote UUID.
          example: 3e598116-e4c4-44ed-91af-8b2bbcc7cad0
        ownerId:
          type: string
          format: uuid
          description: Controlling merchant UUID.
          example: e4918adc-61d4-4b5a-81d4-c0870e5ad846
        clientReference:
          type: string
          nullable: true
          description: Human-readable client reference for roof/project.
          example: "Garden room"
        quoteId:
          type: string
          pattern: ^([0-9A-Fa-f]{3}(-|$)){4}(?<=[0-9A-Fa-f])$
          description: Quote public ID matching format 123-ABC-890-DEF (hexadecimal).
          example: 09F-42B-C58-E57
        purchaseStatus:
          type: string
          description: Purchase status of quote updated by integration.
          default: basket
          enum:
            - saved
            - basket
            - purchased
        lineItems:
          type: array
          items:
            $ref: "#/components/schemas/LineItem" 
          description: Line items specified by calculator.
        lineItemDiffs:
          type: array
          items:
            $ref: "#/components/schemas/LineItem" 
          description: Additional line items added to quote.
        priceList:
          type: string
          nullable: true
          description: Name of price list applied to quote.
          example: Trade
        clientType:
          type: string
          nullable: true
          description: Name of client type to determine available product list.
          example: Trade
        archived:
          type: boolean
          description: Is quote archived? Archived quotes will be locked for modification and add to basket operations.
          default: false
        created_at:
          type: string
          format: date-time
          description: Date at which record created.
          example: 2026-07-06T14:05:45.995Z
        updated_at:
          type: string
          format: date-time
          description: Date at which record last updated.
          example: 2026-10-06T17:00:15.055Z
      required:
        - uuid
        - ownerId
        - clientReference
        - quoteId
        - purchaseStatus
        - lineItems
        - lineItemDiffs
        - priceList
        - clientType
        - archived
        - created_at
        - updated_at
    QuoteUpdate:
      type: object
      properties:
        uuid:
          type: string
          format: uuid
          description: Quote UUID.
          example: b2ce4db9-e0a8-4c16-995d-218b00933049
        clientReference:
          type: string
          nullable: true
          description: Human-readable client reference for roof/project.
          example: "Garden room"
        purchaseStatus:
          type: string
          description: Purchase status of quote updated by integration.
          example: basket
          enum:
            - saved
            - basket
            - purchased
        lineItemDiffs:
          type: array
          items:
            $ref: "#/components/schemas/LineItem" 
          description: Additional line items added to quote.
        archived:
          type: boolean
          description: Is quote archived? Archived quotes will be locked for modification and add to basket operations.
          example: false
      required:
        - uuid
    Product:
      type: object
      properties:
        uuid:
          type: string
          format: uuid
          description: Product UUID.
          example: 02b287c4-565c-4ec5-a364-f62e0b2d0ef1
        ownerId:
          type: string
          format: uuid
          description: Controlling merchant UUID.
          example: c9cef4c1-1589-49ab-9eff-0025a2d26615
        merchantProductId:
          type: string
          format: uuid
          nullable: true
          description: Parent merchant product UUID set if branch product differs from parent merchant product.
          example: 4cb1c1e4-4ee5-4a27-9cd7-8fd5eac740f6
        merchantSku:
          type: string
          description: Product SKU used by merchant.
          example: FP-114-055
        stocked:
          type: boolean
          description: Is product stocked by merchant?
          default: true
        stock:
          type: number
          format: float
          nullable: true
          minimum: 0
          description: Active merchant stock of product (`null` sets infinite stock). 
          default: null
        dropshipped:
          type: boolean
          description: Is product dropshipped by merchant from supplier (calculator *ignores* merchant stock if set to `true`)?
          default: false
        active:
          type: boolean
          description: Is product available to merchant from supplier?
          default: true
        purchasePrice:
          type: number
          format: float
          nullable: true
          description: Product purchase price from supplier.
          example: 2.65
        retailPrice:
          type: number
          format: float
          nullable: true
          description: Product retail price to public.
          example: 5.99
        priceLists:
          type: object
          additionalProperties:
            type: number
            format: float
            description: Discount where values between 0 and 1 represent a *percentage* discount (e.g. 0.1 is a 10% discount) and values less that 0 represent a *flat rate* discount (e.g. -5 is 5.00 GBP discount).   
          description: Object of float discounts by price list name (`Object.<string, number>`).
          default: { "Trade": 0.1 }
        currency:
          type: string
          format: ISO-4217
          description: Product currency code.
          default: GBP
        availableTo:
          type: array
          items:
            type: string
          nullable: true
          description: Client types to which product is available (`null` makes product available to anyone).
          default: null
        created_at:
          type: string
          format: date-time
          description: Date at which record created.
          example: 2026-05-06T12:15:45.745Z
        updated_at:
          type: string
          format: date-time
          description: Date at which record last updated.
          example: 2026-25-06T19:20:35.635Z
        productSku:
          type: string
          description: Product SKU used by supplier.
          example: FP-114-055
        name:
          type: string
          nullable: true
          description: Product name used in quote bill of materials.
          example: 1.14mm Standard FlexiProof One Piece EPDM Membrane - 0.55m width
        description:
          type: string
          nullable: true
          description: Detailed product description.
          example: 1.14mm Standard FlexiProof One Piece EPDM Membrane sold per linear metre to the nearest 10cm at a fixed roll width of 0.55m and up to a maximum length of 30.5m.
        imageUrl:
          type: string
          format: url
          nullable: true
          description: Default product image URL. 
          example: https://www.rubberroofingdirect.co.uk/wp-content/uploads/2021/03/One-Piece-EPDM.png
        productUrl:
          type: string
          format: url
          nullable: true
          description: Product information page URL provided by supplier.
          example: https://www.flexiproof.co.uk/one-piece-epdm
        installationUrl:
          type: string
          format: url
          nullable: true
          description: Installation video URL pertaining to product.
          example: https://www.youtube.com/watch?v=hG4A-yO6MTk"
        type:
          type: string
          description: Product type.
          example: membrane
          enum:
            - membrane
            - adhesive
            - tape
            - trim
            - corner
            - drain
            - kit
            - extra
        categories:
          type: array
          items:
            type: string
          description: Product categories within main type.
          example: ["one-piece", "standard" ]
        system:
          type: string
          description: Product roofing system.
          example: epdm
          enum:
            - epdm
        brand:
          type: string
          description: Product supplier brand.
          example: FlexiProof
          enum:
            - FlexiProof
        recommendedRetailPrice:
          type: number
          format: float
          nullable: true
          description: Product recommended retail price set by supplier.
          example: 5.99
        width:
          type: number
          format: float
          nullable: true
          description: Product width in metres (m) for one unit.
          example: null
        height:
          type: number
          format: float
          nullable: true
          description: Product height in metres (m) for one unit.
          example: null
        depth:
          type: number
          format: float
          nullable: true
          description: Product depth in metres (m) for one unit.
          example: null
        length:
          type: number
          format: float
          nullable: true
          description: Product length in metres (m) for one unit.
          example: null
        thickness:
          type: number
          format: float
          nullable: true
          description: Product thickness in millimetres (mm) for one unit.
          example: null
        volume:
          type: number
          format: float
          nullable: true
          description: Product thickness in litres (l) for one unit.
          example: null
        weight:
          type: number
          format: float
          nullable: true
          description: Product weight in kilograms (kg) for one unit.
          example: null
      required:
        - uuid
        - ownerId
        - merchantProductId
        - merchantSku
        - stocked
        - stock
        - dropshipped
        - active
        - purchasePrice
        - retailPrice
        - priceLists
        - currency
        - availableTo
        - created_at
        - updated_at
        - calculatorSku
        - productSku
        - name
        - description
        - imageUrl
        - productUrl
        - installationUrl
        - type
        - categories
        - system
        - brand
        - recommendedRetailPrice
        - width
        - height
        - depth
        - length
        - thickness
        - volume
        - weight
    ProductUpdate:
      type: object
      properties:
        uuid:
          type: string
          format: uuid
          description: Product UUID.
          example: 5484a829-b115-44b2-9750-604161c4d0ab
        stocked:
          type: boolean
          description: Is product stocked by merchant?
          example: true
        stock:
          type: number
          format: float
          nullable: true
          minimum: 0
          description: Active merchant stock of product (`null` sets infinite stock). 
          example: null
        dropshipped:
          type: boolean
          description: Is product dropshipped by merchant from supplier (calculator *ignores* merchant stock if set to `true`)?
          example: false
        purchasePrice:
          type: number
          format: float
          nullable: true
          description: Product purchase price from supplier.
          example: 3.75
        retailPrice:
          type: number
          format: float
          nullable: true
          description: Product retail price to public.
          example: 8.99
        priceLists:
          type: object
          additionalProperties:
            type: number
            format: float
            description: Discount where values between 0 and 1 represent a *percentage* discount (e.g. 0.1 is a 10% discount) and values less that 0 represent a *flat rate* discount (e.g. -5 is 5.00 GBP discount).   
          description: Object of float discounts by price list name (`Object.<string, number>`).
          example: { "Trade": 0.1 }
        availableTo:
          type: array
          items:
            type: string
          nullable: true
          description: Client types to which product is available (`null` makes product available to anyone).
          example: null
      required:
        - uuid
    MerchantIdentifiers:
      type: object
      properties:
        uuid:
          type: string
          format: uuid
          description: Merchant UUID.
          example: b3e62a9d-d3ee-4770-9eef-7d616ca52150
        ownerId:
          type: string
          format: uuid
          nullable: true
          description: Parent merchant UUID if merchant is a branch.
          example: 9ac787e1-4007-474c-b909-0e5b997692a4
        publicId:
          type: string
          pattern: ^([A-Za-z]{0,4}(-|$)){0,2}(?<=[A-Za-z]$)|^$
          description: Merchant public ID matching format XXXX-YYYY.
          example: QRGP-FWBY
        name:
          type: string
          description: Merchant name.
          example: Roof-Calc Demo
      required:
        - uuid
        - ownerId
        - publicId
        - name
    LineItem:
      type: object
      properties:
        uuid:
          type: string
          format: uuid
          description: Product UUID.
          example: 75515225-8d11-400e-8d00-47998a5398e9
        quantity:
          type: number
          format: float
          description: Product quantity (may be decimal).
          example: 2
        retailPrice:
          type: number
          format: float
          nullable: true
          description: Product retail price correct up to 4 decimal places.
          example: 15.99
        purchasePrice:
          type: number
          format: float
          nullable: true
          description: Product purchase price correct up to 4 decimal places.
          example: 8.30
    UniversalError:
      4xx:
        description: Bad Request - There was a problem with your request, please refer to the specific HTTP response code, check your request against all available documentation and try again. Problems may include missing or disallowed keys or unexpected data types in request body, missing or invalid authentication in request headers, attempting to access a record which does not exist or for which you are not authorized or rate limiting.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RequestError"
      5xx:
        description: Internal Server Error - Your request was correctly formed, however an internal server error was encountered, please try again later or contact support if the issue persists.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/InternalServerError"
tags:
  - name: API Info
    description: Metadata about API.
  - name: Merchants
    description: Identity information about merchants and branches.
  - name: Quotes
    description: Merchant quote management.
  - name: Products
    description: Merchant product management.
