> ## Documentation Index
> Fetch the complete documentation index at: https://api-docs.useopenwrench.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Append photo notes to a work order in bulk

> Appends up to 25 photo-only notes to the work order's buyer↔supplier thread in one call and sends a single grouped notification instead of one notification per photo. Each note must carry a photo URL and no other content (empty text, no video, audio, otherFile, or elements), and the same photo URL cannot appear twice in one request. Every note's noteAddedBy is set to the calling contact and noteAddedAt is overwritten with the current server time, so the batch keeps the order it was sent in. The author's email is added to the work order's buyer subscriber list.



## OpenAPI

````yaml /openapi/buyer.json patch /v1/buyer/work_order/work_orders/append_notes/bulk
openapi: 3.1.0
info:
  title: OpenWrench Buyer API
  version: 1.0.0
  description: >-
    External REST API for OpenWrench buyers (facilities-management side).
    Generated from the application source (Play routes, controllers and models).


    ## Authentication

    Every request must carry a buyer API key in the `X-API-KEY` header. The key
    resolves to a buyer contact, and all reads/writes are tenant-scoped to that
    contact's buyer company (plus, on several endpoints, role-based
    location/brand restrictions). Endpoints under `/v1/buyer/super_admin/...`
    (and a few others noted per-operation) additionally require the key's
    contact to be a buyer super admin.


    ## Rate limiting

    10 requests per 20-second window per API key; requests beyond that receive
    **429**. A handful of operations noted per-operation bypass the rate
    limiter.


    ## Response envelope

    Single-entity responses: `{ "type": "<EntityName>", "data": { ... },
    "status": "ok" }`.

    List responses: `{ "type": "<EntityName>", "data": [ ... ], "count":
    <total>, "status": "ok" }`.

    count_by responses: `{ "type": "CountBy", "data": <integer>, "status": "ok"
    }`.

    Errors: `{ "message": "...", "type": "<ExceptionType>", "status": "error",
    "traceId": "..." }` — 401 missing/invalid key, 400 bad input, 404 not found,
    429 rate limit.


    ## Pagination & filtering

    List endpoints accept `offset`, `limit` (default 10, max 25 — the locations
    list clamps to 10), `sort_by` and `order` (asc|desc). Every other query
    parameter is treated as a filter and matched against the entity's indexed
    columns (multi-value filters are comma-separated strings); these are
    combined with the tenant-security filters derived from the API key.


    Timestamps are ISO 8601 strings unless noted otherwise.


    ## Date formats

    Date-time fields serialize as strings in one of two shapes depending on the
    underlying type: ISO 8601 with offset (e.g. `2026-08-14T13:05:22.000-07:00`)
    for most timestamps, or `yyyy-MM-dd HH:mm:ss.S` (space-separated, no offset)
    for database timestamp fields. Plain dates are `yyyy-MM-dd`. When sending
    date-times, ISO 8601 is accepted.


    ## Required headers

    Every request must carry BOTH `X-API-KEY` (your API key) and `OW-KEY` (the
    OpenWrench shared secret issued with it). Requests missing either return
    401.
servers:
  - url: https://api.useopenwrench.com/api/external
security:
  - ApiKeyAuth: []
    OwKeyAuth: []
tags:
  - name: Ping
  - name: Me
  - name: Locations
  - name: Regions
  - name: Asset Types
  - name: Asset Meters
  - name: Assets
  - name: Asset Labels
    description: Read the asset label catalog and replace the labels applied to an asset.
  - name: Asset Models
  - name: Work Orders
  - name: Work Order Notes
  - name: Work Order Labels
    description: >-
      Read your work order label catalog and replace the labels applied to a
      work order.
  - name: Service Calls
  - name: Site Survey Walkthroughs
  - name: Invoices
  - name: Proposals
  - name: Files
  - name: Planned Maintenance
  - name: Currency Exchange
  - name: Supplier Network
  - name: User Provisioning
paths:
  /v1/buyer/work_order/work_orders/append_notes/bulk:
    patch:
      tags:
        - Work Order Notes
      summary: Append photo notes to a work order in bulk
      description: >-
        Appends up to 25 photo-only notes to the work order's buyer↔supplier
        thread in one call and sends a single grouped notification instead of
        one notification per photo. Each note must carry a photo URL and no
        other content (empty text, no video, audio, otherFile, or elements), and
        the same photo URL cannot appear twice in one request. Every note's
        noteAddedBy is set to the calling contact and noteAddedAt is overwritten
        with the current server time, so the batch keeps the order it was sent
        in. The author's email is added to the work order's buyer subscriber
        list.
      operationId: bulkAppendWorkOrderNotes
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: integer
                  description: Work order id.
                notes:
                  type: array
                  items:
                    $ref: '#/components/schemas/Note'
                  minItems: 1
                  maxItems: 25
                  description: >-
                    Photo-only notes to append, in the order they should appear
                    on the thread. Each entry must set photo and leave every
                    other content field empty; photo URLs must be unique within
                    the request.
              required:
                - id
                - notes
      responses:
        '200':
          description: Success.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkOrderResponse'
        '400':
          description: >-
            Validation failure: notes is empty, has more than 25 entries,
            contains a note that is not photo-only, repeats a photo URL, or the
            payload could not be parsed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Missing or invalid X-API-KEY.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Rate limit exceeded (10 requests per 20-second window per key).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    Note:
      type: object
      properties:
        text:
          type: string
        photo:
          type:
            - string
            - 'null'
        video:
          type:
            - string
            - 'null'
        audio:
          type:
            - string
            - 'null'
        otherFile:
          type:
            - string
            - 'null'
        noteAddedBy:
          type: string
          description: Email of the note author.
        noteAddedAt:
          type: string
          format: date-time
        elements:
          type:
            - array
            - 'null'
          items:
            $ref: '#/components/schemas/NoteElement'
        noteReadDetails:
          type:
            - array
            - 'null'
          items:
            $ref: '#/components/schemas/NoteReadDetail'
        noteAddedByContact:
          anyOf:
            - $ref: '#/components/schemas/Contact'
            - type: 'null'
        noteType:
          type:
            - string
            - 'null'
        noteAddedByType:
          type:
            - string
            - 'null'
        usersActiveInChat:
          type:
            - array
            - 'null'
          items:
            type: string
        s3EmailReference:
          type:
            - string
            - 'null'
        s3EmailReferenceUrl:
          type:
            - string
            - 'null'
        caption:
          type:
            - string
            - 'null'
        captionSource:
          type:
            - string
            - 'null'
        captionModel:
          type:
            - string
            - 'null'
        captionGenerationAttempted:
          type:
            - boolean
            - 'null'
        isNoteAwaitingResponse:
          type:
            - boolean
            - 'null'
        isAudioTranslated:
          type:
            - boolean
            - 'null'
        isAudioTranscriptionError:
          type:
            - boolean
            - 'null'
        siteSurveyTaskTitleId:
          type:
            - string
            - 'null'
        id:
          type:
            - integer
            - 'null'
          description: >-
            Per-note row id (populated on read where the note store is
            normalized).
      required:
        - text
        - noteAddedBy
        - noteAddedAt
    WorkOrderResponse:
      type: object
      properties:
        type:
          type: string
          description: Entity type marker, e.g. "WorkOrder".
        data:
          $ref: '#/components/schemas/WorkOrder'
        status:
          type: string
          enum:
            - ok
      required:
        - type
        - data
        - status
    Error:
      type: object
      properties:
        message:
          type: string
        type:
          type: string
          description: >-
            Exception type, e.g. unauthorizedException, NotFoundException,
            BadRequestException, ParseException, InvalidInputDataException,
            ConflictException, UnexpectedException.
        status:
          type: string
          enum:
            - error
        traceId:
          type: string
          description: >-
            Trace id (a random 11-char alphanumeric string when no explicit
            trace applies).
      required:
        - message
        - type
        - status
        - traceId
      description: >-
        Standard error envelope. 401 = missing/invalid API key, 400 = bad input,
        404 = not found, 429 = rate limit exceeded.
    NoteElement:
      type: object
      properties:
        type:
          type: string
          enum:
            - text
            - user
        value:
          type: string
        userObject:
          anyOf:
            - $ref: '#/components/schemas/Contact'
            - type: 'null'
      required:
        - type
        - value
    NoteReadDetail:
      type: object
      properties:
        readAt:
          type: string
          format: date-time
        readBy:
          type: string
        readByContact:
          anyOf:
            - $ref: '#/components/schemas/Contact'
            - type: 'null'
      required:
        - readAt
        - readBy
    Contact:
      type: object
      properties:
        email:
          type: string
        nameGiven:
          type: string
        nameFamily:
          type: string
        title:
          type:
            - string
            - 'null'
        department:
          type:
            - string
            - 'null'
        facilityId:
          type:
            - integer
            - 'null'
        contactType:
          type: string
          description: '"buyer" or "supplier".'
        isSharedContact:
          type: boolean
        readOnlyAccess:
          type:
            - boolean
            - 'null'
        invitedByEmail:
          type:
            - string
            - 'null'
        invitedAt:
          type:
            - string
            - 'null'
          format: date-time
        invitedByName:
          type:
            - string
            - 'null'
        epaCertificationType:
          type:
            - string
            - 'null'
        epaCertificationNumber:
          type:
            - string
            - 'null'
        createdAt:
          type:
            - string
            - 'null'
          format: date-time
        updatedAt:
          type:
            - string
            - 'null'
          format: date-time
      required:
        - email
        - nameGiven
        - nameFamily
        - contactType
      additionalProperties: true
      description: >-
        Contact record. Abridged: only fields observed in the provided sources
        are listed.
    WorkOrder:
      type: object
      properties:
        id:
          type:
            - integer
            - 'null'
        buyerSpecificId:
          type:
            - string
            - 'null'
        woNumber:
          type:
            - string
            - 'null'
        poNumber:
          type:
            - string
            - 'null'
        buyerProjectIds:
          type:
            - array
            - 'null'
          items:
            type: integer
        isPM:
          type: boolean
        isCapex:
          type: boolean
        isStale:
          type: boolean
        isSupplierInitiated:
          type: boolean
        isCustomerInitiated:
          type: boolean
        isWarranty:
          type: boolean
        title:
          type: string
        displayStatus:
          type: string
        status:
          type: string
        statusChangedAt:
          type:
            - string
            - 'null'
          format: date-time
        description:
          type:
            - string
            - 'null'
        descriptionNonFormatted:
          type:
            - string
            - 'null'
        assetId:
          type:
            - integer
            - 'null'
        asset:
          anyOf:
            - $ref: '#/components/schemas/Asset'
            - type: 'null'
        subAssetIds:
          type:
            - array
            - 'null'
          items:
            type: integer
        isAssetDown:
          type: boolean
        locationId:
          type: integer
        location:
          anyOf:
            - $ref: '#/components/schemas/Location'
            - type: 'null'
        areaId:
          type:
            - integer
            - 'null'
        workCategoryId:
          type:
            - integer
            - 'null'
        spendCategoryId:
          type:
            - integer
            - 'null'
        problemTypeId:
          type: integer
        problemType:
          anyOf:
            - $ref: '#/components/schemas/ProblemType'
            - type: 'null'
        woPriorityId:
          type:
            - integer
            - 'null'
        approvedOrDeniedAt:
          type:
            - string
            - 'null'
          format: date-time
        approvedOrDeniedBy:
          type:
            - string
            - 'null'
        needsApproval:
          type: boolean
        requiresSignature:
          type:
            - boolean
            - 'null'
        images:
          type: array
          items:
            type: string
        dueDate:
          type:
            - string
            - 'null'
          format: date-time
        staleAt:
          type:
            - string
            - 'null'
          format: date-time
        scheduledAt:
          type:
            - string
            - 'null'
          format: date-time
        estimatedCompletionDate:
          type:
            - string
            - 'null'
          format: date-time
        completedAt:
          type:
            - string
            - 'null'
          format: date-time
        markedCompleteBy:
          type:
            - string
            - 'null'
        expirationAt:
          type:
            - string
            - 'null'
          format: date-time
        assignedAt:
          type:
            - string
            - 'null'
          format: date-time
        supplierRespondedAt:
          type:
            - string
            - 'null'
          format: date-time
        supplierFacilityId:
          type:
            - integer
            - 'null'
        supplierFacility:
          anyOf:
            - $ref: '#/components/schemas/SupplierFacility'
            - type: 'null'
        supplierPrimaryContactEmail:
          type:
            - string
            - 'null'
        price:
          type:
            - number
            - 'null'
        currencyId:
          type: string
        terms:
          type:
            - string
            - 'null'
        notes:
          type: array
          items:
            $ref: '#/components/schemas/Note'
        lastNote:
          type:
            - string
            - 'null'
        lastNoteAddedBy:
          type:
            - string
            - 'null'
        lastNoteAddedAt:
          type:
            - integer
            - 'null'
          description: Epoch milliseconds.
        nte:
          type:
            - number
            - 'null'
          description: Not-to-exceed amount.
        statusChanges:
          type: array
          items:
            $ref: '#/components/schemas/StatusChange'
        buyerFacilityId:
          type: integer
        buyerCompanyId:
          type: integer
        createdBy:
          type: string
        submittedByName:
          type:
            - string
            - 'null'
        buyerSubscriberEmails:
          type: array
          items:
            type: string
        supplierSubscriberEmails:
          type: array
          items:
            type: string
        associatedServiceCalls:
          type: array
          items:
            $ref: '#/components/schemas/ServiceCall'
        lastServiceCall:
          anyOf:
            - $ref: '#/components/schemas/ServiceCall'
            - type: 'null'
        hasBuyerArchived:
          type: boolean
        hasSupplierArchived:
          type: boolean
        buyerAttachments:
          type: array
          items:
            $ref: '#/components/schemas/FileDetails'
        supplierAttachments:
          type: array
          items:
            $ref: '#/components/schemas/FileDetails'
        resolutionTypeId:
          type:
            - integer
            - 'null'
        plannedMaintenanceScheduleId:
          type:
            - integer
            - 'null'
        walkThroughId:
          type:
            - integer
            - 'null'
        cancelledAt:
          type:
            - string
            - 'null'
          format: date-time
        cancelledBy:
          type:
            - string
            - 'null'
        isPrivate:
          type: boolean
        fromRequestPortal:
          type: boolean
        fromClientPortal:
          type: boolean
        glCode:
          type:
            - string
            - 'null'
        createdAt:
          type:
            - string
            - 'null'
          format: date-time
        updatedAt:
          type:
            - string
            - 'null'
          format: date-time
        isDeleted:
          type: boolean
        deletedAt:
          type:
            - string
            - 'null'
          format: date-time
      required:
        - title
        - displayStatus
        - status
        - locationId
        - problemTypeId
        - buyerFacilityId
        - buyerCompanyId
        - createdBy
        - currencyId
        - isDeleted
      additionalProperties: true
      description: >-
        Work order. ABRIDGED: the full case class has 150+ fields (hydrated
        approval hierarchies, budgets, troubleshooting answers,
        contractor/sub-contractor details, internal workspaces, labels, stars,
        etc.); only the commonly used fields are listed here and additional
        properties may appear in responses.
    Asset:
      type: object
      properties:
        id:
          type:
            - integer
            - 'null'
        buyerSpecificAssetId:
          type:
            - string
            - 'null'
        assetUUID:
          type:
            - string
            - 'null'
        isUserAssignedUUID:
          type: boolean
        assetNumber:
          type:
            - string
            - 'null'
        name:
          type: string
        description:
          type:
            - string
            - 'null'
        images:
          type: array
          items:
            type: string
        attachments:
          type: array
          items:
            $ref: '#/components/schemas/FileDetails'
        manufacturer:
          type:
            - string
            - 'null'
        upcNumber:
          type:
            - string
            - 'null'
        modelNumber:
          type:
            - string
            - 'null'
        serialNumber:
          type:
            - string
            - 'null'
        assetTypeId:
          type: integer
        assetType:
          anyOf:
            - $ref: '#/components/schemas/AssetType'
            - type: 'null'
        assetModelId:
          type:
            - integer
            - 'null'
        assetModel:
          anyOf:
            - $ref: '#/components/schemas/AssetModel'
            - type: 'null'
        assetTypeDetails:
          type: array
          items:
            $ref: '#/components/schemas/FieldTypeDetails'
        locationId:
          type: integer
        location:
          anyOf:
            - $ref: '#/components/schemas/Location'
            - type: 'null'
        areaId:
          type:
            - integer
            - 'null'
        brand:
          type:
            - string
            - 'null'
        installDate:
          type:
            - string
            - 'null'
          format: date-time
        purchaseDate:
          type:
            - string
            - 'null'
          format: date-time
        isActive:
          type: boolean
        isLeased:
          type: boolean
        leaseStartDate:
          type:
            - string
            - 'null'
          format: date-time
        leaseEndDate:
          type:
            - string
            - 'null'
          format: date-time
        warrantyIds:
          type: array
          items:
            type: integer
        lifeExpectancyInMonths:
          type:
            - integer
            - 'null'
        originalPrice:
          type:
            - number
            - 'null'
        capitalisedCost:
          type:
            - number
            - 'null'
        assetTags:
          type: array
          items:
            type: string
        parentId:
          type:
            - integer
            - 'null'
        availabilityStatus:
          type:
            - string
            - 'null'
        downtimeStatus:
          type:
            - string
            - 'null'
          enum:
            - online
            - offline
        additionalAssetDetails:
          anyOf:
            - $ref: '#/components/schemas/AdditionalAssetDetails'
            - type: 'null'
        daysInUse:
          type:
            - integer
            - 'null'
        isRefrigerantTracked:
          type: boolean
        refrigerantTypeCode:
          type:
            - string
            - 'null'
        fullChargeLb:
          type:
            - number
            - 'null'
        applianceCategory:
          type:
            - string
            - 'null'
        buyerFacilityId:
          type: integer
        buyerCompanyId:
          type: integer
        subAssetCount:
          type:
            - integer
            - 'null'
        totalWOCount:
          type:
            - integer
            - 'null'
        totalNotClosedWOCount:
          type:
            - integer
            - 'null'
        createdAt:
          type:
            - string
            - 'null'
          format: date-time
        updatedAt:
          type:
            - string
            - 'null'
          format: date-time
        isDeleted:
          type: boolean
        deletedAt:
          type:
            - string
            - 'null'
          format: date-time
      required:
        - name
        - assetTypeId
        - locationId
        - isUserAssignedUUID
        - isActive
        - isLeased
        - isRefrigerantTracked
        - buyerFacilityId
        - buyerCompanyId
        - isDeleted
      additionalProperties: true
      description: >-
        Asset. ABRIDGED: the full case class carries further fields (warranties,
        depreciation, spend rollups, meters, refrigerant retrofit plan,
        equipment/purchase-order links, etc.) that may appear in responses.
    Location:
      type: object
      properties:
        id:
          type:
            - integer
            - 'null'
        storeId:
          type:
            - string
            - 'null'
        name:
          type: string
        brandId:
          type:
            - integer
            - 'null'
        brandAssetGroupId:
          type:
            - integer
            - 'null'
        allAssetCount:
          type:
            - integer
            - 'null'
        description:
          type:
            - string
            - 'null'
        isActive:
          type: boolean
        openDate:
          type:
            - string
            - 'null'
          format: date-time
        closeDate:
          type:
            - string
            - 'null'
          format: date-time
        operatingHours:
          anyOf:
            - $ref: '#/components/schemas/OperatingHours'
            - type: 'null'
        phoneNumber:
          type:
            - string
            - 'null'
        locationTypeId:
          type: integer
        locationTypeDetails:
          type: array
          items:
            $ref: '#/components/schemas/FieldTypeDetails'
        notes:
          type:
            - string
            - 'null'
        notesNonFormatted:
          type:
            - string
            - 'null'
        internalNotes:
          type:
            - string
            - 'null'
        images:
          type: array
          items:
            type: string
        internalAttachments:
          type: array
          items:
            $ref: '#/components/schemas/FileDetails'
        primaryContactsEmails:
          type: array
          items:
            type: string
        facilityInChargeEmails:
          type: array
          items:
            type: string
        sendApprovedInvoicesToEmails:
          type: array
          items:
            type: string
        sendApprovedQuotesToEmails:
          type: array
          items:
            type: string
        storeAssociateEmails:
          type: array
          items:
            type: string
        fieldTechEmails:
          type: array
          items:
            type: string
        timeZoneId:
          type:
            - string
            - 'null'
        hasPresetAssetUUID:
          type:
            - boolean
            - 'null'
        regionId:
          type:
            - integer
            - 'null'
        region:
          anyOf:
            - $ref: '#/components/schemas/Region'
            - type: 'null'
        purchaseOrderPrefix:
          type:
            - string
            - 'null'
        isLeased:
          type:
            - boolean
            - 'null'
        leaseStartDate:
          type:
            - string
            - 'null'
          format: date-time
        leaseEndDate:
          type:
            - string
            - 'null'
          format: date-time
        taxRate:
          type:
            - string
            - 'null'
        customFieldDetails:
          type:
            - array
            - 'null'
          items:
            $ref: '#/components/schemas/FieldTypeDetails'
        buildingWarrantyStartDate:
          type:
            - string
            - 'null'
          format: date-time
        buildingWarrantyExpirationDate:
          type:
            - string
            - 'null'
          format: date-time
        buildingWarrantyProblemTypeIds:
          type:
            - array
            - 'null'
          items:
            type: integer
        buildingWarrantyServiceProviderId:
          type:
            - integer
            - 'null'
        invoicesBillTo:
          anyOf:
            - $ref: '#/components/schemas/InvoicesBillTo'
            - type: 'null'
        countryCode:
          type:
            - string
            - 'null'
        buyerFacilityId:
          type: integer
        buyerCompanyId:
          type: integer
        totalWOCount:
          type:
            - integer
            - 'null'
        totalNotClosedWOCount:
          type:
            - integer
            - 'null'
        createdAt:
          type:
            - string
            - 'null'
          format: date-time
        updatedAt:
          type:
            - string
            - 'null'
          format: date-time
        isDeleted:
          type: boolean
        deletedAt:
          type:
            - string
            - 'null'
          format: date-time
      required:
        - name
        - isActive
        - locationTypeId
        - buyerFacilityId
        - buyerCompanyId
        - isDeleted
      additionalProperties: true
      description: >-
        Location. Abridged: hydrated contact/settings arrays and
        brand/facility/company objects may also appear in responses.
    ProblemType:
      type: object
      properties:
        id:
          type:
            - integer
            - 'null'
        name:
          type: string
      additionalProperties: true
      description: >-
        Work order problem type. Abridged: full model not in the provided
        sources.
    SupplierFacility:
      type: object
      properties:
        id:
          type:
            - integer
            - 'null'
        name:
          type: string
        displayName:
          type: string
        status:
          type: string
        currencyId:
          type: string
        isClaimed:
          type: boolean
        about:
          type:
            - string
            - 'null'
        isNationalSupplier:
          type: boolean
        operatingHours:
          anyOf:
            - $ref: '#/components/schemas/OperatingHours'
            - type: 'null'
        w9:
          anyOf:
            - $ref: '#/components/schemas/FileDetails'
            - type: 'null'
        verifications:
          type: array
          items:
            type: object
            properties: {}
            additionalProperties: true
        licenses:
          type: array
          items:
            type: object
            properties: {}
            additionalProperties: true
        certifications:
          type: array
          items:
            type: object
            properties: {}
            additionalProperties: true
        insurances:
          type: array
          items:
            type: object
            properties: {}
            additionalProperties: true
        faqs:
          type: array
          items:
            type: object
            properties: {}
            additionalProperties: true
        isWomenOwned:
          type: boolean
        isMinorityOwned:
          type: boolean
        isVeteranOwned:
          type: boolean
        isDisabledOwned:
          type: boolean
        isLgbtOwned:
          type: boolean
        isSmallBusinessEnterprise:
          type: boolean
        categoryIds:
          type: array
          items:
            type: integer
        categoryNames:
          type: string
        duns:
          type:
            - string
            - 'null'
        taxId:
          type:
            - string
            - 'null'
        corporateURL:
          type:
            - string
            - 'null'
        storefrontURL:
          type:
            - string
            - 'null'
        logoURL:
          type:
            - string
            - 'null'
        poMethod:
          type:
            - string
            - 'null'
        poChangeMethod:
          type:
            - string
            - 'null'
        poEmail:
          type:
            - string
            - 'null'
        website:
          type:
            - string
            - 'null'
        primaryContactEmail:
          type:
            - string
            - 'null'
        primaryPhone:
          type:
            - string
            - 'null'
        primaryAddress:
          anyOf:
            - $ref: '#/components/schemas/Address'
            - type: 'null'
        remitToAddress:
          anyOf:
            - $ref: '#/components/schemas/Address'
            - type: 'null'
        latitude:
          type:
            - number
            - 'null'
        longitude:
          type:
            - number
            - 'null'
        radiusOfServiceInMiles:
          type:
            - number
            - 'null'
        serviceAreaSelfPerforming:
          type: array
          items:
            type: string
        serviceAreaNotSelfPerforming:
          type: array
          items:
            type: string
        averageRating:
          type:
            - number
            - 'null'
        numRatings:
          type:
            - integer
            - 'null'
        supplierCompanyId:
          type: integer
        isLandlord:
          type: boolean
      required:
        - name
        - displayName
        - status
        - currencyId
        - supplierCompanyId
        - isLandlord
      additionalProperties: true
      description: >-
        Supplier facility. Abridged: parsed service-area addresses, business
        codes, social media, webhook details and review tag rollups may also
        appear.
    StatusChange:
      type: object
      properties:
        statusText:
          type: string
        statusChangeAt:
          type: string
          format: date-time
      required:
        - statusText
        - statusChangeAt
    ServiceCall:
      type: object
      properties:
        id:
          type:
            - integer
            - 'null'
        leadTechnicianEmail:
          type:
            - string
            - 'null'
        leadTechnicianEmailContact:
          anyOf:
            - $ref: '#/components/schemas/Contact'
            - type: 'null'
        additionalTechnicianEmails:
          type: array
          items:
            type: string
        additionalTechnicians:
          type: array
          items:
            $ref: '#/components/schemas/Contact'
        stockLocationIds:
          type: array
          items:
            type: integer
        stockLocations:
          type: array
          items:
            type: object
            properties: {}
            additionalProperties: true
        supplierFacilityId:
          type: integer
        supplierFacility:
          anyOf:
            - $ref: '#/components/schemas/SupplierFacility'
            - type: 'null'
        serviceScheduledAt:
          type:
            - string
            - 'null'
          format: date-time
        checkInByEmail:
          type:
            - string
            - 'null'
        checkInByContact:
          anyOf:
            - $ref: '#/components/schemas/Contact'
            - type: 'null'
        checkInStatus:
          type:
            - string
            - 'null'
        checkInTime:
          type:
            - string
            - 'null'
          format: date-time
        checkInNotes:
          type:
            - string
            - 'null'
        checkInImages:
          type: array
          items:
            type: string
        checkInImagesWithCaption:
          type: array
          items:
            $ref: '#/components/schemas/Image'
        checkInGeoLocation:
          anyOf:
            - $ref: '#/components/schemas/ServiceLatLong'
            - type: 'null'
        checkInAudio:
          type:
            - string
            - 'null'
        checkInAudioTranscription:
          type:
            - string
            - 'null'
        checkInIsAudioTranslated:
          type:
            - boolean
            - 'null'
        checkInIsAudioTranscriptionError:
          type:
            - boolean
            - 'null'
        checkOutByEmail:
          type:
            - string
            - 'null'
        checkOutByContact:
          anyOf:
            - $ref: '#/components/schemas/Contact'
            - type: 'null'
        checkOutStatus:
          type:
            - string
            - 'null'
        checkOutTime:
          type:
            - string
            - 'null'
          format: date-time
        checkOutNotes:
          type:
            - string
            - 'null'
        checkOutImages:
          type: array
          items:
            type: string
        checkOutImagesWithCaption:
          type: array
          items:
            $ref: '#/components/schemas/Image'
        checkOutGeoLocation:
          anyOf:
            - $ref: '#/components/schemas/ServiceLatLong'
            - type: 'null'
        checkOutAudio:
          type:
            - string
            - 'null'
        checkOutAudioTranscription:
          type:
            - string
            - 'null'
        checkOutIsAudioTranslated:
          type:
            - boolean
            - 'null'
        checkOutIsAudioTranscriptionError:
          type:
            - boolean
            - 'null'
        numberOfTechs:
          type: integer
        workOrderId:
          type: integer
        locationId:
          type: integer
        buyerFacilityId:
          type: integer
        buyerCompanyId:
          type: integer
        revisionChanges:
          type:
            - array
            - 'null'
          items:
            type: object
            properties: {}
            additionalProperties: true
        createdAt:
          type:
            - string
            - 'null'
          format: date-time
        updatedAt:
          type:
            - string
            - 'null'
          format: date-time
        isDeleted:
          type: boolean
        deletedAt:
          type:
            - string
            - 'null'
          format: date-time
      required:
        - supplierFacilityId
        - numberOfTechs
        - workOrderId
        - locationId
        - buyerFacilityId
        - buyerCompanyId
        - isDeleted
    FileDetails:
      type: object
      properties:
        fileName:
          type: string
          description: Original file name (non-ASCII characters stripped on upload).
        fileId:
          type: string
          description: Opaque file identifier used for later download.
      required:
        - fileName
        - fileId
      description: 'File reference: name plus storage identifier.'
    AssetType:
      type: object
      properties:
        id:
          type:
            - integer
            - 'null'
        name:
          type: string
        primarySpendCategory:
          type:
            - integer
            - 'null'
        attachments:
          type: array
          items:
            $ref: '#/components/schemas/FileDetails'
        allProblemTypeIds:
          type: array
          items:
            type: integer
        allProblemTypeIdsAsString:
          type: string
        allProblemTypes:
          type:
            - array
            - 'null'
          items:
            $ref: '#/components/schemas/ProblemType'
        allProblemTypesName:
          type:
            - string
            - 'null'
        allSpendCategories:
          type: array
          items:
            type: integer
        depreciationClassId:
          type:
            - integer
            - 'null'
        depreciationClassName:
          type:
            - string
            - 'null'
        requiredFields:
          type: array
          items:
            $ref: '#/components/schemas/FieldType'
        optionalFields:
          type: array
          items:
            $ref: '#/components/schemas/FieldType'
        replaceMarkupOnOriginalCost:
          type:
            - number
            - 'null'
        replacementThreshold:
          type:
            - number
            - 'null'
        usesRefrigerant:
          type: boolean
        applianceCategory:
          type:
            - string
            - 'null'
        refrigerantTypeCode:
          type:
            - string
            - 'null'
        fullChargeLb:
          type:
            - number
            - 'null'
        buyerCompanyId:
          type: integer
        createdAt:
          type:
            - string
            - 'null'
          format: date-time
        updatedAt:
          type:
            - string
            - 'null'
          format: date-time
        isDeleted:
          type: boolean
        deletedAt:
          type:
            - string
            - 'null'
          format: date-time
      required:
        - name
        - buyerCompanyId
        - usesRefrigerant
        - isDeleted
      additionalProperties: true
    AssetModel:
      type: object
      properties:
        id:
          type:
            - integer
            - 'null'
        modelName:
          type: string
        manuals:
          type: array
          items:
            $ref: '#/components/schemas/FileDetails'
        specs:
          type: array
          items:
            $ref: '#/components/schemas/AssetSpec'
        assetTypeId:
          type: integer
        assetType:
          anyOf:
            - $ref: '#/components/schemas/AssetType'
            - type: 'null'
        buyerCompanyId:
          type: integer
        createdAt:
          type:
            - string
            - 'null'
          format: date-time
        updatedAt:
          type:
            - string
            - 'null'
          format: date-time
        isDeleted:
          type: boolean
        deletedAt:
          type:
            - string
            - 'null'
          format: date-time
      required:
        - modelName
        - assetTypeId
        - buyerCompanyId
        - isDeleted
    FieldTypeDetails:
      type: object
      properties:
        key:
          type: string
        valueAsString:
          type: string
        valueType:
          type: string
      required:
        - key
        - valueAsString
        - valueType
    AdditionalAssetDetails:
      type: object
      properties:
        energyEfficiencyDetails:
          type:
            - string
            - 'null'
        capacityDetails:
          type:
            - string
            - 'null'
        hasLeakDetector:
          type:
            - boolean
            - 'null'
        usesRefrigerant:
          type:
            - boolean
            - 'null'
        refrigerantDetails:
          type:
            - string
            - 'null'
    OperatingHours:
      type: object
      properties:
        timeZoneId:
          type:
            - string
            - 'null'
        timeZoneName:
          type:
            - string
            - 'null'
        Monday:
          anyOf:
            - $ref: '#/components/schemas/Timings'
            - type: 'null'
        Tuesday:
          anyOf:
            - $ref: '#/components/schemas/Timings'
            - type: 'null'
        Wednesday:
          anyOf:
            - $ref: '#/components/schemas/Timings'
            - type: 'null'
        Thursday:
          anyOf:
            - $ref: '#/components/schemas/Timings'
            - type: 'null'
        Friday:
          anyOf:
            - $ref: '#/components/schemas/Timings'
            - type: 'null'
        Saturday:
          anyOf:
            - $ref: '#/components/schemas/Timings'
            - type: 'null'
        Sunday:
          anyOf:
            - $ref: '#/components/schemas/Timings'
            - type: 'null'
    Region:
      type: object
      properties:
        id:
          type:
            - integer
            - 'null'
        name:
          type: string
        buyerCompanyId:
          type: integer
        hierarchyName:
          type:
            - string
            - 'null'
        parentId:
          type:
            - integer
            - 'null'
        hasChildren:
          type: boolean
        createdAt:
          type:
            - string
            - 'null'
          format: date-time
        updatedAt:
          type:
            - string
            - 'null'
          format: date-time
        isDeleted:
          type: boolean
        deletedAt:
          type:
            - string
            - 'null'
          format: date-time
      required:
        - name
        - buyerCompanyId
        - hasChildren
        - isDeleted
    InvoicesBillTo:
      type: object
      properties:
        billTo:
          type: string
        serviceAddress:
          type: object
          properties: {}
          additionalProperties: true
      required:
        - billTo
        - serviceAddress
    Address:
      type: object
      properties: {}
      additionalProperties: true
      description: Postal address object. Shape abridged (model not in provided sources).
    Image:
      type: object
      properties:
        s3ObjectKey:
          type: string
        caption:
          type:
            - string
            - 'null'
        captionSource:
          type:
            - string
            - 'null'
        captionModel:
          type:
            - string
            - 'null'
        createdAt:
          type:
            - string
            - 'null'
          format: date-time
        createdBy:
          type:
            - string
            - 'null'
        updatedAt:
          type:
            - string
            - 'null'
          format: date-time
      required:
        - s3ObjectKey
    ServiceLatLong:
      type: object
      properties:
        lat:
          type: string
        long:
          type: string
      required:
        - lat
        - long
    FieldType:
      type: object
      properties: {}
      additionalProperties: true
      description: >-
        Field type definition for asset type required/optional fields. Shape
        abridged (model not in provided sources).
    AssetSpec:
      type: object
      properties:
        key:
          type: string
        value:
          type:
            - string
            - 'null'
      required:
        - key
    Timings:
      type: object
      properties: {}
      additionalProperties: true
      description: Opening/closing timings for one weekday. Shape abridged.
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-KEY
    OwKeyAuth:
      type: apiKey
      in: header
      name: OW-KEY
      description: >-
        OpenWrench shared secret. Required on every request alongside X-API-KEY;
        issued together with your API key.

````