openapi: 3.0.3
info:
  title: Orderwerks REST API
  version: '1.19'
  description: >
    The Orderwerks REST API lets integrators read and write customers (vendors),
    catalogs, catalog items,

    price groups and orders for a supplier account.


    # Authentication


    Every request must carry one of two header sets. Each endpoint lists which
    set it accepts under

    **Authorizations**.


    **API key and secret** (recommended for integrations): send `x-apiKey` and
    `x-apiSecret`. Requests

    authenticated this way run as the supplier's master user. Add a `vendorGuid`
    header to act in the

    context of one customer, and optionally a `userGuid` header to attribute the
    call to a specific user.


    **User session headers** (used by the Orderwerks web and mobile apps): send
    `userGuid`, `userToken`

    (the JWT issued at login) and `supplierGuid`, plus `vendorGuid` when acting
    for a customer.


    API keys are created in the Orderwerks web app under Business Settings. The
    secret is shown once, at creation.


    # Conventions


    - Paths are versioned per resource (`/v1/...`, `/v2/...`); a few legacy
    paths have no version segment.

    - Responses are JSON. There is no common envelope; each endpoint documents
    its own shape.

    - Paged list endpoints take `limit` (default 25, maximum 100) and `offset`.
    `offset` is a **page number**,
      not a row count: the server skips `offset * limit` rows.
    - Delta sync: list endpoints that return `serverTimestamp` accept it back as
    `lastUpdatedAt` on the next
      call to fetch only rows changed since then. Soft-deleted rows are included in delta responses with
      `deleted_at` set.
    - Errors return `4xx`/`5xx` with a JSON body of the form `{ "message": "..."
    }`. A few legacy endpoints
      return a plain-text message instead; those are noted individually.

    # Terminology


    Orderwerks calls the business operating the account the **supplier**, and
    the customers who place orders

    **vendors** (also "accounts" or "customers" in the apps). Vendor endpoints
    are customer endpoints.
  x-logo:
    url: https://www.orderwerks.com/assets/images/orderwerks-stacked-logo-grey.svg
    altText: Orderwerks
servers:
  - url: https://owapi.orderwerks.com
    description: Production
security:
  - ApiKey: []
    ApiSecret: []
  - UserGuid: []
    UserToken: []
    SupplierGuid: []
tags:
  - name: Vendors
    description: >
      Customers of the supplier (called vendors, accounts or customers in the
      Orderwerks apps). A vendor

      carries its billing and shipping addresses, price group, payment terms and
      integration identifiers.
  - name: Catalogs
    description: >-
      A catalog is a priced product list. Every catalog item, price group and
      order belongs to one catalog.
  - name: Catalog Items
    description: >
      Products within a catalog. Pricing is a JSON object keyed by price group
      name; a value of `"N/A"` means

      the item is not offered to that price group.
  - name: Price Groups
    description: >-
      Named price levels within a catalog (for example `Retail`, `Wholesale`).
      Each vendor is assigned one.
  - name: Orders
    description: >
      Sales orders. Orders are created in the `PRELIMINARY` state and, unless
      `remainInPreliminary` is set, are

      submitted automatically into the supplier's workflow.
x-tagGroups:
  - name: Customers
    tags:
      - Vendors
  - name: Catalog
    tags:
      - Catalogs
      - Catalog Items
      - Price Groups
  - name: Orders
    tags:
      - Orders
paths:
  /vendors:
    get:
      tags:
        - Vendors
      operationId: listVendors
      summary: List customers
      description: >
        Returns the supplier's customers (vendors) as a paged list of
        supplier-to-customer connections; the customer

        record is under `Vendor` on each row. Requires supplier-level access.


        Supports delta sync: pass the returned `serverTimestamp` back as
        `lastUpdatedAt` to receive only customers

        changed since then.
      parameters:
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Offset'
        - $ref: '#/components/parameters/LastUpdatedAt'
        - in: query
          name: name
          schema:
            type: string
          description: Filter by customer name (contains match).
        - in: query
          name: category
          schema:
            type: string
          description: Filter by customer category.
        - in: query
          name: state_license
          schema:
            type: string
          description: Filter by state license number.
        - in: query
          name: filter_inactive
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
          description: Exclude inactive customers.
        - in: query
          name: filterInactive
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
          description: Alias of `filter_inactive`.
        - in: query
          name: order_by
          schema:
            type: string
          description: Column to sort by (for example `name`).
        - in: query
          name: order_dir
          schema:
            type: string
            enum:
              - asc
              - desc
        - in: query
          name: nameGuidOnly
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
          description: >-
            Return only `id`, `guid` and `name` for each customer (faster for
            pickers).
      responses:
        '200':
          description: A page of customers.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VendorListResponse'
        '400':
          description: >-
            Bad request. `code` is `INVALID_DELTA_CURSOR` when `lastUpdatedAt`
            cannot be parsed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      tags:
        - Vendors
      operationId: createVendor
      summary: Create a customer
      description: >
        Creates a customer (vendor) with optional billing address, shipping
        address, primary contact and account note,

        without an order. Idempotent on supplier + `newVendor.email`: a retry
        after a lost response returns the existing

        customer's references instead of creating a duplicate.


        Accepts user session headers only. Contact support to request API key
        access for this endpoint.
      security:
        - UserGuid: []
          UserToken: []
          SupplierGuid: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateVendorRequest'
            example:
              newVendor:
                name: Acme, Inc.
                email: orders@acme.example
                phone: 555-0100
                customer_internal_id: ACME-001
              newVendorBillTo:
                name: Accounts Payable
                company_name: Acme, Inc.
                address_line_one: 123 Any Street
                city: Anytown
                state: CA
                postal_code: '12345'
                country: US
              newVendorShipTo:
                name: Receiving
                company_name: Acme, Inc.
                address_line_one: 400 Warehouse Road
                city: Anytown
                state: CA
                postal_code: '12345'
                country: US
              newVendorContact:
                name: Jane Doe
                email: jane@acme.example
      responses:
        '200':
          description: The created (or matched) customer.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateVendorResponse'
        '400':
          description: Validation failure (`newVendor` or `newVendor.name` missing).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReconcileErrors'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/vendors/{vendorGuid}:
    get:
      tags:
        - Vendors
      operationId: getVendor
      summary: Get a customer
      description: >-
        Returns one customer (vendor) with its addresses, integration links and
        shipping preferences.
      parameters:
        - $ref: '#/components/parameters/VendorGuidPath'
      responses:
        '200':
          description: The customer.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Vendor'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
    put:
      tags:
        - Vendors
      operationId: updateVendor
      summary: Update a customer
      description: >
        Updates a customer's name, email, addresses and settings. `name` and
        `email` are required; everything else is

        optional and left unchanged when omitted.


        Accepts user session headers only. Contact support to request API key
        access for this endpoint.
      security:
        - UserGuid: []
          UserToken: []
          SupplierGuid: []
      parameters:
        - $ref: '#/components/parameters/VendorGuidPath'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateVendorRequest'
            example:
              name: Acme, Inc.
              email: orders@acme.example
              options:
                price_group_id: 12
                require_po: true
      responses:
        '200':
          description: The updated customer.
          content:
            application/json:
              schema:
                type: object
                properties:
                  vendorModel:
                    $ref: '#/components/schemas/Vendor'
                  resource:
                    type: string
                    example: vendor
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
  /v1/catalogs:
    get:
      tags:
        - Catalogs
      operationId: listCatalogs
      summary: List catalogs
      description: >
        Returns the catalogs visible to the caller. Supplier users see every
        catalog; a customer context (`vendorGuid`)

        narrows the list to the catalogs that customer may order from.
      parameters:
        - $ref: '#/components/parameters/VendorGuidHeader'
        - in: query
          name: vendorGuid
          schema:
            type: string
            format: uuid
          description: Customer context, as an alternative to the `vendorGuid` header.
        - in: query
          name: onlyActive
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
          description: Return active catalogs only.
        - in: query
          name: checkIfHasCategories
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
          description: >-
            Also return `catalogsDetails` with a `hasCategories` flag per
            catalog.
        - in: query
          name: includeDeletedPriceGroups
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
          description: Include soft-deleted price groups under each catalog.
      responses:
        '200':
          description: The catalogs.
          content:
            application/json:
              schema:
                type: object
                properties:
                  catalogs:
                    type: array
                    items:
                      $ref: '#/components/schemas/Catalog'
                  resource:
                    type: string
                    example: Catalog
                  catalogsDetails:
                    type: array
                    description: Present when `checkIfHasCategories=true`.
                    items:
                      type: object
                      properties:
                        catalogGuid:
                          type: string
                          format: uuid
                        catalogName:
                          type: string
                        catalogId:
                          type: integer
                        hasCategories:
                          type: boolean
                required:
                  - catalogs
                  - resource
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
  /v1/catalog/{catalogGuid}/catalog_items:
    get:
      tags:
        - Catalog Items
      operationId: listCatalogItems
      summary: List catalog items
      description: >
        Paged list of the items in a catalog. With API key authentication each
        item carries the fixed field set shown

        in the schema; with user session headers the full item model is
        returned.


        Supports delta sync: pass the returned `serverTimestamp` back as
        `lastUpdatedAt` to receive only items created,

        updated or deleted since then (deleted items carry `deleted_at`).
      parameters:
        - $ref: '#/components/parameters/CatalogGuidPath'
        - $ref: '#/components/parameters/VendorGuidHeader'
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Offset'
        - $ref: '#/components/parameters/LastUpdatedAt'
        - in: query
          name: skipTotalCount
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
          description: >-
            Skip the total count query; `totalCatalogItems` is then 0. Faster
            for large catalogs.
        - in: query
          name: skipCategoryRetrieval
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
          description: Do not attach `Category` / `CategoryHierarchy` to each item.
        - in: query
          name: includeAttributes
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
          description: Include item attributes.
      responses:
        '200':
          description: A page of catalog items.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CatalogItemsPage'
        '400':
          description: >-
            Unknown catalog GUID, or `code` is `INVALID_DELTA_CURSOR` when
            `lastUpdatedAt` cannot be parsed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/catalog/{catalogGuid}/catalog_items/{catalogItemGuid}:
    get:
      tags:
        - Catalog Items
      operationId: getCatalogItem
      summary: Get a catalog item
      description: >-
        Returns one catalog item with its category, attachments, options and
        attributes.
      parameters:
        - $ref: '#/components/parameters/CatalogGuidPath'
        - $ref: '#/components/parameters/CatalogItemGuidPath'
        - $ref: '#/components/parameters/VendorGuidHeader'
      responses:
        '200':
          description: The catalog item.
          content:
            application/json:
              schema:
                type: object
                properties:
                  catalog_item:
                    $ref: '#/components/schemas/CatalogItem'
                  resource:
                    type: string
                    example: catalog_item
                required:
                  - catalog_item
                  - resource
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/catalog/{catalogGuid}/catalog_items/batch:
    post:
      tags:
        - Catalog Items
      operationId: getCatalogItemsByBatch
      summary: Get catalog items by ids or GUIDs
      description: >-
        Returns the requested items in one call. Unknown ids are skipped, not
        reported.
      parameters:
        - $ref: '#/components/parameters/CatalogGuidPath'
        - $ref: '#/components/parameters/VendorGuidHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BatchRequest'
      responses:
        '200':
          description: The matching catalog items.
          content:
            application/json:
              schema:
                type: object
                properties:
                  catalog_items:
                    type: array
                    items:
                      $ref: '#/components/schemas/CatalogItem'
                  resource:
                    type: string
                    example: catalog_items
                required:
                  - catalog_items
                  - resource
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/catalog/{catalogGuid}/catalog_items/typeahead:
    post:
      tags:
        - Catalog Items
      operationId: searchCatalogItems
      summary: Search catalog items
      description: >
        Full-text search over a catalog (name, SKU, description, UPC) with
        optional category, price-group and attribute

        filters. This is the endpoint the order-entry screens use.


        When `priceGroupGuid` or `orderGuid` is given, items not offered to that
        price group are excluded and each

        item's `pricing` is reduced to that single price. A 12-digit numeric
        `name` performs a UPC lookup instead of a

        text search.
      parameters:
        - $ref: '#/components/parameters/CatalogGuidPath'
        - $ref: '#/components/parameters/VendorGuidHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TypeaheadRequest'
            example:
              name: widget
              limit: 10
              offset: 0
              onlyActive: true
              includeTotal: true
              priceGroupGuid: 0f5a4b1e-1c9c-4d1a-9b8e-6f4a2a3c1d10
      responses:
        '200':
          description: Matching catalog items.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TypeaheadResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/catalog_items/sku-lookup:
    post:
      tags:
        - Catalog Items
      operationId: lookupCatalogItemBySku
      summary: Look up catalog items by SKU
      description: >-
        Fast exact-SKU lookup within a catalog. Returns a lightweight
        projection; use *Get a catalog item* for the full record.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SkuLookupRequest'
      responses:
        '200':
          description: Matching items (empty array when none).
          content:
            application/json:
              schema:
                type: object
                properties:
                  catalog_items:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        sku:
                          type: string
                          nullable: true
                        description:
                          type: string
                          nullable: true
                  resource:
                    type: string
                    example: catalog_items
                required:
                  - catalog_items
                  - resource
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/{catalogGuid}/catalogItems:
    get:
      tags:
        - Catalog Items
      operationId: listCatalogItemsLegacy
      summary: List catalog items (legacy path)
      deprecated: true
      description: >-
        Legacy alias of `GET /v1/catalog/{catalogGuid}/catalog_items`. Same
        parameters and response; use the new path.
      parameters:
        - $ref: '#/components/parameters/CatalogGuidPath'
        - $ref: '#/components/parameters/VendorGuidHeader'
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Offset'
        - $ref: '#/components/parameters/LastUpdatedAt'
        - in: query
          name: skipTotalCount
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
        - in: query
          name: skipCategoryRetrieval
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
        - in: query
          name: includeAttributes
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
      responses:
        '200':
          description: A page of catalog items.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CatalogItemsPage'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/catalog/{catalogGuid}/price_groups:
    get:
      tags:
        - Price Groups
      operationId: listPriceGroups
      summary: List price groups
      description: >-
        Returns the price groups defined on a catalog. `name` is the key used in
        each catalog item's `pricing` object.
      parameters:
        - $ref: '#/components/parameters/CatalogGuidPath'
      responses:
        '200':
          description: The catalog's price groups.
          content:
            application/json:
              schema:
                type: object
                properties:
                  priceGroups:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        guid:
                          type: string
                          format: uuid
                        name:
                          type: string
                          example: Wholesale
                        created_at:
                          type: string
                          format: date-time
                        updated_at:
                          type: string
                          format: date-time
                required:
                  - priceGroups
        '400':
          description: Unknown catalog GUID (plain-text body `Invalid Catalog Guid`).
          content:
            text/plain:
              schema:
                type: string
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/orders:
    get:
      tags:
        - Orders
      operationId: listOrdersApi
      summary: List orders
      description: >
        Paged list of the supplier's orders, newest first, with a reduced
        projection of each order and its lines

        (`Order_Items` carry `id`, `item_no`, `qty`, `note` and the item's `id`,
        `name`, `sku`).


        **API key and secret only.** Requests without `x-apiKey` / `x-apiSecret`
        are rejected with a plain-text `400`.
      security:
        - ApiKey: []
          ApiSecret: []
      parameters:
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Offset'
        - in: query
          name: from_updated_at
          schema:
            type: string
          description: >-
            Return only orders updated at or after this UTC timestamp
            (`YYYY-MM-DD HH:mm:ss` or ISO-8601).
          example: '2026-09-01 00:00:00'
        - in: query
          name: name
          schema:
            type: string
          description: Filter by order number (contains match).
        - in: query
          name: guid
          schema:
            type: string
            format: uuid
          description: Return the single order with this GUID.
      responses:
        '200':
          description: A page of orders.
          content:
            application/json:
              schema:
                type: object
                properties:
                  orders:
                    type: array
                    items:
                      $ref: '#/components/schemas/Order'
                  count:
                    type: integer
                    description: Number of orders in this page (not the total).
                required:
                  - orders
                  - count
        '400':
          description: Missing API key or secret (plain-text body `Invalid API Payload`).
          content:
            text/plain:
              schema:
                type: string
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/orders/list:
    get:
      tags:
        - Orders
      operationId: listOrders
      summary: List orders (filtered)
      description: >
        Paged, filterable order list used by the Orderwerks web app. Supplier
        users see all of the supplier's orders;

        customer users see their own.


        Accepts user session headers only. Integrators should use `GET
        /v1/orders`.
      security:
        - UserGuid: []
          UserToken: []
          SupplierGuid: []
      parameters:
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Offset'
        - in: query
          name: includePercentageFillable
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
          description: >-
            Compute `percentageFillable` per order from current inventory
            (slower).
        - in: query
          name: queryString
          schema:
            type: string
          description: >-
            URL-encoded filter string as built by the web app, e.g.
            `filter_shipped=true&is_quote=0`. Individual filter keys may also be
            passed as top-level query parameters.
      responses:
        '200':
          description: A page of orders.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  orders:
                    type: array
                    items:
                      $ref: '#/components/schemas/Order'
                  totalOrders:
                    type: integer
                  resource:
                    type: string
                    example: order
                required:
                  - success
                  - orders
                  - totalOrders
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/orders/{orderGuid}:
    get:
      tags:
        - Orders
      operationId: getOrder
      summary: Get an order
      description: >-
        Returns the full order with its lines, addresses, customer, state
        history and related records, plus any related orders (backorders, parent
        order).
      parameters:
        - $ref: '#/components/parameters/OrderGuidPath'
        - $ref: '#/components/parameters/VendorGuidHeader'
      responses:
        '200':
          description: The order.
          content:
            application/json:
              schema:
                type: object
                properties:
                  order:
                    $ref: '#/components/schemas/Order'
                  relatedOrders:
                    type: array
                    items:
                      $ref: '#/components/schemas/Order'
                required:
                  - order
                  - relatedOrders
        '401':
          description: >-
            Invalid credentials (plain-text body `Invalid API Key or Secret` or
            `Invalid Headers`).
          content:
            text/plain:
              schema:
                type: string
        '500':
          $ref: '#/components/responses/InternalError'
    put:
      tags:
        - Orders
      operationId: updateOrder
      summary: Update an order
      description: >
        Partial update of an order's header fields. Rejected with `403` when the
        order's current workflow step is

        read-only for the caller's user type.


        Accepts user session headers only.
      security:
        - UserGuid: []
          UserToken: []
          SupplierGuid: []
      parameters:
        - $ref: '#/components/parameters/OrderGuidPath'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateOrderRequest'
            example:
              po_no: PO-77812
              note: Deliver to the rear dock.
      responses:
        '200':
          description: The updated order.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Order'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: >-
            Insufficient access, or the order is read-only at its current
            workflow step (`currentStep` and `stepNumber` included).
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: false
                  message:
                    type: string
                  currentStep:
                    type: string
                  stepNumber:
                    type: integer
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'
  /v2/order:
    post:
      tags:
        - Orders
      operationId: createOrderV2
      summary: Create an order
      description: >
        Creates an order with its lines for an existing customer and, unless
        `remainInPreliminary` is true, submits it

        into the supplier's workflow. This is the recommended endpoint for
        integrations.


        **API key and secret only.** The order is attributed to the supplier's
        master user. Requests without

        `x-apiKey` / `x-apiSecret` are rejected with a plain-text `400`.
      security:
        - ApiKey: []
          ApiSecret: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateOrderV2Request'
            example:
              vendorGuid: 2b7c1d9e-3f4a-4b5c-8d6e-7f8091a2b3c4
              catalogGuid: 0f5a4b1e-1c9c-4d1a-9b8e-6f4a2a3c1d10
              priceGroupGuid: 9c8b7a6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d
              order:
                po_no: PO-77812
                note: Deliver to the rear dock.
                shipping_instructions: Call on arrival
              orderItems:
                - catalog_item_guid: 7a1d2e3f-4b5c-4d6e-8f90-a1b2c3d4e5f6
                  qty: 12
                - catalog_item_guid: 1f2e3d4c-5b6a-4978-8a9b-0c1d2e3f4a5b
                  qty: 2
                  note: Gift wrap
              shipTo:
                name: Receiving
                company_name: Acme, Inc.
                address_line_one: 400 Warehouse Road
                city: Anytown
                state: CA
                postal_code: '12345'
                country: US
              source: OTHER
      responses:
        '200':
          description: The created order.
          content:
            application/json:
              schema:
                type: object
                properties:
                  order:
                    $ref: '#/components/schemas/Order'
                required:
                  - order
        '400':
          description: >-
            Missing API key or secret, or the customer could not be resolved
            (plain-text body).
          content:
            text/plain:
              schema:
                type: string
                enum:
                  - Invalid API Payload
                  - Error Locating Account
                  - Error Setting Up Order Accounts
        '401':
          description: >-
            The API key's user may not order for this customer (plain-text body
            `Invalid Access`).
          content:
            text/plain:
              schema:
                type: string
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/orderWithItems:
    post:
      tags:
        - Orders
      operationId: createOrderWithItems
      summary: Create an order (with optional new customer)
      description: >
        Creates an order with its lines, optionally creating the customer in the
        same call (`newVendor*` fields).

        Used by the Orderwerks mobile sales app; also available to integrators
        with an API key.


        Before anything is written the request is validated: the customer must
        be active and accessible, and every

        line's item must be active with enough inventory. Failures come back as
        `400` with a `ReconcileErrors` body.


        Idempotent on `order.api_guid`: a retry with the same key returns the
        existing order (and the customer /

        address / contact references) instead of creating a duplicate.
      parameters:
        - $ref: '#/components/parameters/VendorGuidHeader'
        - $ref: '#/components/parameters/UserGuidHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateOrderWithItemsRequest'
            example:
              catalogGuid: 0f5a4b1e-1c9c-4d1a-9b8e-6f4a2a3c1d10
              priceGroupGuid: 9c8b7a6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d
              order:
                api_guid: 4c0d3e2a-8f7b-4c1e-9a6d-0b1c2d3e4f5a
                po_no: PO-77812
              orderItems:
                - catalog_item_id: 10432
                  qty: 6
              newVendor:
                name: New Retailer LLC
                email: buyer@newretailer.example
              newVendorShipTo:
                name: Receiving
                address_line_one: 1 Main St
                city: Anytown
                state: CA
                postal_code: '12345'
                country: US
      responses:
        '200':
          description: The created (or matched) order.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateOrderWithItemsResponse'
        '400':
          description: Validation failed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReconcileErrors'
        '401':
          description: Missing credentials or no access to the customer.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  isValid:
                    type: boolean
                    example: false
        '500':
          description: >-
            Unexpected error. `noAccountAccess` / `inactiveAccount` are set when
            that was the cause.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errMessage:
                    type: string
                  noAccountAccess:
                    type: boolean
                  inactiveAccount:
                    type: boolean
                  isValid:
                    type: boolean
                    example: false
  /v1/order:
    post:
      tags:
        - Orders
      operationId: createOrderV1
      summary: Create an empty order (legacy)
      description: >
        Creates an order header for the customer given in the `vendorGuid`
        header, without lines. Lines are added

        afterwards through the order-entry screens. Prefer `POST /v2/order` or
        `POST /v1/orderWithItems`.


        Accepts user session headers only. Requests without them are rejected
        with a plain-text `400`.
      security:
        - UserGuid: []
          UserToken: []
          SupplierGuid: []
      parameters:
        - $ref: '#/components/parameters/VendorGuidHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateOrderV1Request'
      responses:
        '200':
          description: The created order.
          content:
            application/json:
              schema:
                type: object
                properties:
                  order:
                    $ref: '#/components/schemas/Order'
                required:
                  - order
        '400':
          description: >-
            Missing user session headers (plain-text body `Invalid API
            Payload`).
          content:
            text/plain:
              schema:
                type: string
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/order/submit:
    post:
      tags:
        - Orders
      operationId: submitOrder
      summary: Submit an order / advance its state
      description: >
        Moves an order to the next step of its workflow (or to `order_state_id`
        when given), reserving inventory and

        sending the step's notifications. Orders created through `POST
        /v2/order` are submitted automatically; use this

        for orders created with `remainInPreliminary: true` or by `POST
        /v1/order`.


        Accepts user session headers only.
      security:
        - UserGuid: []
          UserToken: []
          SupplierGuid: []
      parameters:
        - $ref: '#/components/parameters/VendorGuidHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubmitOrderRequest'
            example:
              orderGuid: 6d5c4b3a-2f1e-4d0c-9b8a-7f6e5d4c3b2a
              allowPartialFulfillment: true
      responses:
        '200':
          description: The order after the transition.
          content:
            application/json:
              schema:
                type: object
                properties:
                  order:
                    $ref: '#/components/schemas/Order'
                  autoFulfilledItems:
                    type: array
                    description: >-
                      Pending backorder lines that were fulfilled from stock
                      during a release transition.
                    items:
                      type: object
                      properties:
                        orderItemId:
                          type: integer
                        catalogItemName:
                          type: string
                        catalogItemSku:
                          type: string
                        qtyFulfilled:
                          type: number
                        qtyFromHeld:
                          type: number
                        qtyFromOnHand:
                          type: number
                required:
                  - order
        '400':
          description: >-
            Missing credentials or `orderGuid` (plain-text body `Invalid API
            Payload`).
          content:
            text/plain:
              schema:
                type: string
        '422':
          description: >-
            The transition is blocked (insufficient inventory, backorder limit,
            pending items on release, serials not assigned).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubmitOrderError'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  securitySchemes:
    ApiKey:
      type: apiKey
      in: header
      name: x-apiKey
      description: Supplier API key. Always sent together with `x-apiSecret`.
    ApiSecret:
      type: apiKey
      in: header
      name: x-apiSecret
      description: Supplier API secret. Always sent together with `x-apiKey`.
    UserGuid:
      type: apiKey
      in: header
      name: userGuid
      description: GUID of the authenticated user (user session headers).
    UserToken:
      type: apiKey
      in: header
      name: userToken
      description: JWT issued to the user at login (user session headers).
    SupplierGuid:
      type: apiKey
      in: header
      name: supplierGuid
      description: >-
        GUID of the supplier account the user is acting in (user session
        headers).
  parameters:
    VendorGuidHeader:
      in: header
      name: vendorGuid
      required: false
      description: >-
        GUID of the customer (vendor) to act for. With API key authentication
        this selects the customer context; with user session headers it is the
        vendor the user is acting on behalf of.
      schema:
        type: string
        format: uuid
    UserGuidHeader:
      in: header
      name: userGuid
      required: false
      description: >-
        With API key authentication only: run the request as this user instead
        of the supplier's master user (the order is attributed to them). Ignored
        when user session headers are used, where it is part of the credentials.
      schema:
        type: string
        format: uuid
    Limit:
      in: query
      name: limit
      required: false
      description: Number of rows per page.
      schema:
        type: integer
        minimum: 1
        maximum: 100
        default: 25
    Offset:
      in: query
      name: offset
      required: false
      description: Zero-based **page number**. The server skips `offset * limit` rows.
      schema:
        type: integer
        minimum: 0
        default: 0
    LastUpdatedAt:
      in: query
      name: lastUpdatedAt
      required: false
      description: >-
        Delta-sync cursor. Pass the `serverTimestamp` returned by the previous
        call to receive only rows created, updated or soft-deleted since then
        (deleted rows carry `deleted_at`). Accepts ISO-8601
        (`2026-09-01T14:00:00.000Z`) or `YYYY-MM-DD HH:mm:ss` (treated as UTC).
        The server re-fetches a 60-second overlap window to absorb clock skew.
        An unparsable value returns `400` with `code: INVALID_DELTA_CURSOR`.
      schema:
        type: string
        example: '2026-09-01T14:00:00.000Z'
    CatalogGuidPath:
      in: path
      name: catalogGuid
      required: true
      description: GUID of the catalog. Must belong to the authenticated supplier.
      schema:
        type: string
        format: uuid
    CatalogItemGuidPath:
      in: path
      name: catalogItemGuid
      required: true
      description: GUID of the catalog item.
      schema:
        type: string
        format: uuid
    VendorGuidPath:
      in: path
      name: vendorGuid
      required: true
      description: GUID of the customer (vendor).
      schema:
        type: string
        format: uuid
    OrderGuidPath:
      in: path
      name: orderGuid
      required: true
      description: GUID of the order.
      schema:
        type: string
        format: uuid
  responses:
    BadRequest:
      description: >-
        The request is malformed or references a resource the supplier does not
        own (for example an unknown catalog GUID).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Missing or invalid credentials.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            message: Unauthorized
    Forbidden:
      description: >-
        The credentials are valid but the user lacks the access level this
        endpoint requires.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            message: Forbidden
    NotFound:
      description: No resource with that GUID is visible to the authenticated supplier.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    InternalError:
      description: >-
        Unexpected server error. Some legacy endpoints return the message as
        `text/plain` instead of JSON.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
        text/plain:
          schema:
            type: string
  schemas:
    Error:
      type: object
      properties:
        message:
          type: string
          description: Human-readable error message.
          example: Invalid Catalog GUID
        error:
          type: string
          description: Underlying error detail, when available.
        code:
          type: string
          description: >-
            Machine-readable code for specific failures (for example
            `INVALID_DELTA_CURSOR`).
      required:
        - message
    EntityRef:
      type: object
      description: >-
        Minimal reference to a created record, so a client can back-fill its
        local rows.
      properties:
        id:
          type: integer
          example: 4821
        guid:
          type: string
          format: uuid
      required:
        - id
        - guid
    Address:
      type: object
      description: >-
        A billing or shipping address. Additional internal fields may be
        present.
      properties:
        id:
          type: integer
        guid:
          type: string
          format: uuid
        vendor_id:
          type: integer
          nullable: true
        order_id:
          type: integer
          nullable: true
        name:
          type: string
          description: Contact name at this address.
        company_name:
          type: string
        address_line_one:
          type: string
        address_line_two:
          type: string
        address_line_three:
          type: string
        city:
          type: string
        state:
          type: string
        postal_code:
          type: string
        country:
          type: string
        phone:
          type: string
        fax:
          type: string
        email:
          type: string
        note:
          type: string
        address_internal_id:
          type: string
          description: Your own identifier for this address, if one was supplied.
        is_vendor_main_ship_to:
          type: boolean
        verified:
          type: boolean
          description: True when the address was verified against a postal database.
        lat:
          type: number
          nullable: true
        lng:
          type: number
          nullable: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    AddressInput:
      type: object
      description: Address fields accepted when creating or updating an address.
      properties:
        name:
          type: string
          description: Contact name at this address.
          example: Jane Doe
        company_name:
          type: string
          example: Acme, Inc.
        address_line_one:
          type: string
          example: 123 Any Street
        address_line_two:
          type: string
          example: Unit A
        address_line_three:
          type: string
        city:
          type: string
          example: Anytown
        state:
          type: string
          example: CA
        postal_code:
          type: string
          example: '12345'
        country:
          type: string
          example: US
        phone:
          type: string
        fax:
          type: string
        email:
          type: string
        note:
          type: string
        address_internal_id:
          type: string
          description: Your own identifier for this address.
    Vendor:
      type: object
      description: >-
        A customer of the supplier. The full model includes many
        integration-specific fields (QuickBooks, Stripe, FastBound, routing);
        only the commonly used ones are listed here.
      properties:
        id:
          type: integer
        guid:
          type: string
          format: uuid
        supplier_id:
          type: integer
        parent_vendor_id:
          type: integer
          nullable: true
        customer_internal_id:
          type: string
          nullable: true
          description: Your own identifier for this customer.
        name:
          type: string
        email:
          type: string
        shipping_email:
          type: string
          nullable: true
        phone:
          type: string
          nullable: true
        cell:
          type: string
          nullable: true
        fax:
          type: string
          nullable: true
        address_line_one:
          type: string
          nullable: true
        address_line_two:
          type: string
          nullable: true
        city:
          type: string
          nullable: true
        state:
          type: string
          nullable: true
        postal_code:
          type: string
          nullable: true
        country:
          type: string
          nullable: true
        active:
          type: boolean
        tax_exempt:
          type: boolean
        resale_tax_id:
          type: string
          nullable: true
        lock_catalog_id:
          type: integer
          nullable: true
          description: When set, the customer can only order from this catalog.
        price_group_id:
          type: integer
          nullable: true
          description: Price group used for this customer's pricing.
        payment_type_id:
          type: integer
          nullable: true
        payment_term_id:
          type: integer
          nullable: true
        require_payment:
          type: boolean
        credit_limit:
          type: number
          nullable: true
        open_balance:
          type: number
          nullable: true
        is_ecomm_user:
          type: boolean
          description: True for Orderwerks Online (e-commerce) customers.
        net_term_ecomm_user:
          type: boolean
        require_po:
          type: boolean
        standing_po:
          type: string
          nullable: true
        hide_pricing:
          type: boolean
        currency_id:
          type: integer
          nullable: true
        notes:
          type: string
          nullable: true
        default_order_category_id:
          type: integer
          nullable: true
        route_id:
          type: integer
          nullable: true
        timezone:
          type: string
          nullable: true
        bill_to_id:
          type: integer
          nullable: true
        ship_to_id:
          type: integer
          nullable: true
        Bill_To:
          $ref: '#/components/schemas/Address'
        Ship_To:
          $ref: '#/components/schemas/Address'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        deleted_at:
          type: string
          format: date-time
          nullable: true
          description: Present only in delta-sync responses for soft-deleted customers.
    VendorInput:
      type: object
      description: Customer fields accepted on create.
      properties:
        name:
          type: string
          example: Acme, Inc.
        email:
          type: string
          example: orders@acme.example
        customer_internal_id:
          type: string
          description: >-
            Your own identifier for this customer. Used for idempotent matching
            by some integrations.
        phone:
          type: string
        cell:
          type: string
        fax:
          type: string
        shipping_email:
          type: string
        address_line_one:
          type: string
        address_line_two:
          type: string
        city:
          type: string
        state:
          type: string
        postal_code:
          type: string
        country:
          type: string
        active:
          type: boolean
          default: true
        tax_exempt:
          type: boolean
        resale_tax_id:
          type: string
        price_group_id:
          type: integer
        lock_catalog_id:
          type: integer
        payment_type_id:
          type: integer
        payment_term_id:
          type: integer
        require_payment:
          type: boolean
        require_po:
          type: boolean
        standing_po:
          type: string
        hide_pricing:
          type: boolean
        is_ecomm_user:
          type: boolean
        notes:
          type: string
        default_order_category_id:
          type: integer
        route_id:
          type: integer
      required:
        - name
    VendorContactInput:
      type: object
      properties:
        name:
          type: string
          example: Jane Doe
        email:
          type: string
        phone:
          type: string
        mobile:
          type: string
      required:
        - name
    VendorOptions:
      type: object
      description: >-
        Optional customer settings. All fields are optional; omitted fields are
        left unchanged.
      properties:
        active:
          type: boolean
        customer_internal_id:
          type: string
        lock_catalog_id:
          type: integer
          nullable: true
        price_group_id:
          type: integer
          nullable: true
        payment_type_id:
          type: integer
          nullable: true
        payment_term_id:
          type: integer
        require_payment:
          type: boolean
        credit_limit:
          type: number
        open_balance:
          type: number
          nullable: true
        tax_exempt:
          type: boolean
        tax_shipping:
          type: boolean
          nullable: true
        resale_tax_id:
          type: string
        is_ecomm_user:
          type: boolean
        net_term_ecomm_user:
          type: boolean
        require_po:
          type: boolean
        hide_pricing:
          type: boolean
        shipping_email:
          type: string
        default_shipping_instructions:
          type: string
        default_order_category_id:
          type: integer
        category_id:
          type: integer
        parent_vendor_id:
          type: integer
        currency_id:
          type: integer
        notes:
          type: string
        route_id:
          type: integer
        default_local_delivery:
          type: boolean
          nullable: true
        default_local_pickup:
          type: boolean
          nullable: true
        timezone:
          type: string
          nullable: true
        create_in_qbo:
          type: boolean
          description: Create the customer in QuickBooks Online after saving.
        create_in_qbd:
          type: boolean
          description: Queue the customer for creation in QuickBooks Desktop after saving.
    CreateVendorRequest:
      type: object
      description: >-
        Mirrors the `newVendor*` block accepted by `POST /v1/orderWithItems`.
        Idempotent on supplier + `newVendor.email`: a retry after a lost
        response returns the existing customer's references instead of creating
        a duplicate.
      properties:
        newVendor:
          $ref: '#/components/schemas/VendorInput'
        newVendorBillTo:
          $ref: '#/components/schemas/AddressInput'
        newVendorShipTo:
          $ref: '#/components/schemas/AddressInput'
        newVendorContact:
          $ref: '#/components/schemas/VendorContactInput'
        newVendorNote:
          type: string
          description: Free-text account note stored against the new customer.
        source:
          type: string
          description: Origin of the record (for example `APP`). Stored for reporting only.
      required:
        - newVendor
    CreateVendorResponse:
      type: object
      description: >-
        The `billTo`, `shipTo`, `contact` and `note` references are present only
        when that record was created (or matched on a retry).
      properties:
        vendor:
          $ref: '#/components/schemas/Vendor'
        billTo:
          $ref: '#/components/schemas/EntityRef'
        shipTo:
          $ref: '#/components/schemas/EntityRef'
        contact:
          $ref: '#/components/schemas/EntityRef'
        note:
          $ref: '#/components/schemas/EntityRef'
      required:
        - vendor
    UpdateVendorRequest:
      type: object
      properties:
        name:
          type: string
        email:
          type: string
        billTo:
          $ref: '#/components/schemas/AddressInput'
        shipTo:
          $ref: '#/components/schemas/AddressInput'
        options:
          $ref: '#/components/schemas/VendorOptions'
        tokenOptions:
          type: object
          description: >-
            Connection-level settings for the customer's login (catalog / price
            group locks, discounts).
          properties:
            catalog_id:
              type: integer
              nullable: true
            price_group_id:
              type: integer
              nullable: true
            hide_pricing:
              type: boolean
            price_discount_one:
              type: number
              nullable: true
            price_discount_two:
              type: number
        shippingDetails:
          type: array
          description: >-
            Replaces the customer's saved shipping preferences (carrier /
            service defaults).
          items:
            type: object
            additionalProperties: true
        shippingAccounts:
          type: array
          description: Replaces the customer's third-party shipping accounts.
          items:
            type: object
            additionalProperties: true
      required:
        - name
        - email
    VendorConnection:
      type: object
      description: >-
        A supplier-to-customer connection row. Customer lists are returned as
        connections because a customer's catalog and price group locks live on
        the connection; the customer record itself is under `Vendor`.
      properties:
        id:
          type: integer
        guid:
          type: string
          format: uuid
        supplier_id:
          type: integer
        vendor_id:
          type: integer
        parent_vendor_id:
          type: integer
          nullable: true
        catalog_id:
          type: integer
          nullable: true
          description: Catalog the customer is locked to, if any.
        price_group_id:
          type: integer
          nullable: true
          description: Price group override on the connection, if any.
        hide_pricing:
          type: boolean
        price_discount_one:
          type: number
          nullable: true
        price_discount_two:
          type: number
          nullable: true
        is_master:
          type: boolean
        route_id:
          type: integer
          nullable: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        deleted_at:
          type: string
          format: date-time
          nullable: true
        Vendor:
          $ref: '#/components/schemas/Vendor'
        Price_Group:
          $ref: '#/components/schemas/PriceGroup'
    VendorListResponse:
      type: object
      properties:
        supplierVendorTokens:
          type: array
          items:
            $ref: '#/components/schemas/VendorConnection'
        totalVendors:
          type: integer
          description: Total matching customers across all pages.
        salesPeopleAssigned:
          type: array
          description: Sales rep assignments for the customers on this page.
          items:
            type: object
            properties:
              id:
                type: integer
              vendor_id:
                type: integer
              user_id:
                type: integer
              User:
                type: object
                properties:
                  id:
                    type: integer
                  guid:
                    type: string
                    format: uuid
                  name:
                    type: string
                  email:
                    type: string
        serverTimestamp:
          type: string
          format: date-time
          description: Pass back as `lastUpdatedAt` on the next call for delta sync.
      required:
        - supplierVendorTokens
        - totalVendors
    Catalog:
      type: object
      properties:
        id:
          type: integer
        guid:
          type: string
          format: uuid
        supplier_id:
          type: integer
        name:
          type: string
          example: Main Catalog
        email:
          type: string
          nullable: true
        version:
          type: string
          nullable: true
        active:
          type: boolean
        order_item_type_id:
          type: integer
        currency_id:
          type: integer
          nullable: true
        order_prefix_override:
          type: string
          nullable: true
          description: >-
            Prefix used for order numbers created from this catalog, if
            overridden.
        last_inventory_update:
          type: string
          format: date-time
          nullable: true
        Price_Groups:
          type: array
          items:
            $ref: '#/components/schemas/PriceGroup'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    PriceGroup:
      type: object
      properties:
        id:
          type: integer
        guid:
          type: string
          format: uuid
        catalog_id:
          type: integer
        value:
          type: string
          description: >-
            Price group name. This is the key used in a catalog item's `pricing`
            object.
          example: Wholesale
        is_main:
          type: boolean
        percentage:
          type: number
          nullable: true
        price_upcharge_type_id:
          type: integer
          nullable: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        deleted_at:
          type: string
          format: date-time
          nullable: true
    CatalogItem:
      type: object
      description: >-
        A product. With API key authentication the paged list endpoint returns
        exactly the fields below; other endpoints (and user session calls)
        return the full model, which has many more optional fields.
      properties:
        id:
          type: integer
        guid:
          type: string
          format: uuid
        catalog_id:
          type: integer
        category_id:
          type: integer
          nullable: true
        sku:
          type: string
        upc:
          type: string
          nullable: true
        name:
          type: string
        description:
          type: string
          nullable: true
        manufacturer:
          type: string
          nullable: true
        color:
          type: string
          nullable: true
        style:
          type: string
          nullable: true
        active:
          type: boolean
        is_taxable:
          type: boolean
        msrp:
          type: number
          nullable: true
        cost_per_uom:
          type: number
          nullable: true
          description: Supplier cost. Omitted for customer (vendor) users.
        pricing:
          type: object
          description: >-
            Price per price group, keyed by price group name. `"N/A"` means not
            offered to that group.
          additionalProperties:
            oneOf:
              - type: number
              - type: string
                enum:
                  - N/A
          example:
            Retail: 99.99
            Wholesale: 79.99
            Distributor: N/A
        has_inventory:
          type: boolean
          description: Whether stock is tracked for this item.
        qty_on_hand:
          type: number
        qty_incoming:
          type: number
        reserved_qty_on_hand:
          type: number
        qty_backordered:
          type: number
        qty_held_for_backorders:
          type: number
        min_qty_on_hand:
          type: number
          nullable: true
        max_qty_on_hand:
          type: number
          nullable: true
        min_order_qty:
          type: number
          nullable: true
        allow_backorder:
          type: boolean
        qty_break:
          type: number
          nullable: true
          description: Quantity at which `qty_break_price` applies.
        qty_break_price:
          type: number
          nullable: true
        has_serials:
          type: boolean
        has_lots:
          type: boolean
        has_exp_date:
          type: boolean
        width:
          type: number
          nullable: true
        height:
          type: number
          nullable: true
        depth:
          type: number
          nullable: true
        item_weight:
          type: number
          nullable: true
        shipping_weight:
          type: number
          nullable: true
        is_product_group:
          type: boolean
        product_group_type:
          type: string
          nullable: true
          enum:
            - flat
            - multi
            - null
        product_group_display_style:
          type: string
          nullable: true
        group_parent_catalog_item_id:
          type: integer
          nullable: true
        group_sequence:
          type: integer
          nullable: true
        group_title:
          type: string
          nullable: true
        subsection_id:
          type: integer
          nullable: true
        third_party_sku:
          type: string
          nullable: true
        third_party_pricing:
          type: string
          nullable: true
        third_party_size:
          type: string
          nullable: true
        Category:
          $ref: '#/components/schemas/Category'
        CategoryHierarchy:
          type: array
          description: Root-to-leaf category path, when category retrieval is not skipped.
          items:
            $ref: '#/components/schemas/Category'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        deleted_at:
          type: string
          format: date-time
          nullable: true
          description: Present only in delta-sync responses for soft-deleted items.
    Category:
      type: object
      properties:
        id:
          type: integer
        guid:
          type: string
          format: uuid
        catalog_id:
          type: integer
        parent_category_id:
          type: integer
          nullable: true
        name:
          type: string
        sequence:
          type: integer
          nullable: true
        hide_category:
          type: boolean
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    CatalogItemsPage:
      type: object
      properties:
        catalog_items:
          type: array
          items:
            $ref: '#/components/schemas/CatalogItem'
        totalCatalogItems:
          type: integer
          description: Total items in the catalog (0 when `skipTotalCount=true`).
        hasMoreItems:
          type: boolean
        resource:
          type: string
          example: catalog_items
        serverTimestamp:
          type: string
          format: date-time
          description: Pass back as `lastUpdatedAt` on the next call for delta sync.
      required:
        - catalog_items
        - totalCatalogItems
        - hasMoreItems
        - resource
    BatchRequest:
      type: object
      properties:
        type:
          type: string
          enum:
            - id
            - guid
          description: Whether `values` holds numeric ids or GUIDs.
        values:
          type: array
          minItems: 1
          items:
            oneOf:
              - type: integer
              - type: string
                format: uuid
      required:
        - type
        - values
      example:
        type: guid
        values:
          - 0f5a4b1e-1c9c-4d1a-9b8e-6f4a2a3c1d10
          - 7a1d2e3f-4b5c-4d6e-8f90-a1b2c3d4e5f6
    TypeaheadRequest:
      type: object
      description: >-
        Search filters. Only `name` is commonly needed; a 12-digit numeric
        `name` triggers a UPC lookup instead of a text search.
      properties:
        name:
          type: string
          description: >-
            Search term. Matches name, SKU and description. Empty string returns
            the first page of the catalog.
          example: widget
        limit:
          type: integer
          default: 10
        offset:
          type: integer
          default: 0
          description: Zero-based page number.
        priceGroupGuid:
          type: string
          format: uuid
          description: >-
            Return only items offered to this price group, with `pricing`
            reduced to that group's price.
        orderGuid:
          type: string
          format: uuid
          description: Use the price group of this order (alternative to `priceGroupGuid`).
        categoryGuid:
          type: string
          format: uuid
        categoryId:
          type: integer
        includeSubcategories:
          type: boolean
          description: With a category filter, also match items in its subcategories.
        onlyActive:
          type: boolean
        onlyWithSerials:
          type: boolean
        includeTotal:
          type: boolean
          description: Populate `totalCatalogItems` (costs an extra count query).
        includeKitItems:
          type: boolean
        includeAttributes:
          type: boolean
        includeOptions:
          type: boolean
        includeRootCategories:
          type: boolean
          description: Also return the catalog's root categories in `categories`.
        ignoreProductGroups:
          type: boolean
          description: Return individual items instead of their product groups.
        singleWildcard:
          type: boolean
          description: Match `PHRASE%` (prefix) instead of `%PHRASE%` (contains).
        priceRange:
          type: object
          properties:
            minPrice:
              type: number
            maxPrice:
              type: number
            priceField:
              type: string
              enum:
                - msrp
                - map
                - cost_per_uom
                - min_price
              description: >-
                Field to filter on when no price group is given. Defaults to
                `msrp`.
        options:
          type: object
          description: Field-level search switches and attribute filters.
          properties:
            searchName:
              type: boolean
            searchSku:
              type: boolean
            searchDescription:
              type: boolean
            searchUpc:
              type: boolean
            attributes:
              type: object
              description: >-
                Attribute name to required value (string, number, boolean, range
                object or list).
              additionalProperties: true
        state:
          type: string
          description: >-
            Opaque value echoed back in the response, for correlating concurrent
            requests.
    TypeaheadResponse:
      type: object
      properties:
        catalog_items:
          type: array
          items:
            $ref: '#/components/schemas/CatalogItem'
        totalCatalogItems:
          type: integer
        resource:
          type: string
          example: catalog_items
        offset:
          type: integer
          nullable: true
        state:
          type: string
        categories:
          type: array
          description: Root categories, when `includeRootCategories` was true.
          items:
            $ref: '#/components/schemas/Category'
      required:
        - catalog_items
        - resource
    SkuLookupRequest:
      type: object
      properties:
        catalogGuid:
          type: string
          format: uuid
        skuName:
          type: string
          description: Exact SKU to match (case-insensitive, trimmed).
          example: WIDGET-001
      required:
        - catalogGuid
        - skuName
    Order:
      type: object
      description: >-
        A sales order. `GET /v1/orders` returns a reduced projection (the header
        fields plus id/guid/name of each related record); the single-order and
        create endpoints return the full model with all relations.
      properties:
        id:
          type: integer
        guid:
          type: string
          format: uuid
        name:
          type: string
          description: Order number as displayed, e.g. `ABC-10000`.
        api_guid:
          type: string
          nullable: true
          description: >-
            Client-supplied idempotency key, when the order was created through
            the API.
        supplier_id:
          type: integer
        vendor_id:
          type: integer
          nullable: true
        user_id:
          type: integer
          nullable: true
        catalog_id:
          type: integer
          nullable: true
        price_group_id:
          type: integer
          nullable: true
        category_id:
          type: integer
          nullable: true
        parent_order_id:
          type: integer
          nullable: true
        client_id:
          type: integer
          nullable: true
        project_id:
          type: integer
          nullable: true
        sales_rep_id:
          type: integer
          nullable: true
        ship_to_id:
          type: integer
          nullable: true
        order_state_id:
          type: integer
          description: >-
            Current workflow state id (1 = PRELIMINARY, 2 = SUBMITTED, 8 =
            SHIPPED, 9 = COMPLETED, 23 = CANCELLED, ...).
        order_source_id:
          type: integer
          nullable: true
          description: Origin of the order (1 = ORDERWERKS, 20 = OTHER, 21 = APP, ...).
        po_no:
          type: string
          nullable: true
        invoice_no:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        note:
          type: string
          nullable: true
        internal_note:
          type: string
          nullable: true
        shipping_instructions:
          type: string
          nullable: true
        is_quote:
          type: boolean
        is_sample:
          type: boolean
        is_local_pickup:
          type: boolean
        is_local_delivery:
          type: boolean
        is_shipped:
          type: boolean
        partially_shipped:
          type: boolean
        is_on_hold:
          type: boolean
        is_cancelled:
          type: boolean
        sub_total:
          type: number
          nullable: true
        tax:
          type: number
          nullable: true
        shipping:
          type: number
          nullable: true
        labor:
          type: number
          nullable: true
        discount:
          type: number
          nullable: true
        discount_total:
          type: number
          nullable: true
        other:
          type: number
          nullable: true
        grand_total:
          type: number
          nullable: true
        delivery_date:
          type: string
          nullable: true
        ship_date:
          type: string
          nullable: true
        do_not_ship_before_date:
          type: string
          nullable: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        Order_Items:
          type: array
          items:
            $ref: '#/components/schemas/OrderItem'
        Ship_To:
          $ref: '#/components/schemas/Address'
        Vendor:
          $ref: '#/components/schemas/Vendor'
        Catalog:
          $ref: '#/components/schemas/Catalog'
        Price_Group:
          $ref: '#/components/schemas/PriceGroup'
        Category:
          $ref: '#/components/schemas/Category'
        Order_State:
          type: object
          properties:
            id:
              type: integer
            guid:
              type: string
              format: uuid
            name:
              type: string
        User:
          type: object
          description: User who created the order.
          properties:
            id:
              type: integer
            guid:
              type: string
              format: uuid
            name:
              type: string
            email:
              type: string
        Supplier:
          type: object
          properties:
            id:
              type: integer
            guid:
              type: string
              format: uuid
            name:
              type: string
            email:
              type: string
        Client:
          type: object
          nullable: true
          description: End client on behalf of whom the customer placed the order, if any.
          properties:
            id:
              type: integer
            guid:
              type: string
              format: uuid
            name:
              type: string
        Parent_Order:
          type: object
          nullable: true
          properties:
            id:
              type: integer
            guid:
              type: string
              format: uuid
            name:
              type: string
        Order_Detail:
          type: object
          nullable: true
          description: Supplier-specific extra fields.
          additionalProperties: true
        Order_State_Logs:
          type: array
          description: State transition history.
          items:
            type: object
            properties:
              created_at:
                type: string
                format: date-time
              User:
                type: object
                properties:
                  name:
                    type: string
                  email:
                    type: string
              Order_State:
                type: object
                properties:
                  name:
                    type: string
        Assigned_Users:
          type: array
          items:
            type: object
            properties:
              id:
                type: integer
              guid:
                type: string
                format: uuid
              name:
                type: string
              email:
                type: string
    OrderItem:
      type: object
      description: A line on an order. Additional internal fields may be present.
      properties:
        id:
          type: integer
        guid:
          type: string
          format: uuid
        order_id:
          type: integer
        catalog_item_id:
          type: integer
        catalog_item_guid:
          type: string
          format: uuid
        parent_order_item_id:
          type: integer
          nullable: true
        item_no:
          type: integer
          description: Line number within the order.
        sku:
          type: string
          nullable: true
        name:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        qty:
          type: number
          description: Quantity ordered. Never reduced by shipments.
        qty_shipped:
          type: number
          nullable: true
        qty_backordered:
          type: number
          nullable: true
        qty_pending:
          type: number
          nullable: true
        qty_reserved:
          type: number
          nullable: true
        is_manual_price:
          type: boolean
        list_price_frozen:
          type: number
          nullable: true
          description: Unit price captured when the line was created.
        net_price:
          type: number
          nullable: true
        discount:
          type: number
          nullable: true
        discount_total:
          type: number
          nullable: true
        tax:
          type: number
          nullable: true
        total:
          type: number
          nullable: true
        is_credit:
          type: boolean
        is_backordered:
          type: boolean
        note:
          type: string
          nullable: true
        width:
          type: number
          nullable: true
        height:
          type: number
          nullable: true
        depth:
          type: number
          nullable: true
        selected_options:
          type: array
          nullable: true
          items:
            type: object
            additionalProperties: true
        Catalog_Item:
          $ref: '#/components/schemas/CatalogItem'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    OrderInput:
      type: object
      description: Order header fields accepted on create.
      properties:
        api_guid:
          type: string
          description: >-
            Your idempotency key for this order (unique per supplier). A retry
            with the same value returns the existing order instead of creating a
            duplicate. Honored by `POST /v1/orderWithItems`.
          example: 4c0d3e2a-8f7b-4c1e-9a6d-0b1c2d3e4f5a
        name:
          type: string
          description: >-
            Override the generated order number. Leave unset to let Orderwerks
            assign one.
        po_no:
          type: string
          description: Customer purchase order number.
          example: PO-77812
        note:
          type: string
          description: Note visible to the customer.
        internal_note:
          type: string
          description: Note visible to supplier users only.
        description:
          type: string
        is_quote:
          type: boolean
          default: false
        is_sample:
          type: boolean
          default: false
        shipping_instructions:
          type: string
        is_local_pickup:
          type: boolean
        is_local_delivery:
          type: boolean
        shipping:
          type: number
          description: Manual shipping charge.
        do_not_ship_before_date:
          type: string
          format: date
        shipstation_carrierCode:
          type: string
        shipstation_serviceType:
          type: string
        shipstation_packageType:
          type: string
    OrderItemInput:
      type: object
      description: >-
        A line to add. Identify the product by `catalog_item_id` or
        `catalog_item_guid`.
      properties:
        catalog_item_id:
          type: integer
        catalog_item_guid:
          type: string
          format: uuid
        qty:
          type: number
          example: 12
        item_no:
          type: integer
          description: Line number. Assigned sequentially when omitted.
        price_group_id:
          type: integer
          description: Price the line from this price group instead of the order's.
        is_manual_price:
          type: boolean
          description: >-
            When true, `list_price_frozen` is used as the unit price instead of
            catalog pricing.
        list_price_frozen:
          type: number
          description: Manual unit price. Only honored when `is_manual_price` is true.
        note:
          type: string
        description:
          type: string
        name:
          type: string
        width:
          type: number
        height:
          type: number
        depth:
          type: number
        selected_options:
          type: array
          description: Chosen item options for configurable products.
          items:
            type: object
            additionalProperties: true
        itemOptionValues:
          type: array
          items:
            type: object
            properties:
              item_option_id:
                type: integer
              value:
                description: Option value; type depends on the option.
      required:
        - qty
    CreateOrderV2Request:
      type: object
      properties:
        vendorGuid:
          type: string
          format: uuid
          description: Customer placing the order.
        catalogGuid:
          type: string
          format: uuid
        priceGroupGuid:
          type: string
          format: uuid
        order:
          $ref: '#/components/schemas/OrderInput'
        orderItems:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/OrderItemInput'
        orderDetails:
          type: object
          description: Supplier-specific extra order fields.
          additionalProperties: true
        shipTo:
          $ref: '#/components/schemas/AddressInput'
        client:
          type: object
          description: >-
            End client the customer is ordering for. Creates a client record
            linked to the order.
          properties:
            name:
              type: string
            email:
              type: string
            phone:
              type: string
          required:
            - name
        source:
          description: >-
            Order source, as a name (`OTHER`, `APP`, `SHOPIFY`, ...) or its
            numeric id.
          oneOf:
            - type: string
            - type: integer
          example: OTHER
        remainInPreliminary:
          type: boolean
          default: false
          description: >-
            When true the order stays in PRELIMINARY instead of being submitted
            into the workflow.
      required:
        - vendorGuid
        - catalogGuid
        - priceGroupGuid
        - order
        - orderItems
    CreateOrderWithItemsRequest:
      type: object
      description: >-
        Either act for an existing customer (send the `vendorGuid` header) or
        create one inline with the `newVendor*` fields, in which case the
        `vendorGuid` header is ignored.
      properties:
        catalogGuid:
          type: string
          format: uuid
        priceGroupGuid:
          type: string
          format: uuid
        order:
          $ref: '#/components/schemas/OrderInput'
        orderItems:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/OrderItemInput'
        orderDetails:
          type: object
          description: Supplier-specific extra order fields.
          additionalProperties: true
        shipTo:
          $ref: '#/components/schemas/AddressInput'
        source:
          description: Order source, as a name (`OTHER`, `APP`, ...) or its numeric id.
          oneOf:
            - type: string
            - type: integer
        workflowGuid:
          type: string
          format: uuid
          description: >-
            Workflow to run the order through, for suppliers with multiple
            workflows. Defaults to the supplier's default workflow.
        newVendor:
          $ref: '#/components/schemas/VendorInput'
        newVendorBillTo:
          $ref: '#/components/schemas/AddressInput'
        newVendorShipTo:
          $ref: '#/components/schemas/AddressInput'
        newVendorContact:
          $ref: '#/components/schemas/VendorContactInput'
        newVendorNote:
          type: string
        remainInPreliminary:
          type: boolean
          description: >-
            When true the order stays in PRELIMINARY. When omitted, the supplier
            setting "remain in preliminary" decides; when false the order is
            submitted.
        utm:
          type: object
          description: UTM attribution captured by the client, stamped onto the order.
          additionalProperties:
            type: string
      required:
        - catalogGuid
        - priceGroupGuid
        - order
        - orderItems
    CreateOrderWithItemsResponse:
      type: object
      description: >-
        The `vendor`, `billTo`, `shipTo`, `contact` and `note` fields are
        present only when the request created (or matched) that record.
      properties:
        order:
          $ref: '#/components/schemas/Order'
        vendor:
          $ref: '#/components/schemas/Vendor'
        billTo:
          $ref: '#/components/schemas/EntityRef'
        shipTo:
          $ref: '#/components/schemas/EntityRef'
        contact:
          $ref: '#/components/schemas/EntityRef'
        note:
          $ref: '#/components/schemas/EntityRef'
      required:
        - order
    CreateOrderV1Request:
      type: object
      description: >-
        Creates an empty order header. Lines are added afterwards through the
        order-entry endpoints or the web app.
      properties:
        catalogGuid:
          type: string
          format: uuid
        priceGroupGuid:
          type: string
          format: uuid
        api_guid:
          type: string
          description: Your idempotency key for this order.
        po_no:
          type: string
        note:
          type: string
        internal_note:
          type: string
        description:
          type: string
        is_quote:
          type: boolean
        is_sample:
          type: boolean
        is_template:
          type: boolean
        category_id:
          type: integer
        project_id:
          type: integer
        shipping_instructions:
          type: string
        is_local_pickup:
          type: boolean
        is_local_delivery:
          type: boolean
        is_dropship:
          type: boolean
        shipping:
          type: number
        tax:
          type: number
        workflow_id:
          type: integer
        allow_substitutions:
          type: boolean
        allow_backorders:
          type: boolean
        do_not_ship_before_date:
          type: string
          format: date
        cancel_date:
          type: string
          format: date
        tags:
          type: array
          items:
            type: integer
        orderDetails:
          type: object
          additionalProperties: true
    UpdateOrderRequest:
      type: object
      description: >-
        Partial update; only supplied fields change. The order must not be
        read-only at its current workflow step for the caller's user type.
      properties:
        name:
          type: string
        po_no:
          type: string
        note:
          type: string
        internal_note:
          type: string
        invoice_no:
          type: string
        vendor_id:
          type: integer
        catalog_id:
          type: integer
        price_group_id:
          type: integer
          nullable: true
        project_id:
          type: integer
        client_id:
          type: integer
        is_sample:
          type: boolean
        is_on_hold:
          type: boolean
        is_cancelled:
          type: boolean
        is_local_delivery:
          type: boolean
        shipping:
          type: number
        clear_manual_shipping_fee:
          type: boolean
        labor:
          type: number
        price_adjustment:
          type: number
        discount:
          type: number
        discount_type_id:
          type: integer
        tax_rate_override:
          type: number
          nullable: true
        Ship_To:
          $ref: '#/components/schemas/AddressInput'
        save_address_to_vendor:
          type: boolean
          description: Also save `Ship_To` as the customer's default shipping address.
        shipping_warehouse_id:
          type: integer
        workflow_id:
          type: integer
          nullable: true
        allow_substitutions:
          type: boolean
        allow_backorders:
          type: boolean
        approve_decline:
          type: string
          nullable: true
          enum:
            - APPROVE
            - DECLINE
            - null
          description: Approve or decline a quote.
        tags:
          type: array
          nullable: true
          items:
            type: integer
        do_not_ship_before_date:
          type: string
          format: date
          nullable: true
        cancel_date:
          type: string
          format: date
          nullable: true
        assignedUsers:
          type: array
          items:
            type: object
            properties:
              guid:
                type: string
                format: uuid
        details:
          type: object
          description: Supplier-specific extra order fields.
          additionalProperties: true
    SubmitOrderRequest:
      type: object
      properties:
        orderGuid:
          type: string
          format: uuid
        order_state_id:
          type: integer
          description: >-
            Target workflow state. Defaults to the next step in the order's
            workflow.
        stateChangeNote:
          type: string
          description: Note shown to the customer with the state change.
        stateChangeInternalNote:
          type: string
        skipInventoryCheck:
          type: boolean
        allowPartialFulfillment:
          type: boolean
          description: >-
            When true, reserve what is available and auto-create a backorder for
            the rest. When false, backorder the whole order if anything is
            short. When omitted, allocate what is available without creating a
            backorder.
        useHeldInventory:
          type: boolean
          description: Draw from inventory held for backorders before on-hand stock.
        skipPendingItemsCheck:
          type: boolean
        pendingItemsAction:
          type: string
          enum:
            - backorder
            - remove
            - zero_out
          description: >-
            What to do with pending backorder lines when moving into a release
            state.
        customMessage:
          type: string
          description: Custom text merged into the outbound email for steps that allow it.
      required:
        - orderGuid
    ReconcileErrors:
      type: object
      description: Returned with `400` when the order cannot be created as requested.
      properties:
        isValid:
          type: boolean
          example: false
        inactiveAccount:
          type: boolean
          description: The customer account is inactive.
        noAccountAccess:
          type: boolean
          description: The caller may not order for this customer.
        message:
          type: string
        errors:
          type: array
          description: One entry per line that failed validation.
          items:
            type: object
            properties:
              sku:
                type: string
              name:
                type: string
              active:
                type: boolean
              inventoryAvailable:
                type: number
      required:
        - isValid
        - errors
    SubmitOrderError:
      type: object
      description: Returned with `422` when the order cannot move to the requested state.
      properties:
        success:
          type: boolean
          example: false
        errorType:
          type: string
          description: Present for `PendingItemsOnRelease` and `SerialsNotAssigned`.
          enum:
            - PendingItemsOnRelease
            - SerialsNotAssigned
        message:
          type: string
        items:
          type: array
          description: The lines that blocked the transition.
          items:
            type: object
            additionalProperties: true
      required:
        - success
        - message
